We know that getTime method of java.util.Date returns the number of milliseconds since January 1, 1970, 00:00:00 GMT represented by this Date object.
I noticed a weird situation as below;
System time zone is:(UTC+02:00) Istanbul
Date currentDate = new Date();
System.out.println(currentDate .getTime());
System.out.println(currentDate);
Java ConsoleOutput:
1360753217219
Wed Feb 13 13:00:17 VET 2013
Then my javascript plugin is using this long object like below;
Javascript:
console.log(new Date(1360753217219));
Browser ConsoleOutput:
Date {Wed Feb 13 2013 13:00:17 GMT+0200 (Turkey Standard Time)}
Thats all ok, however! After change my local time zone as (UTC-04:30) Caracas, situation and hour is changing as below with same number of milliseconds;
Javascript:
console.log(new Date(1360753217219));
Browser ConsoleOutput:
Date {Wed Feb 13 2013 06:30:17 GMT-0430 (Venezuela Standard Time)}
Can someone explain this? Is that js bug? Or more importantly, how should I handle this on java side, to get same date with same number of miliseconds for different time zones on js side?
Thanks!
The milliseconds are time zone agnostic. Time is measured as an absolute since Jan 1, 1970 GMT. So, the idea is that you get the milliseconds and then work out what the local time for a given time zone is after the fact. If you think about it, it makes sense. The number of milliseconds that have passed since 1970 are the same no matter where you are.
It gets a bit confusing but do NOT noodle around with the milliseconds in order to adjust for time zones. Every Date library has mechanisms to translate a millisecond stamp into a time zone specific local time.
So if your specific question is how to communicate the date effectively between the server and the client (what languages you're using is not important), the answer is it's perfectly safe to pass milliseconds back and forth and work out on either side what global specific time you're talking about, if that's important to the context of what you're doing with that time.
not a bug, that's just how time zones work.
if you call someone in Venezuela right now and ask him what time it is, he'll tell you it's 6.5 (according to your example) hours earlier than the time in turkey.
as you mentioned, the number you're dealing with represents the number of milliseconds since 1970, 00:00:00 GMT, in Caracas at that very same second, the time was 31.12.1969 19:30 GMT-0430
so, however many seconds later, the time in Venezuela will still be 4:30 hours earlier compared to GMT.
you can't get the exact same date in different time zones if you use the same input (milliseconds) because that would simply be wrong.
if you want to get the same result, you could add the difference in timezones (6.5 hours in this case) to the output. following Dr.Dredel's advice, you probably shouldn't mess with the milliseconds.
Instant.ofEpochMilli( 1_360_753_217_219L ) // UTC
2013-02-13T11:00:17.219Z
Instant.ofEpochMilli( 1_360_753_217_219L )
.atZone( ZoneId.of( "Europe/Istanbul" ) ) // Same moment, two hours *ahead* of UTC.
2013-02-13T13:00:17.219+02:00[Europe/Istanbul]
Instant.ofEpochMilli( 1_360_753_217_219L )
.atZone( ZoneId.of( "America/Caracas" ) ) // Same moment, four-and-a-half hours *behind* UTC.
2013-02-13T06:30:17.219-04:30[America/Caracas]
You are using troublesome old date-time classes bundled with the earliest versions of Java. They are now legacy, supplanted by the java.time classes, the best date-time library on any platform.
Start with your number of milliseconds since an epoch reference date of the beginning of 1970 in UTC (1970-01-01T00:00:00Z). Others point out that you may not grasp that an epoch reference date has a time zone, and here with this epoch that zone is UTC, an offset of zero hours. All other offsets are measured against this one, a number of hours and minutes ahead of UTC or behind UTC.
The Instant
class represents a moment on the timeline in UTC with a resolution of nanoseconds (up to nine (9) digits of a decimal fraction).
long input = 1_360_753_217_219L ;
Instant instant = Instant.ofEpochMilli( input ) ;
instant.toString(): 2013-02-13T11:00:17.219Z
If you want to see that same moment through the lens of a particular region’s wall-clock time, apply a time zone.
A time zone is a history of past, present, and future changes to the offset in use by a particular region.
Specify a proper time zone name in the format of continent/region
, such as America/Montreal
, Africa/Casablanca
, or Pacific/Auckland
. Never use the 3-4 letter abbreviation such as EST
or IST
as they are not true time zones, not standardized, and not even unique(!).
ZoneId zEurope_Istanbul = ZoneId.of( "Europe/Istanbul" ) ;
ZonedDateTime zdtEurope_Istanbul = instant.atZone( zEurope_Istanbul ) ;
zdtEurope_Istanbul.toString(): 2013-02-13T13:00:17.219+02:00[Europe/Istanbul]
You can apply another time zone.
ZoneId zAmerica_Caracas = ZoneId.of( "America/Caracas" ) ;
ZonedDateTime zdtAmerica_Caracas = zdtEurope_Istanbul.withZoneSameInstant( zAmerica_Caracas ) ;
zdtAmerica_Caracas.toString(): 2013-02-13T06:30:17.219-04:30[America/Caracas]
See this code live at IdeOne.com.
These three objects, instant & zdtEurope_Istanbul & zdtAmerica_Caracas, all represent the very same simultaneous moment, the same point on the timeline.
Your count-from-epoch represents 11 AM in UTC. Istanbul is two hours ahead of UTC, so the time-of-day there at the same moment is two hours after 11 AM, 1 PM (13:00). Venezuela is four and a half hours behind UTC, so the time-of-day there at the same moment is 6:30 AM. These all make sense, all the same moment but different wall-clock time.
Do not use a count-from-epoch for exchanging or storing date-time values. That is error-prone, being impposible to read meaningfully by a human, and ambiguous as there are at least a couple dozen epoch reference dates in use by various software systems and at different granularities (whole seconds, milliseconds, microseconds, nanoseconds, etc.).
When passing date-time values outside your JVM, use the standard ISO 8601 formats for textual representation. The java.time classes use the standard formats by default when parsing/generating strings. You can see those formats in this Answer’s example code.
The java.time framework is built into Java 8 and later. These classes supplant the troublesome old legacy date-time classes such as java.util.Date
, Calendar
, & SimpleDateFormat
.
The Joda-Time project, now in maintenance mode, advises migration to the java.time classes.
To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310.
Where to obtain the java.time classes?
The ThreeTen-Extra project extends java.time with additional classes. This project is a proving ground for possible future additions to java.time. You may find some useful classes here such as Interval
, YearWeek
, YearQuarter
, and more.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With