chris01
chris01

Reputation: 12415

SimpleDateFormat - Timezone not correct

I have a problem in parsing timestampls in Java.

I would expect to have both timestamps in the same timezone (CET).

    SimpleDateFormat sdaf = new SimpleDateFormat ("dd.MM.yyyy HH:mm:ss");

    String str = "30.03.2013 06:00:00";
    sdaf.setTimeZone (TimeZone.getTimeZone ("CET"));
    java.util.Date dat = sdaf.parse (str);
    System.out.println (str + " = " + dat);

    str = "31.03.2013 05:00:00";
    sdaf.setTimeZone (TimeZone.getTimeZone ("CET"));
    dat = sdaf.parse (str);
    System.out.println (str + " = " + dat);

But that is not the case - see the output.

30.03.2013 06:00:00 = Sat Mar 30 06:00:00 CET 2013
31.03.2013 05:00:00 = Sun Mar 31 05:00:00 CEST 2013

EDIT:

If I change CET with GMT+1 I get this.

 03.2013 06:00:00 = Sat Mar 30 06:00:00 CET 2013
 31.03.2013 05:00:00 = Sun Mar 31 06:00:00 CEST 2013

Seems to be correct. But why is CET not working?

UTC+1 produces

30.03.2013 06:00:00 = Sat Mar 30 07:00:00 CET 2013
31.03.2013 05:00:00 = Sun Mar 31 07:00:00 CEST 2013

what is different to GMT+1 - ????

Upvotes: 3

Views: 4809

Answers (3)

Anonymous
Anonymous

Reputation: 86379

AxelH’s answer is correct. Thus I don’t think you really want Central European (Standard) Time for your date-time on 31st March.

I should like to make three other points:

  • You should never rely on any three or four letter time zone abbreviation, like CET.
  • If you really want Central European Time, it is possible since two African countries use CET all year, Algeria and Tunesia.
  • Avoid the outdated SimpleDateFormat, TimeZone and Date and use java.time, the modern Java date and time API, instead.

So my code suggestion is:

    ZoneId cetAllYear = ZoneId.of("Africa/Algiers");
    DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd.MM.uuuu HH:mm:ss");
    DateTimeFormatter demoFormatter 
            = DateTimeFormatter.ofPattern("EEE MMM dd HH:mm:ss z yyyy", Locale.ROOT);

    String str = "31.03.2013 05:00:00";
    ZonedDateTime dateTime = LocalDateTime.parse(str, formatter).atZone(cetAllYear);
    System.out.println (str + " = " + dateTime 
                            + " = " + dateTime.format(demoFormatter));

Output:

31.03.2013 05:00:00 = 2013-03-31T05:00+01:00[Africa/Algiers] = Sun Mar 31 05:00:00 CET 2013

The same is possible with Africa/Tunis time zone.

Avoid three letter time zone abbreviations. Central European Time is a common name for the standard time at offset +01:00 used 5 months of the year in a large number of European time zones. So in one way it’s only half a time zone, in another way it’s many, and you don’t know which one you get. And even less so when you give a date-time that falls in the summer time (DST time of the year). Very many three and four letter abbreviations are ambiguous. Instead give time zone as for example Europe/Rome or Africa/Tunis, as region/city.

Avoid SimpleDateFormat and its outdated friends. That class is notoriously troublesome. java.time is so much nicer to work with.

Links

Upvotes: 2

AxelH
AxelH

Reputation: 14572

You can't get a CET time zone for the 31.03.2013 05:00:00 because it was not on that timezone anymore. To understand, just check the name of both timezone

  • CET : Central European Time (UTC+1 or GMT+1)
  • CEST : Central European Summer Time (UTC+2 or GMT+2)

That's the Saving Daylight Time that occured during the 31.03.2013 at 02:00:00. So you can't get a CET timezone for the second date since it is on the summer "time zone".

If you parse 31.03.2013 02:00:00 you will get

31.03.2013 02:00:00 = Sun Mar 31 03:00:00 CEST 2013

Because at 02:00:00 that day, the saving daylight time happened and it became 03:00:00.

You can check that using TimeZone.inDaylightTime(Date)

String str = "30.03.2013 06:00:00";
java.util.Date dat = sdaf.parse (str);
System.out.println (str + " = " + dat);
System.out.println("SDT : " + TimeZone.getTimeZone("CET").inDaylightTime(dat));

30.03.2013 06:00:00 = Sat Mar 30 06:00:00 CET 2013
SDT : false

str = "31.03.2013 02:00:00";
dat = sdaf.parse (str);
System.out.println (str + " = " + dat);
System.out.println("SDT : " + TimeZone.getTimeZone("CET").inDaylightTime(dat));

31.03.2013 02:00:00 = Sun Mar 31 03:00:00 CEST 2013
SDT : true

Since CET is the same as UTC+1 or GMT+1 and CEST become UTC+2 or GMT+2, when you force the date to be on GMT+1, you get the equivalent of the CET but without taking into account the SDT parameter.

Note : This is one of the reason LocalDateTime don't bother with TimeZone for most of the processing.

Upvotes: 4

Hatice
Hatice

Reputation: 944

You can use Java 8 and it is more clear and simple than this one.

DateTimeFormatter parse = DateTimeFormatter.ofPattern("dd.MM.yyyy hh:mm:ss.XXX");
LocalDate localDate = LocalDate.of(2013,3,30);
LocalTime localTime = LocalTime.of(6,0);

LocalDateTime dateTime = LocalDateTime.of(localDate, localTime);
ZonedDateTime zonedDateTime = dateTime.atZone(ZoneId.of("CET"));

System.out.println(zonedDateTime.format(parse));

Output : 30.03.2013 06:00:00.+01:00

Upvotes: 1

Related Questions