1

In Java what is the accepted method for determining daylight savings time for any given Date object for a certain locale.

For example if you had two date Objects

Date date = new Date("01/01/2014");
Date date2 = new Date("01/07/2014");

And the locale was "Europe/London", 'date' should return GMT and date2 should return "BST"

    String timeZone = new String("Europe/London");
    TimeZone tz = TimeZone.getTimeZone(timeZone);
    System.out.println(tz.getDisplayName(tz.inDaylightTime(date),
            TimeZone.SHORT));

    TimeZone tz2 = TimeZone.getTimeZone(timeZone);
    System.out.println(tz2.getDisplayName(tz2.inDaylightTime(date2),
            TimeZone.SHORT));

Both these examples print GMT, shouldn't the second print BST?

user898465
  • 944
  • 1
  • 12
  • 23
  • 1
    `Europe/London` is *not* a [Locale](https://docs.oracle.com/javase/8/docs/api/java/util/Locale.html), it is a [proper time zone name](https://en.wikipedia.org/wiki/List_of_tz_database_time_zones). Avoid using the 3 or 4 letter abbreviations as they are neither standardized nor unique. Except for [UTC](https://en.wikipedia.org/wiki/Coordinated_Universal_Time). – Basil Bourque Nov 11 '14 at 17:04

2 Answers2

3

java.time

The legacy date-time API (java.util date-time types and their formatting type, SimpleDateFormat) is outdated and error-prone. It is recommended to stop using it completely and switch to java.time, the modern date-time API*.

And the locale was "Europe/London", 'date' should return GMT and date2 should return "BST"

Note that Europe/London is a time zone (ZoneId), not a Locale. Java SE 8 date-time API (java.time) provides us with ZonedDateTime which automatically adjusts the timezone offset as per the DST transition.

Demo:

import java.time.LocalDate;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Locale;

public class Main {
    public static void main(String[] args) {
        DateTimeFormatter dtfInput = DateTimeFormatter.ofPattern("d/M/u", Locale.ENGLISH);
        LocalDate date = LocalDate.parse("01/01/2014", dtfInput);
        LocalDate date2 = LocalDate.parse("01/07/2014", dtfInput);

        ZoneId zoneId = ZoneId.of("Europe/London");

        ZonedDateTime zdt = date.atStartOfDay(zoneId);
        ZonedDateTime zdt2 = date2.atStartOfDay(zoneId);

        DateTimeFormatter dtfOutput = DateTimeFormatter.ofPattern("dd/MM/uuuu'['z']'", Locale.ENGLISH);
        System.out.println(zdt.format(dtfOutput));
        System.out.println(zdt2.format(dtfOutput));
    }
}

Output:

01/01/2014[GMT]
01/07/2014[BST]

Learn more about java.time, the modern date-time API* from Trail: Date Time.


* For any reason, if you have to stick to Java 6 or Java 7, you can use ThreeTen-Backport which backports most of the java.time functionality to Java 6 & 7. If you are working for an Android project and your Android API level is still not compliant with Java-8, check Java 8+ APIs available through desugaring and How to use ThreeTenABP in Android Project.

Basil Bourque
  • 303,325
  • 100
  • 852
  • 1,154
Arvind Kumar Avinash
  • 71,965
  • 6
  • 74
  • 110
2

I think your dates are both not in daylight saving time, the pattern is mm/dd/yyyy, so your dates are 1st jan 2014 and 7th jan 2014. By the way: The constructor you use is deprecated!

Date date = new Date("01/01/2014");
Date date2 = new Date("01/07/2014");
Date date3 = new Date("07/07/2014");

Calendar cal = Calendar.getInstance(Locale.UK);
cal.setTime(date);
System.out.println(date + " " + cal.getTimeZone().inDaylightTime(date));
cal.setTime(date2);
System.out.println(date2 + " " + cal.getTimeZone().inDaylightTime(date2));
cal.setTime(date3);
System.out.println(date3 + " " + cal.getTimeZone().inDaylightTime(date3));

This should give you a hint. At least you know if the date is in daylight saving time, how this time is called is a second problem, I don't think it's resolveable with standard-API. Have you tried looking at http://www.joda.org/joda-time/? It's an API for DateTime calculations.

Ishkafel
  • 333
  • 1
  • 10
  • Is there a Data constructor for String format? The deprecated one is for int year, month, day format. – dragon66 Nov 11 '14 at 15:49
  • There is SimpleDateFormat for this: `SimpleDateFormat sdf = new SimpleDateFormat("dd.MM.yyyy"); Date date = sdf.parse("01.01.2014"); Date date2 = sdf.parse("07.01.2014"); Date date3 = sdf.parse("01.07.2014");`. API doc and patterns: https://docs.oracle.com/javase/7/docs/api/java/text/SimpleDateFormat.html – Ishkafel Nov 11 '14 at 15:53
  • Agh, goddamn American date formatting! This is correct actually, silly mistake. – user898465 Nov 11 '14 at 16:05
  • But what I mean is the constructor for the Date object itself, not the parameter for the parse method of SimpleDateFormat – dragon66 Nov 11 '14 at 16:40
  • https://docs.oracle.com/javase/7/docs/api/java/util/Date.html Here is the API of Date. Only non-deprecated constructors are `Date()` and `Date(long date)` where `long date` is `number of milliseconds since the standard base time known as "the epoch", namely January 1, 1970, 00:00:00 GMT.` So: No, you can't construct a Date-Object directly from a String. – Ishkafel Nov 11 '14 at 16:51
  • Update to this old Answer… This Answer uses terrible date-time classes that have now been supplanted by the *java.time* classes. Sun, Oracle, and the JCP gave up on these legacy classes with the unanimous adoption of [JSR 310](https://jcp.org/en/jsr/detail?id=310). See modern solution in the [Answer by Avinash](https://stackoverflow.com/a/67561103/642706). Also, the *Joda-Time* project mentioned is now in maintenance-mode. Its creator, [Stephen Colebourne](https://stackoverflow.com/users/38896/jodastephen), took lessons learned there and went on to lead the JSR 310 effort. – Basil Bourque May 16 '21 at 23:33