1. Overview
The Protocol Buffer (protobuf) data format helps us transfer structured data over a network. It’s independent of any programming language and has an implementation for most programming languages, including Java.
The protobuf Timestamp type represents a point in time, independent of any specific time zone. Time is a crucial component in computing, and there may be a case in which we need to convert the protobuf Timestamp to a Java time instance, such as LocalDate, to seamlessly integrate it into an existing Java codebase.
In this tutorial, we’ll explore the process of converting a protobuf Timestamp instance to the LocalDate type, enabling us to work with protobuf data more efficiently within Java applications.
2. Maven Dependency
To create an instance of Timestamp or make use of code generated from .proto file, we need to add protobuf-java dependency to the pom.xml:
<dependency>
<groupId>com.google.protobuf</groupId>
<artifactId>protobuf-java</artifactId>
<version>4.26.1</version>
</dependency>
The dependency provides a Timestamp class and other protobuf-related classes.
3. The Timestamp Class
The protobuf Timestamp class represents a point in time since the Unix epoch. The time zone or the local calendar does not influence it.
It’s represented as a count of seconds and nanoseconds at a point in time. Let’s see an example that computes the current Timestamp by using a Java Instant object:
Instant currentTimestamp = Instant.now();
Timestamp timestamp = Timestamp.newBuilder()
.setSeconds(currentTimestamp.getEpochSecond())
.setNanos(currentTimestamp.getNano())
.build();
In the code above, we compute the Timestamp from the Instant object. First, we create an Instant object that represents date and time at a given point. Next, we extract the seconds and nanoseconds and pass them to the Timestamp instance.
4. Convert Timestamp Instance to LocalDate
When converting from Timestamp to LocalDate, it’s crucial to consider the time zone and its associated offset from UTC to accurately represent the local date. To convert Timestamp to LocalDate, let’s start by creating a Timestamp instance with a specific set of seconds and nanoseconds:
Timestamp ts = Timestamp.newBuilder()
.setSeconds(1000000)
.setNanos(77886600)
.build();
Since the Instant class is the most suitable representation for a point in time, let’s create a method that accepts the Timestamp as an argument and converts it to LocalDate:
LocalDate convertToLocalDate(Timestamp timestamp) {
Instant instant = Instant.ofEpochSecond(timestamp.getSeconds(), timestamp.getNanos());
LocalDate time = instant.atZone(ZoneId.of("America/Montreal")).toLocalDate();
return time;
}
In the code above, we create an Instant object from the Timestamp by using the ofEpochSecond() method, which takes the seconds and nanoseconds from the Timestamp as an argument.
Then, we convert the Instant object to LocalDate by using the atZone() method, which allows us to specify the time zone. This is essential because it ensures the resulting LocalDate reflects the time zone offset.
Notably, we can also use our default system time zone:
LocalDate time = instant.atZone(ZoneId.systemDefault()).toLocalDate();
Let’s write a unit test to assert the logic:
@Test
void givenTimestamp_whenConvertedToLocalDate_thenSuccess() {
Timestamp timestamp = Timestamp.newBuilder()
.setSeconds(1000000000)
.setNanos(778866000)
.build();
LocalDate time = TimestampToLocalDate.convertToLocalDate(timestamp);
assertEquals(LocalDate.of(2001, 9, 9), time);
}
In the code above, we assert that the LocalDate from the conversion matches the expected result.
5. Conclusion
In this tutorial, we learned how to convert from Timestamp to LocalDate by converting to Instant to represent a point in time. Also, we converted an Instance object to a LocalDate type by setting the time zone to deal with possible offset.
As always, the full source code for the example is available over on GitHub.