8

Yes, another question about Date in Java and Javascript.

The timezone is GMT+4 (Moscow) both in Java and Browser (Chrome).

<script language="javascript">
  var d = new Date(170798400000);
  document.write(d);
</script>

Gives: Sun Jun 01 1975 00:00:00 GMT+0400 (Russian Standard Time)

public class Test {
    public static void main(String[] args) {
        java.util.Date d = new java.util.Date(170798400000L); // the same epoch value!
        System.out.println(d);
    }
}

Gives: Sat May 31 23:00:00 MSK 1975

If I change the epoch value to something like 2011-2012 year (after daylight saving was canceled in Russia) the output is OK. Timezone updater tool ran OK.

Is this a bug or documented feature? Is there any way to handle this except formatting and re-parsing like YYYY-MM-dd HH:mm:SS or so?

from javadoc:

Date(long date)

Allocates a Date object and initializes it to represent the specified number of milliseconds since the standard base time known as "the epoch", namely January 1, 1970, 00:00:00 GMT.

from javascript reference:

new Date(milliseconds)

milliseconds - Integer value representing the number of milliseconds since 1 January 1970 00:00:00 UTC (Unix Epoch).

ike3
  • 1,760
  • 1
  • 17
  • 26
  • Maybe this has something to do with "Time zone changes": http://en.wikipedia.org/wiki/Moscow_Time – Eng.Fouad Jan 18 '12 at 15:53
  • It definetely is. Is that means Date constructor cannot be used in javascript anymore? – ike3 Jan 18 '12 at 15:56
  • Well, if one of them is giving the right answer, but not the other one, then I'd say the other one has a bug :-) Is Java correct or is JavaScript? I'd sort-of expect the Java version to give the right answer, but that's just a suspicion. – Pointy Jan 18 '12 at 15:56
  • Yes, Java is correct, but javascript is not – ike3 Jan 18 '12 at 15:57
  • @user509723: here both outputs are correct. The JS version shows it in GMT+x format, whereas the Java version uses MSK (which no longer exists as far as I understand). Java can be updated with tzdata to get the right 'Europe/Moscow' tz. It looks like JS may not be able to use the correct tzdata (when converting this way): this will almost inevitably be browser dependent (and perhaps depend on the OS and the user settings). – Bruno Jan 18 '12 at 16:46
  • 2
    both tzdata and jdk (using timezone updater tool) were updated so Java knows that before 2011 it was GMT+3 but GMT+4 after 2011. It seems Javascript is missing this information and thinks that it was always GMT+4. I can hack JSON serializer to insert a condition and adjust the time zone but wondering is there a better way? – ike3 Jan 19 '12 at 02:55
  • No, Daylight Saving Time (+04:00) was not canceled in 2011. Just the opposite. DST was made permanent, in effect year round. It was *Standard Time* (+03:00) that was canceled. See [Wikipedia](http://en.wikipedia.org/wiki/Moscow_Time). – Basil Bourque May 18 '14 at 08:08

3 Answers3

1

String representation of time (like "Sun Jun 01 1975 00:00:00 GMT+0400") are used for human. Time value (milliseconds since 1 January, 1970 UTC) are used for storage and calculation.

There is no bug there. In JavaScript, according to the specification, the contente of string representation is implementation-dependant. In Java, according to the documentation, the daylight saving time may be reflected.

From JavaScript specification:

15.9.5.2 Date.prototype.toString ( )

This function returns a String value. The contents of the String are implementation->dependent, but are intended to represent the Date in the current time zone in a convenient, human-readable form.

From Java documentation:

java.util.Date, public String toString()

Converts this Date object to a String of the form: dow mon dd hh:mm:ss zzz yyyy

where:
...
zzz is the time zone (and may reflect daylight saving time).`
Ortomala Lokni
  • 56,620
  • 24
  • 188
  • 240
1

Is this a bug or documented feature?

This is not a bug with Javascript. At least, I see no way I could claim that.

The browser's Javascript engine is returning the time converted to "GMT+4". What you are wanting, apparently, is MSK which is different from GMT+4 (as noted in your comment). Javascript not knowing about MSK doesn't count as a bug, but a lack of a feature. Perhaps js is "wrong" for not having that detailed knowledge of timezones, but it's not a bug.

Is there any way to handle this except formatting and re-parsing like YYYY-MM-dd HH:mm:SS or so?

Keeping track of all the arbitrary details of timezones requires a lot of work. I know of no such codebase which has all that work available for javascript. Therefore, I believe that, yes, you would have to manually code that conversion yourself if you want to use true MSK.

Alexander Bird
  • 38,679
  • 42
  • 124
  • 159
0

tl;dr

Instant.ofEpochMilli( 170_798_400_000L )

1975-05-31T20:00:00Z

…and…

Instant.ofEpochMilli( 170_798_400_000L )
       .atZone( ZoneId.of( "Europe/Moscow" ) )

1975-05-31T23:00+03:00[Europe/Moscow]

See live code.

Using java.time

The modern approach uses the java.time classes in Java 8 and later.

You are using troublesome old date-time classes in Java that are now legacy. Among the many problems on those classes was the well-intentioned but confusing feature of the Date::toString method applying the current default time zone while generating the string. The internal value is actually always in UTC, but toString creates the illusion that Date has a time zone when in fact it does not. That explains your MSK mystery.

[Even more confusing, there actually is a time zone buried deep in Date but is irrelevant to this discussion. Those old Date/Calendar classes are an awful mess. Fortunately Java now has the best-in-class date-time framework on any platform: java.time.]

Apparently your input represents the number of milliseconds since the Unix epoch of 1970-01-01T00:00:00Z.

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). This class can directly parse your input number.

Instant instant = Instant.ofEpochMilli( 170_798_400_000L ) ;

instant.toString(): 1975-05-31T20:00:00Z

If you want to see that same moment through the lens of a particular region’s wall-clock time, apply a time zone. Apply a ZoneId to get a ZonedDateTime object.

ZoneId z = ZoneId.of( "Europe/Moscow" ) ;
ZonedDateTime zdt = instant.atZone( z ) ;

1975-05-31T23:00+03:00[Europe/Moscow]

JavaScript library is incorrect

The results of your call to the JavaScript library is incorrect with its offset of +04:00. According to Wikipedia, Moscow time from 1930 to 1981 was three hours ahead, +03:00. The java.time framework yields correct results of +03:00 throughout the year of 1975. See Time in Russia for more info. Caveat: I am not expert in Russia/Soviet time.


About java.time

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.

Basil Bourque
  • 303,325
  • 100
  • 852
  • 1,154