0

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.)

Coyttl
  • 537
  • 1
  • 4
  • 19
  • How and where are you seeing that your time zone is taken into account? (Asking because it is not.) – Ole V.V. Apr 10 '21 at 10:01
  • @OleV.V. I didn't think the Date object had any 'timezone' info at all - however, when I look in Android Studio during debugging, there is a field part of the Date object that contains the zone offset time. (The name of said field at the moment escapes me - will need to pull it up once I'm back in the office tomorrow.) – Coyttl Apr 11 '21 at 21:47
  • 1
    Ir’s correct, the implementation of `Date` often stores a time zone. I have never understood why, it’s very confusing. One guess is that it is an optimization thing. I have never seen a case where it differed from the JVM default time zone. – Ole V.V. Apr 12 '21 at 03:26

1 Answers1

1

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

Ole V.V.
  • 81,772
  • 15
  • 137
  • 161
  • Thanks for the thgouth-out answer. At this time I (believe) I am stuck with the Date object as the value is ending up being stored in an ObjectBox database, as a 'Date' type. Other types (like `LocalDate`, which actually would fit better as well, and is what I started with) needs a custom converter hooked up, to save the value as a base type. (String, Int, etc.) – Coyttl Apr 11 '21 at 21:45
  • 1
    I don’t know ObjectBox. If I understand [this page](https://docs.objectbox.io/advanced/custom-types) correctly, ObjectBox stores the millisecond value I mentioned, so you should be set, I guess. I’d still prefer to get rid of the confusing `Date` class and store for example `Instant` from java.time even if it means writing a custom converter. – Ole V.V. Apr 12 '21 at 04:09
  • You recommend an `Instant` or a `LocalDate`? I note the latter only stores the date, which is all that's important in this use-case. If I gotta write a converter, I will. :) – Coyttl Apr 13 '21 at 00:58
  • Yes, in that case a `LocalDate`, you are right. The *local* in the class name means *without time zone*. – Ole V.V. Apr 13 '21 at 06:08