Reputation: 1105
I am trying to understand LocalDate and LocalDateTime. Since they do not carry zone info, how does it work for now() on two different time zone.
Example:
Server 1(EST time zone):
LocalDateTime.now() -> 2020-04-06T23:00:00.040 LocalDate.now(). -> 2020-04-06
Server 2(UTC time zone):
LocalDateTime.now() -> What would be the value? LocalDate.now(). -> What would be the value? (Note in EST, time it executed was 11 PM)
Also, If I convert below date string to LocalDateTime and then toLocalDate, what would be the outcome?
2020-04-06T23:00:00.000
Upvotes: 3
Views: 13919
Reputation: 338171
On April 6, 2020, most time zones on the east coast of North America such as America/Montreal
and America/New_York
use an offset of four hours behind UTC.
So, in those zones 11 PM on 2020-04-06 is simultaneously 3 AM on the 7th in UTC. Add four hours to 2020-04-06T23:00 to get 2020-04-07T03:00. Adding four hours brings us from the wall-clock time used in America/Port-au-Prince
and America/Nassau
to UTC.
The offset used by the time zones mentioned above are four hours behind UTC only half the year. The politicians in those locations have decided to observe Daylight Saving Time (DST) for about half the year. So half the year they jump their clocks ahead an hour for an offset-from-UTC of -04:00, and later in the year they fall back an hour for an offset-from-UTC of -05:00. For example, earlier in the year 11 PM in America/New_York
would be 04:00 in UTC rather than the 03:00 time seen in April.
Standard time, in January, is five hours behind UTC. So, 11 PM plus five hours is 4 AM next day.
ZoneId z = ZoneId.of( "America/New_York" ) ;
ZonedDateTime zdt = ZonedDateTime.of( 2020 , 1 , 6 , 23 , 0 , 0 , 0 , zNewYork ) ;
Instant instant = zdt.toInstant() ; // 2020-01-07T04:00Z
Daylight Saving Time, in April, is four hours behind UTC. So, 11 PM plus four hours is 3 AM next day.
ZoneId z = ZoneId.of( "America/New_York" ) ;
ZonedDateTime zdt = ZonedDateTime.of( 2020 , 4 , 6 , 23 , 0 , 0 , 0 , zNewYork ) ;
Instant instant = zdt.toInstant() ; // 2020-04-07T03:00Z
By the way, DST is only one of many reasons politicians have for changing the offset used by the time zone(s) of their jurisdiction. Politicians around the world have shown a penchant for changing their offsets surprisingly often. Your programming should always expect a time zone to change its offset. Just because your particular zone of concern does not currently observe DST does not mean the offset will never change.
As for parsing 2020-04-06T23:00:00.000
as a LocalDateTime
, you will get 2020-04-06T23:00:00.000
. Ignoring time zones is the entire point of LocalDateTime
. So no adjustments are made.
You may be thinking of LocalDateTime
as representing a particular locality. But, no, it represents any locality or all localities. But never any one particular locality. For a particular locality, use ZonedDateTime
.
Another point: EST
is not a time zone. Such 2-4 letter letter codes are not real time zones, are not standardized, and are not even unique. For example, by EST
, did you mean Australian Eastern Standard Time or North American Eastern Standard Time? Is CST
Central Standard Time or China Standard Time? Avoid these pseudo-zones in your date-time-handling.
And you happened to use the wrong pseudo-code. On April 6 2020, most of those east coast time zones are observing Daylight Saving Time (DST). So they would be considered to be in “EDT” rather than “EST”. Avoid the problem by specifying the real time zone name.
Real time zones are named using Continent/Region
format. See Wikipedia for a list of real time zones.
LocalDateTime.now
I cannot imagine a case where calling LocalDateTime.now
would be the right thing to do. Determining the current moment requires a time zone (or offset). And LocalDateTime
by definition has no time zone or offset. When a programmer writes LocalDateTime.now
, you can bet they do not fully understand the necessary concepts.
When you call LocalDateTime.now
, the JVM’s current default time zone is implicitly used to capture the current time as seen by the people in the region of that zone. And then the fact of that time zone is deleted.
This:
LocalDateTime.now()
…is the same as this:
LocalDateDate.now( ZoneId.systemDefault() )
…which is the same as getting the current moment as seen in a particular time zone, followed by removing the time zone information:
ZonedDateTime.now( ZoneId.systemDefault() ).toLocalDateTime()
For more code examples demonstrating LocalDateTime.now
, see the correct Answer by Ole V.V.
LocalDateTime
If LocalDateTime
is not appropriate for getting the current moment, and is not appropriate for tracking any moment, what is the appropriate use for this class? Three things: representing any locality, representing all localities, and booking future appointments.
Set the appointment.
LocalDateTime appointment = LocalDateTime.of( 2021 , 1 , 23 , 15 , 0 , 0 , 0 ) ;
Determine a moment for producing a calendar. Every time you do this, you may get a different result if the politicians have changed the rules of this time zone.
ZoneId z = ZoneId.of ( "America/Panama" ) ;
ZonedDateTime dueToArrive = appointment.atZone( z ) ;
LocalDate
As for LocalDate
, we saw in the examples above that the date depends on time zone. For any given moment, the date varies around the globe by time zone. It may be “tomorrow” in Tokyo Japan while still “yesterday” in Montréal Québec Canada.
So, you must specify a time zone when asking for the current date.
LocalDate ld = LocalDate.now( ZoneId.of( "Asia/Kolkata" ) ) ;
If you omit the time zone, the JVM’s current default time zone is implicitly applied. So LocalDate.now()
becomes LocalDate.now( ZoneId.systemDefault() )
. I recommend specifying your desired/expected zone explicitly, rather than rely on implicit default.
You said:
server which runs in EST vs UTC
FYI, servers should generally be set to UTC. Most of your thinking, programming, logging, and so on should be done in UTC. Learn to think of UTC as The One True Time, with all other zones but mere variations.
As a programmer, you should never rely on the default time zone. That is far outside your control. That default can be changed so easily by the user or sysadmin. Furthermore, any code in any thread of any app within the JVM can instantly change the JVM’s current default time with a call to TimeZone.setDefault
. So even during execution of your app, the default can be changed at any moment.
Upvotes: 9
Reputation: 86140
To prevent confusion pass explicit time zone to now()
and see for yourself:
ZoneId easternTime = ZoneId.of("America/Montreal");
System.out.println(LocalDateTime.now(easternTime));
System.out.println(LocalDateTime.now(ZoneOffset.UTC));
System.out.println(LocalDate.now(easternTime));
System.out.println(LocalDate.now(ZoneOffset.UTC));
Output when I ran just now:
2020-04-06T09:56:17.381558 2020-04-06T13:56:17.385215 2020-04-06 2020-04-06
While you are correct that LocalDateTime
and LocalDate
don’t contain any time zone information, their now
methods do use time zones. Either the one passed to them, or if you use the no-arg variant, the default time zone of the JVM.
You also asked:
Also, If I convert below date string to LocalDateTime and then toLocalDate, what would be the outcome?
2020-04-06T23:00:00.000
Why not try out that too?
LocalDateTime ldt = LocalDateTime.parse("2020-04-06T23:00:00.000");
System.out.println(ldt);
LocalDate ld = ldt.toLocalDate();
System.out.println(ld);
2020-04-06T23:00 2020-04-06
Converting from LocalDateTime
to LocalDate
involves no time zone (or UTC offset) whatsoever. The time part is simply discarded and the date part kept unchanged.
Upvotes: 5