Reputation: 913
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:
Date
object00:00:00
String
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
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