0

This code:

DateTimeParser[] parsers = { DateTimeFormat.forPattern("dd/MM/yyyy HH:mm:ss zzz").getParser(),
DateTimeFormat.forPattern("dd/MM/yyyy HH:mm:ss").getParser(), DateTimeFormat.forPattern("dd/MM/yyyy HH:mm").getParser(),
DateTimeFormat.forPattern("HH:mm").getParser() };
DateTimeFormatter formatter = new DateTimeFormatterBuilder().append(null, parsers).toFormatter();

Session session;
DateTime dTime = null;
Calendar calendar;

try{
    if (completedTime != null && !completedTime.equalsIgnoreCase("")){
        LocalDateTime jt = LocalDateTime.parse(completedTime, formatter);
        LocalDateTime dt;
        LocalDateTime retDate;

produces the error:

java.lang.IllegalArgumentException: Invalid format: "09/05/2015 04:00:00 GDT" is malformed at " GDT" at the LocalDateTime jt = LocalDateTime.parse(completedTime, formatter); line

I can't for the life of me work out why it is failing. I am pretty sure it is something simple, but I haven't spotted it.

TT.
  • 15,774
  • 6
  • 47
  • 88
Rob Mason
  • 1,385
  • 10
  • 23
  • 1
    Are you sure that `GDT` is a time zone identifier that is supported? – Jesper May 08 '15 at 17:50
  • shouldn't it be `z`? ; I think only `z` for the short version and `zzzz` for the full text version exists. – bvdb May 08 '15 at 18:23
  • As far as I can tell, GDT is a synonym for BST (British Summer Time) on the database platform I am using. As it is immaterial to the system I am working on, I am just stripping it out to handle the issue. – Rob Mason May 11 '15 at 19:35

3 Answers3

1

You may want to refer to this thread (or one of the many others like it). My best advice would be to try cutting to only one "z" in your parser.

Community
  • 1
  • 1
Ivan1211
  • 181
  • 1
  • 7
0

First thing to note:

What is "GDT"? The website http://www.timeanddate.com/time/zones/ does not yield an answer. So if it really exists and is not a typo then what is your locale? Remember that time zone names and abbreviations are highly localized.

Second: The count of pattern symbols "z" is okay - for classes like SimpleDateFormat etc. - see its documentation. Either four letters for the full name or less than four letters for the abbreviation:

General time zone: Time zones are interpreted as text if they have names. Text: For formatting, if the number of pattern letters is 4 or more, the full form is used; otherwise a short or abbreviated form is used if available. For parsing, both forms are accepted, independent of the number of pattern letters.

But you use Joda-Time. Its documentation clearly states:

Zone names: Time zone names ('z') cannot be parsed.

I have verified this non-support using the newest Joda-Time version 2.7 by following code:

    DateTimeFormatter formatter = DateTimeFormat.forPattern("dd/MM/yyyy HH:mm:ss z").withLocale(Locale.GERMANY);
    DateTime dt = formatter.parseDateTime("09/05/2015 04:00:00 MESZ");
    System.out.println("Joda-Time: " + dt);
    // Exception in thread "main" java.lang.IllegalArgumentException: Invalid format: "09/05/2015 04:00:00 MESZ" is malformed at "MESZ"

Of course, "MESZ" is correct and must be interpreted as Europe/Berlin in context of given german locale.

However, since version update (2.2) the same code set to Locale.US works for some timezones names like "EDT", "PST" etc., see also this commit. So we can finally say, the parsing support of Joda-Time for timezone names and abbreviations is best to say very limited. Once again, what is your Locale? If it is not US then I can understand why you get the exception. And you will also get an exception for the input "GDT" even if we consider it as valid due to the limited capabilities of Joda-Time-parser.

Meno Hochschild
  • 42,708
  • 7
  • 104
  • 126
0

You need to manually specify a mapping from timezone abbreviation to timezone. For example:

    return new DateTimeFormatterBuilder()
                .appendPattern("dd/MM/yyyy HH:mm:ss ")
                .appendTimeZoneShortName(UK_TIMEZONE_SYMBOLS)
                .toFormatter();

Here UK_TIMEZONE_SYMBOLS is a Map<String,DateTimeZone> which contains our view of timezone names (so BST is British summer time, not Bangladesh standard time)

Here's how we build ours:

public static Map<String, String> buildTimeZoneSymbolMap(Locale locale) {
    Map<String, String> timeZoneSymbols = Maps.newLinkedHashMap();
    for (String[] zoneInfo : DateFormatSymbols.getInstance(locale).getZoneStrings()) {
        String timeZone = zoneInfo[0];
        if (!timeZoneSymbols.containsKey(zoneInfo[2])) {
            timeZoneSymbols.put(zoneInfo[2], timeZone);
        }
        if (zoneInfo[4] != null && !timeZoneSymbols.containsKey(zoneInfo[4])) {
            timeZoneSymbols.put(zoneInfo[4], timeZone);
        }
    }
    timeZoneSymbols.put("UTC", "GMT");
    return timeZoneSymbols;
}

public static Map<String, DateTimeZone> buildDateTimeZoneSymbolMap(Locale locale) {
    return Maps.transformValues(buildTimeZoneSymbolMap(locale), input -> DateTimeZone.forTimeZone(TimeZone.getTimeZone(input)));
}

public static final Map<String, DateTimeZone> UK_TIMEZONE_SYMBOLS = ImmutableMap.copyOf(buildDateTimeZoneSymbolMap(Locale.UK));
araqnid
  • 127,052
  • 24
  • 157
  • 134
  • What would UK_TIMEZONE_SYMBOLS look like? – doughgle Mar 01 '16 at 07:33
  • @doughgle just a Map from timezone string to recognise to the DateTimeZone instance to use, e.g. `ImmutableMap.of("GMT", DateTimeZone.UTC)`. We actually build ours on-the-fly from the locale data: I'll add the code into the answer. – araqnid Mar 01 '16 at 14:43