DevelopingDeveloper
DevelopingDeveloper

Reputation: 913

LocalDate inconsistency

I am trying to produce a Date object (java.util.Date) from a LocalDate object (java.time.LocalDate) in which I have the following criteria:

To meet this criteria, I have created a test program, however I am getting interesting results when I modify a certain property of the LocalDate. See code below:

  public static void main (String args[]) {
    Long processingDaysInPast = 0L;
    LocalDate createdDate1 = LocalDate.now(Clock.systemUTC()).minusDays(processingDaysInPast);
    LocalDate createdDate2 = LocalDate.now(Clock.systemUTC()).minusDays(processingDaysInPast);
    System.out.println(createdDate1);
    System.out.println(createdDate1.atStartOfDay().toInstant(ZoneOffset.UTC));
    System.out.println(Date.from(createdDate1.atStartOfDay().toInstant(ZoneOffset.UTC)));
    System.out.println((createdDate2.atStartOfDay().atZone(ZoneId.systemDefault()).toInstant()));
    System.out.println(Date.from(createdDate2.atStartOfDay().atZone(ZoneId.systemDefault()).toInstant()));
}

Output:

 2017-08-14
 2017-08-14T00:00:00Z
 Sun Aug 13 19:00:00 CDT 2017
 2017-08-14
 2017-08-14T05:00:00Z
 Mon Aug 14 00:00:00 CDT 2017

When I add the value Date.from(createdDate1.atStartOfDay().toInstant(ZoneOffset.UTC)) I get the expected output of the date, with a 00:00:00 time field. However, if I do not add this parameter, such as: Date.from(createdDate2.atStartOfDay().atZone(ZoneId.systemDefault()).toInstant()) I get the resulting day before , at 19:00:00 why is this?

My main goal from this is to be able to capture a Date object, with the current UTC Date, and the Time zeroed out (StartOfDay).

Upvotes: 2

Views: 1247

Answers (1)

user7605325
user7605325

Reputation:

When you do:

createdDate2.atStartOfDay().atZone(ZoneId.systemDefault())

First, createdDate2.atStartOfDay() returns a LocalDateTime, which will be equivalent to 2017-08-14 at midnight. A LocalDateTime is not timezone-aware.

When you call atZone(ZoneId.systemDefault()), it creates a ZonedDateTime with the respective date (2017-08-14) and time (midnight) in the system's default timezone (ZoneId.systemDefault()). And in your case, the default timezone is not UTC (it's "CDT", so it's getting midnight at CDT - just do System.out.println(ZoneId.systemDefault()) to check what your default timezone is).

To get the date at midnight in UTC, you can replace the default zone (ZoneId.systemDefault()) with UTC (ZoneOffset.UTC):

Date.from(createdDate2.atStartOfDay().atZone(ZoneOffset.UTC).toInstant())

Or (a shorter version):

Date.from(createdDate2.atStartOfDay(ZoneOffset.UTC).toInstant())

Of course you can also do the same way you did with createdDate1:

Date.from(createdDate2.atStartOfDay().toInstant(ZoneOffset.UTC))

They're all equivalent and will result in midnight at UTC.


Just a quick note: short timezone names like CDT or PST are not real timezones.
The API uses IANA timezones names (always in the format Region/City, like America/Chicago or Europe/Berlin). Avoid using the 3-letter abbreviations (like CDT or PST) because they are ambiguous and not standard.

There are lots of different timezones that can use CDT as abbreviation. This happens because a timezone is the set of all different offsets that a region had, has and will have during history. Just because many places uses CDT today, it doesn't mean they all used in the past at the same periods, nor that it'll be used by all in the future. As the history differs, a timezone is created for each region.

Upvotes: 3

Related Questions