54

This snippet of code always parses the date into the current timezone, and not into the timezone in the string being parsed.

final DateTimeFormatter df = DateTimeFormat
        .forPattern("EEE MMM dd HH:mm:ss 'GMT'Z yyyy");
final DateTime dateTime = df
        .parseDateTime("Mon Aug 24 12:36:46 GMT+1000 2009");
System.out.println("dateTime = " + dateTime);
// outputs dateTime = 2009-08-24T04:36:46.000+02:00

It outputs:

dateTime = 2009-08-24T04:36:46.000+02:00

whereas I expect:

dateTime = 2009-08-24T04:36:46.000+10:00

Any ideas what I'm doing wrong?

JJD
  • 50,076
  • 60
  • 203
  • 339
Steve McLeod
  • 51,737
  • 47
  • 128
  • 184

3 Answers3

78

OK, further Googling gave me the answer to my own question: use withOffsetParsed(), as so:

final DateTimeFormatter df = DateTimeFormat
        .forPattern("EEE MMM dd HH:mm:ss 'GMT'Z yyyy");
final DateTime dateTime = df.withOffsetParsed()
        .parseDateTime("Mon Aug 24 12:36:46 GMT+1000 2009");

This works.

Björn Pollex
  • 75,346
  • 28
  • 201
  • 283
Steve McLeod
  • 51,737
  • 47
  • 128
  • 184
  • 8
    IMO, the default behavior of `DateTimeFormatter` seems to violate "principle of least astonishment", especially in the context of an unmarshaller. Thank you Steve for unearthing `withOffsetParsed()`. – David J. Liszewski May 20 '15 at 02:46
  • I have to agree that the default behaviour - i.e. ignoring a properly parsed timezone - is bizarre. – Clyde Nov 22 '17 at 05:45
37

also you can chose:

// parse using the Paris zone
DateTime date = formatter.withZone(DateTimeZone.forID("Europe/Paris")).parseDateTime(str);
z0mb1ek
  • 899
  • 9
  • 16
1

java.time

Quoted below is a notice from the home page of Joda-Time:

Note that from Java SE 8 onwards, users are asked to migrate to java.time (JSR-310) - a core part of the JDK which replaces this project.

Do not use a fixed text for the timezone:

Do not use a fixed text (e.g. 'GMT') for the timezone as you have done because that approach may fail for other locales.

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

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

public class Main {
    public static void main(String[] args) {
        String strDateTime = "Mon Aug 24 12:36:46 GMT+1000 2009";
        DateTimeFormatter parser = DateTimeFormatter.ofPattern("E MMM d H:m:s VVZ u", Locale.ENGLISH);
        OffsetDateTime odt = OffsetDateTime.parse(strDateTime, parser);
        System.out.println(odt);

        // Custom fromat
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("uuuu-MM-dd'T'HH:mm:ss.SSSXXX", Locale.ENGLISH);
        System.out.println(formatter.format(odt));
    }
}

Output:

2009-08-24T12:36:46+10:00
2009-08-24T12:36:46.000+10:00

ONLINE DEMO

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
  • I prefer `'GMT'Z`. `GMT+1000` are not two pieces of information, `GMT` and `+1000` (which would have contradicted each other), but one piece. When we cannot parse as one piece, I prefer only to parse the bit that holds relevant information, that is `+1000`. If one day (however unlikely) someone parsed into a `ZonedDateTime` using your formatter, they would get a result that was 10 hours off. Your `VV` will tell the reader that `GMT` is the zone ID of the date and time, which is not the case, so it will confuse rather than help. – Ole V.V. Jul 11 '21 at 09:25
  • 1
    @OleV.V. - "If one day (however unlikely) someone parsed into a ZonedDateTime using your formatter, they would get a result that was 10 hours off." - This is not correct. `System.out.println(ZonedDateTime.parse(strDateTime, parser))` gives `2009-08-24T02:36:46Z[GMT]` which represents the same instant/moment in time i.e. `2009-08-24T12:36:46+10:00` = `2009-08-24T02:36:46Z[GMT]`. – Arvind Kumar Avinash Jul 11 '21 at 09:34
  • Your code holds even more surprises than I had thought. While you get the correct instant, you don’t get the expected time of day nor the expected zone. (And on Java 8 I got `2009-08-24T12:36:46Z[GMT]`, may be a bug in Java 8.) – Ole V.V. Jul 11 '21 at 09:43
  • It must be a bug in Java 8. Ideone server currently uses Java-12 and [here](https://ideone.com/CKAvgA) are the results on it. – Arvind Kumar Avinash Jul 11 '21 at 09:53