androiddatejava-timejava.util.datedatetime-conversion

Android Date.from() taking device timezone into account?


Using the following code in Java8 -

newTable.LogDate = Date.from(ZonedDateTime.of(year, month, day, 0, 0, 0, 0, ZoneId.of("GMT")).toInstant());

The LogDate is ending up adjusted for my (and my user's) devices.

In the above case, for example, if I send it 1934, 1, 1 (Jan 1st, 1934), the LogDate has Dec 31st, 1933, 7pm. (For my device's Eastern US timezone.)

Is there a way to have the Date object NOT take the device's timezone and do any conversion?

Edit to add: If I change the ZoneId.of("GMT") and change JUST IT to ZoneId.systemDefault(), the ending result is as expected and 'correct'. (i.e. Stays Jan 1st 1934.)


Solution

  • The device or JVM time zone is not taken into account in the conversion itself.

    The Date class is confusing. Despite its name it does not represent a date, nor a date and time of day. It represents a moment in time, a point in time, an instant. As you probably know, Jan 1st, 1934 00:00 GMT is the same point in time as Dec 31st, 1933, 7pm. in America/New_York time zone. This means that you are getting a correct conversion. And more than that: it means that you are getting the only possible correct conversion. Any other conversion to a Date would have given you a different point in time, that is, a wrong point in time.

    What may have confused you could be that if you try to use your Date for something, that something could well assume that you intended the default time zone of your JVM and device. For example if you print out the Date or view it in your debugger, in both cases implicitly invoking its toString method, then that toString method uses your time zone to render the string that you see:

    Sun Dec 31 19:00:00 EST 1933

    toString() is telling a lie. I would have us believe that the Date contains that value. It does not. It contains a count of milliseconds since the Java epoch of 1970-01-01 00:00 UTC. In your case a negative count since your point in time is before the epoch, -1 136 073 600 000 milliseconds. Nothing else.

    The solution? It depends on what you need at Date for and what the requirements for that Date are. Ideally you should not need a Date since that class is poorly designed and long outdated. You would be better off using exclusively classes from java.time, the modern Java date and time API to which ZonedDateTime and ZoneId belong. If you do need a Date, maybe you have already got the right one and just need to clear your confusion and settle with it. If you give us reason and the requirements, we can probably guide you better.

    Link: All about java.util.Date on Jon Skeet’s coding blog