java.lang.IllegalArgumentException: 格式无效

java.lang.IllegalArgumentException: Invalid format

此代码:

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;

产生错误:

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

我一辈子都弄不明白它为什么会失败。我很确定这很简单,但我还没有发现它。

您可能需要参考 this 话题(或许多其他类似话题之一)。我最好的建议是尝试在你的解析器中只削减一个 "z"。

首先要注意的是:

什么是"GDT"? 网站http://www.timeanddate.com/time/zones/ 没有给出答案。 因此,如果它真的存在并且不是拼写错误,那么您的语言环境是什么?请记住,时区名称和缩写是高度本地化的。

其次:模式符号的数量 "z" 没问题 - 对于 类 如 SimpleDateFormat 等 - 请参阅其 documentation.全名四个字母或缩写少于四个字母:

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.

但是你使用 Joda-Time。它的文档明确指出:

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

我已通过以下代码使用最新的 Joda-Time 2.7 版验证了此不支持:

    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"

当然,"MESZ" 是正确的,在给定的德语语言环境中必须解释为 Europe/Berlin

但是,自版本更新 (2.2) 以来,设置为 Locale.US 的相同代码适用于某些时区名称,例如 "EDT"、"PST" 等,另请参阅此 commit.所以我们最终可以说,Joda-Time 对时区名称和缩写的解析支持最好是非常有限。再一次,你的 Locale 是什么?如果不是美国,那么我可以理解为什么你会得到例外。即使由于 Joda-Time-parser 的功能有限,我们认为它是有效的,您也会得到输入 "GDT" 的异常。

您需要手动指定从时区缩写到时区的映射。例如:

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

这里UK_TIMEZONE_SYMBOLS是一个Map<String,DateTimeZone>,其中包含我们对时区名称的看法(所以BST是英国夏令时,不是孟加拉国标准时间)

我们的构建方式如下:

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));