6

Why: When I give input date string with GMT timezone, SimpleDateFormat parses it and outputs EET timezone?

public static String DATE_FORMAT="dd MMM yyyy hh:mm:ss z";
public static String CURRENT_DATE_STRING ="31 October 2011 11:19:56 GMT";
...
SimpleDateFormat simpleDateFormat =  new SimpleDateFormat(DATE_FORMAT, Locale.US);
simpleDateFormat.setTimeZone(TimeZone.getTimeZone("GMT"));
System.out.println(simpleDateFormat.parseObject(CURRENT_DATE_STRING));

And the output is:

Mon Oct 31 13:19:56 EET 2011

rather than

Mon Oct 31 13:19:56 GMT 2011

Arvind Kumar Avinash
  • 71,965
  • 6
  • 74
  • 110
IgorDiy
  • 919
  • 1
  • 12
  • 25

2 Answers2

10

You're printing out the result of Date.toString(). A Date doesn't have any concept of a timezone - it's just the number of milliseconds since the UTC Unix epoch. Date.toString() always uses the system default time zone.

Note that you shouldn't be expecting "Mon Oct 31 13:19:56 GMT 2011" given that you've given a time which specifies a GMT hour of 11, not 13.

If you want to use a specific time zone for printing, you should use another DateFormat for the printing, rather than using Date.toString(). (Date.toString() keeps causing confusion like this; it's really unfortunate.)

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
0

java.util.Date does not hold timezone information.

A java.util.Date object simply represents the number of milliseconds since the standard base time known as "the epoch", namely January 1, 1970, 00:00:00 GMT (or UTC). Since it does not hold any timezone information, its toString function applies the JVM's timezone to return a String in the format, EEE MMM dd HH:mm:ss zzz yyyy, derived from this milliseconds value. To get the String representation of the java.util.Date object in a different format and timezone, you need to use SimpleDateFormat with the desired format and the applicable timezone.

Apart from this, there are a couple of problems with your code:

  1. Use H instead of h for the 24-Hour format. The letter, h is used for the 12-Hour format (i.e. with AM/PM marker).
  2. Even though MMM works for parsing the long name of the month (e.g. January) with SimpleDateFormat, it is meant for the 3-letter month name (e.g. Jan). If you try doing it with the modern Date-Time API, you will be greeted with the DateTimeParseException. You should use MMMM for the long name of the month.

Demo incorporating these points:

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
import java.util.TimeZone;

public class Main {
    public static void main(String[] args) throws ParseException {
        String strDateTime = "31 October 2011 11:19:56 GMT";

        SimpleDateFormat sdf = new SimpleDateFormat("dd MMMM yyyy HH:mm:ss z", Locale.ENGLISH);
        sdf.setTimeZone(TimeZone.getTimeZone("GMT"));

        Date date = sdf.parse(strDateTime);

        String strDate = sdf.format(date);
        System.out.println(strDate);

        // Some other format
        sdf = new SimpleDateFormat("MMMM dd HH:mm:ss z yyyy", Locale.ENGLISH);
        sdf.setTimeZone(TimeZone.getTimeZone("GMT"));
        strDate = sdf.format(date);
        System.out.println(strDate);

        // The last format with some other timezone
        sdf.setTimeZone(TimeZone.getTimeZone("America/New_York"));
        strDate = sdf.format(date);
        System.out.println(strDate);
    }
}

Output:

31 October 2011 11:19:56 GMT
October 31 11:19:56 GMT 2011
October 31 07:19:56 EDT 2011

ONLINE DEMO

Switch to java.time API.

The java.util Date-Time API and their formatting API, SimpleDateFormat are outdated and error-prone. It is recommended to stop using them completely and switch to the modern Date-Time API*.

Solution using java.time, the modern Date-Time API:

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

public class Main {
    public static void main(String[] args) {
        String strDateTime = "31 October 2011 11:19:56 GMT";

        DateTimeFormatter dtf = DateTimeFormatter.ofPattern("dd MMMM uuuu HH:mm:ss z", Locale.ENGLISH);

        ZonedDateTime zdt = ZonedDateTime.parse(strDateTime, dtf);
        System.out.println(zdt);

        // Some other format
        DateTimeFormatter dtfAnother = DateTimeFormatter.ofPattern("MMMM dd HH:mm:ss z uuuu", Locale.ENGLISH);
        String strDate = dtfAnother.format(zdt);
        System.out.println(strDate);
    }
}

Output:

2011-10-31T11:19:56Z[GMT]
October 31 11:19:56 GMT 2011

ONLINE DEMO

The Z in the output is the timezone designator for zero-timezone offset. It stands for Zulu and specifies the Etc/UTC timezone (which has the timezone offset of +00:00 hours).

Learn more about 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.

Arvind Kumar Avinash
  • 71,965
  • 6
  • 74
  • 110