Maverick283
Maverick283

Reputation: 1403

Get LocalDateTime from seconds including the timezone

I have the time in seconds from our computers "Day 0" (a.k.a. midnight, January 1st 1970 UTC) and I want to convert that into a LocalDateTime instance. This code will do that:

LocalDateTime dateTime = LocalDateTime.ofEpochSecond(seconds, 0, ZoneOffset.UTC)

Nevertheless, I need this LocalDateTime to be in my timezone. Changing ZoneOffset.UTCto ZineOffset.of("+2) will bring the LocalDateTime to display the correct time. (For, let's say Paris as of 8/31/2015)

But this is more or less an imperfect workaround, as it does not take care of Daylight Saving Time.

So I tried around a bit more, and found the ZonedDateTime class. It didn't help me out either, but I got stuck here:

LocalDateTime localDateTime = LocalDateTime.ofEpochSecond(seconds, 0, ZoneOffset.UTC);
ZonedDateTime zonedDateTime = ZonedDateTime.of(localDateTime,ZoneId.systemDefault());

This doesn't work at all though, as ZonedDateTime contains a LocalDateTime which then contains a LocalTime which is my time in UTC, rather then in my current time zone.

So how do you get a LocalDateTime in the (preferably) Systems time Zone including Daylight Saving Time (if needed) from a UTC seconds-from-epoche value?

Upvotes: 7

Views: 13243

Answers (1)

steffen
steffen

Reputation: 16938

You need to specify the ZoneId in order to have the daylight savings from a geographical region taken into account. Get a list of available zone IDs:

System.out.println(ZoneId.getAvailableZoneIds());

With the correct zone ID, you'll have access to the daylight saving rules.

For example, in Germany (UTC+1) they had the first daylight savings in 1940 (UTC+2). In 1947, they introduced the midsummer time, being two hours ahead of the standard winter time (=UTC+3). Here's an example for summer 1940, 1947, 1970 (no daylight savings) and this morning:

Instant[] instants = new Instant[] {
        LocalDateTime.of(1939, 6, 1, 0, 0).toInstant(ZoneOffset.UTC),
        LocalDateTime.of(1940, 6, 1, 0, 0).toInstant(ZoneOffset.UTC),
        LocalDateTime.of(1947, 6, 1, 0, 0).toInstant(ZoneOffset.UTC),
        Instant.ofEpochSecond(0), // 1970-01-01T00:00:00 UTC
        LocalDateTime.of(1970, 6, 1, 0, 0).toInstant(ZoneOffset.UTC),
        Instant.now().truncatedTo(ChronoUnit.DAYS), // 2015-08-31T00:00:00 UTC
};

for (Instant instant : instants) {
    LocalDateTime inBerlin = LocalDateTime.ofInstant(instant, ZoneId.of("Europe/Berlin"));
    System.out.println("UTC    " + instant.atOffset(ZoneOffset.UTC).toLocalDateTime());
    System.out.println("BERLIN " + inBerlin);
    System.out.println();
}

This will print something like:

UTC    1939-06-01T00:00
BERLIN 1939-06-01T01:00

UTC    1940-06-01T00:00
BERLIN 1940-06-01T02:00

UTC    1947-06-01T00:00
BERLIN 1947-06-01T03:00

UTC    1970-01-01T00:00
BERLIN 1970-01-01T01:00

UTC    1970-06-01T00:00
BERLIN 1970-06-01T01:00

UTC    2015-08-31T00:00
BERLIN 2015-08-31T02:00

As you can see, the rules are implemented correctly. The first daylight savings in Berlin were 1940. In 1947, there were daylight savings with an additional hour shift. In the years from 1950 - 1980 there were no daylight savings at all. In 1980, many countries in Europe had an orchestrated start of daylight savings.

Oh, to answer your question:

LocalDateTime.ofInstant(Instant.ofEpochSecond(seconds), ZoneId.systemDefault())

Upvotes: 14

Related Questions