I built a small function to convert a TimeStamp into a LocalDate, and stumbled upon strange behaviour. Here is the code:
import java.sql.Timestamp;
import java.time.Instant;
import java.time.LocalDate;
import java.time.ZoneId;
import java.time.ZonedDateTime;
public class Test {
private static void convert(long seconds) {
System.out.printf("At %d seconds%n", seconds);
Timestamp t = new Timestamp(seconds * 1000L);
System.out.format("Timestamp: %s%n", t);
Instant i = t.toInstant();
System.out.format("Instant: %s%n", i);
ZonedDateTime atZone = i.atZone(ZoneId.systemDefault());
System.out.format("at Zone: %s%n", atZone);
LocalDate localDate = atZone.toLocalDate();
System.out.format("LocalDate: %s%n", localDate);
}
}
My local timezone is Europe/Berlin. Now, when calling this for Timestamp 0, I get the correct result:
At 0 seconds
Timestamp: 1970-01-01 01:00:00.0
Instant: 1970-01-01T00:00:00Z
at Zone: 1970-01-01T01:00+01:00[Europe/Berlin]
LocalDate: 1970-01-01
Everything is as expected. But when I call it with a date in the year 1, it fails my expectations:
At -62135769600 seconds
Timestamp: 0001-01-01 01:00:00.0
Instant: 0000-12-30T00:00:00Z
at Zone: 0000-12-30T00:53:28+00:53:28[Europe/Berlin]
LocalDate: 0000-12-30
Questions:
- There is a missing day after converting to Instant, so it seems like the timezones UTC and Europe/Berlin were a day plus one hour apart at that time?
- When converting the Instant back to my timezone, 6 minutes and 32 seconds get lost somewhere! Why is that?
- The resulting LocalDate is not correct. What would be a robust way to do the conversion?


java.sql.Timestamp, it is a thin wrapper aroundjava.util.Datebut also that it is recommended that code not view Timestamp values generically as an instance ofjava.util.Date. Best practice: Don't use anything related tojava.util.Datefor calculations on dates and times anymore. This tells you why...0001-01-01as a timestamp instead, and I want to write a converter to LocalDate that would handle that case and return NULL.LocalDate.getYear() > 1or similar? I mean always convert the timestamp and check the resultingLocalDatefor valid values.java.timeis not perfectly designed for dates and times around Christ. In addition, there shouldn't be a year 0, but only a year 1 B.C. immediately followed by a year 1 A.C... Not entirely sure about that.