3

I'm using Joda-Time DateTime in Android.

It seems that the DateTimeZone doesn't work correctly. Maybe it has something to do with daylight savings?

At this moment, we have GMT +2. This will change in a few weeks, for the winter. Then it will be GMT +1. But right now it's not correct.

import org.joda.time.DateTime
import org.joda.time.DateTimeZone
import org.joda.time.LocalDateTime

// GMT: Thursday 26 October 2017 12:11:54
val epochTime: Long = 1509019914 

var dateServer = LocalDateTime(epochTime * 1000).toDateTime(DateTimeZone.forID("Europe/Amsterdam"))

Expected (correct time in Amsterdam):

14:11:54 GMT+02:00 DST

Actual:

13:11 2017-10-26T13:11:54.000+01:00

Jim Clermonts
  • 1,694
  • 8
  • 39
  • 94

1 Answers1

4

The LocalDateTime constructor gets the epochTime value and converts to the default timezone to get the date and time values - check the value of DateTimeZone.getDefault(), it's probably a timezone that's currently using the +01:00 offset.

Then the toDateTime method creates a DateTime that corresponds to the same date and time represented by the LocalDateTime, but at the specified timezone (it just "attaches" the timezone to the date/time values, and no conversion is made).

If you want to get the date and time that corresponds to the epochTime in a specific timezone, just create the DateTime directly:

val dateServer = DateTime(epochTime * 1000, DateTimeZone.forID("Europe/Amsterdam"));

With this, dateServer will be:

2017-10-26T14:11:54.000+02:00


An example in my default timezone, just to be more clear. My default timezone (returned by DateTimeZone.getDefault()) is America/Sao_Paulo, which is using the offset -02:00 (2 hours behind UTC) at October 26th 2017.

The epochTime 1509019914 corresponds to UTC 2017-10-26T12:11:54Z.

When I do LocalDateTime(epochTime * 1000), it gets the corresponding UTC value (12:11) and converts to the default timezone: in my case, to 10:11, so the LocalDateTime will have the value 2017-10-26T10:11:54.

Then the toDateTime method just creates a DateTime that corresponds to the same date and time (2017-10-26T10:11:54), at the specified timezone. So it creates 2017-10-26T10:11:54 at Amsterdam (+02:00).

Your default timezone is probably one that uses the +01:00 offset, which would explain the difference you're getting (12:11 UTC is first converted to LocalDateTime with 13:11, and then toDateTime creates 13:11 at Amsterdam).


JSR310 - new date/time API

Joda-Time is in maintainance mode and is being replaced by the new APIs, so I don't recommend start a new project with it. Even in joda's website it says: "Note that Joda-Time is considered to be a largely “finished” project. No major enhancements are planned. If using Java SE 8, please migrate to java.time (JSR-310).".

If you can't (or don't want to) migrate from Joda-Time to the new API, you can ignore this section.

In Android, you can use the ThreeTen Backport, a great backport for Java 8's new date/time classes. To make it work, you'll also need the ThreeTenABP (more on how to use it here).

To get the corresponding UTC instant from the epochTime, you can use the org.threeten.bp.Instant class. Then you use a org.threeten.bp.ZoneId to convert it to a timezone, resulting in a org.threeten.bp.ZonedDateTime:

val dateServer = Instant.ofEpochSecond(epochTime).atZone(ZoneId.of("Europe/Amsterdam"));

dateServer will be a org.threeten.bp.ZonedDateTime, with the value corresponding to 2017-10-26T14:11:54+02:00[Europe/Amsterdam].