3

I've just come upon a very strange behaviour of Java’s Date class when I try to create two dates consequently:

Date startDate = new Date(1282863600000L);
System.out.println(startDate);

Date endDate = new Date(1321919999000L);
System.out.println(endDate);

The output is respectively:

Fri Aug 27 00:00:00 BST 2010
Mon Nov 21 23:59:59 GMT 2011

Has anyone seen something like that? Both Dates are initialized in the same manner, but when printed, the first is shown in BST and the latter in GMT? How come?

I tried to find explanation about that but I didn’t.

4
  • Do you remember winding clocks forward/backward by an hour due to daylight saving? ;) Commented May 31, 2011 at 12:17
  • For new readers to the question, first of all you should use java.time, the modern Java date and time API, for your date and time work. The Date class was poorly designed and is long outdated, so better avoided. Commented Dec 20, 2024 at 20:27
  • BST is for British Summer Time (meaning daylight saving time). British standard time coincides with GMT (or UTC), so Java renders it as GMT in English. Commented Dec 20, 2024 at 20:28
  • 1
    BTW that is not a "Date creation behaviour" but a toString() conversion feature Commented Dec 20, 2024 at 21:05

4 Answers 4

5

This is documented behaviour.

From Date.toString():

Converts this Date object to a String of the form:

 dow mon dd hh:mm:ss zzz yyyy

zzz is the time zone (and may reflect daylight saving time). Standard time zone abbreviations include those recognized by the method parse. If time zone information is not available, then zzz is empty - that is, it consists of no characters at all.

You are using a locale that uses British Summer Time and creating a date where a day-light-saving rule applies. This would be the expected form of the date at that time to a local user.

Sign up to request clarification or add additional context in comments.

Comments

2

Why BST and GMT in your output?

  1. java.util.Date does not hold timezone information. It stores the number of milliseconds since Midnight, January 1st, 1970 UTC and Date#toString applies the JVM's default time zone to it to form the output text. Since, your JVM has Europe/London as the time zone set, Date#toString uses the same.
  2. August falls under DST in the Europe/London time zone and the time during DST is called British Summer Time (BST). November falls outside DST in the Europe/London time zone and the time outside DST is called Greenwich Mean Time (GMT). Check this and this link to learn more about it.

java.time

In March 2014, Java 8 introduced the modern, java.time date-time API which supplanted the error-prone legacy java.util date-time API. Any new code should use the java.time API.

java.time.ZonedDateTime holds time zone information along with date and time. Below is an excerpt from its documentation:

A date-time with a time-zone in the ISO-8601 calendar system, such as 2007-12-03T10:15:30+01:00 Europe/Paris.

The best thing about it is it automatically adjusts the zone offset as per the DST as you can see in the below demo.

To avoid any misleading output, ZonedDateTime requires you to specify the ZoneId while converting an Instant into a ZonedDateTime.

Demo:

class Main {
    public static void main(String[] args) {

        ZoneId zoneId = ZoneId.of("Europe/London");
        
        ZonedDateTime zdt1 = Instant.ofEpochMilli(1282863600000L)
                                    .atZone(zoneId);
        ZonedDateTime zdt2 = Instant.ofEpochMilli(1321919999000L)
                                    .atZone(zoneId);

        System.out.println(zdt1);
        System.out.println(zdt2);
    }
}    

Output:

2010-08-27T00:00+01:00[Europe/London]
2011-11-21T23:59:59Z[Europe/London]

Z represents a time zone offset of +00:00, which is the zone offset for UTC.

Online Demo

Learn more about the modern Date-Time API from Trail: Date Time.

Comments

1

For me the output of this code is

Fri Aug 27 01:00:00 CEST 2010
Tue Nov 22 00:59:59 CET 2011

The exact result depends on the default locale Java is using on your system.

The difference is that CEST is the central european summer time, while CET is the central european time (i.e. not summer time).

You seem to be running in a british locale (en_GB or similar), so your output shows the British Summer Time and the Greenwich Mean Time respectively.

The first date you specify falls into the respective summer times and the second doesn't. So Java chooses the appropriate time zone for each locale/time combination.

Comments

1

After a lovely session of trying different long values I got this:

Date startDate1 = new Date(1284245999999L);
Date startDate2 = new Date(1284246000000L);
System.out.println(startDate1);
System.out.println(startDate2);

Date endDate = new Date(1321919999000L);
System.out.println(endDate);

The output was:

Sun Sep 12 01:59:59 IDT 2010
Sun Sep 12 01:00:00 IST 2010 <-- Long value is greater, but due to DST changes, actual time is one hour earlier
Tue Nov 22 01:59:59 IST 2011

Note that incrementing the long by 1 from 1284245999999L to 1284246000000L takes us "back in time" because of the transition from standard time to daylight savings time.
That is how Java time calculation behaves - the number of milliseconds since 1/1/1970 does not change, but the time it represents is based on the timezone.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.