使用Joda的DateTimeFormatter解析时如何忽略时区?

时间:2016-01-04 23:16:16

标签: java parsing jodatime datetime-format

我正在尝试从IPTC元数据中解析垃圾日期值。格式假设yyyyMMdd,但在某些情况下则不是。我发现的一个特定值是"Tue Jan 05 00:00:00 AEDT 2016"

如果我尝试使用Joda的DateTimeFormatter

解析它
DateTimeFormat.forPattern("EEE MMM dd HH:mm:ss Z yyyy")
              .parseLocalDate("Tue Jan 05 00:00:00 AEDT 2016");

这给了我一个错误:

java.lang.IllegalArgumentException: Invalid format: "Tue Jan 05 00:00:00 AEDT 2016" is malformed at "AEDT 2016"

我尝试过以下区域符号:

  • ž
  • ZZ
  • ž
  • ZZ
  • ZZZ

我意识到文档确实说DateTimeFormatter无法解析时区。我也意识到这些短时区名称含糊不清。但在这种情况下,我只是试图找出LocalDate,所以我真正想要的只是月,日和年。 (注意小时,分钟和秒也是零?)

我希望必须在字符串中间使用正则表达式废话,然后再将其传递出去,因为我正在通过此格式化程序来预期DateTimeFormatter目前。

有没有办法在解析时指定某种任意模式的垃圾扔掉?我似乎无法在API中找到它,但这并不一定意味着它不存在。

3 个答案:

答案 0 :(得分:3)

我会在此期间发布我自己的消息解决方法,它使用现有格式模式和自定义解析器的混合来丢弃时区。

DateTimeFormatter formatter = new DateTimeFormatterBuilder()
    .appendPattern("EEE MMM dd HH:mm:ss ")
    .append(DateTimeFormat.forPattern("Z").getPrinter(), new DiscardTimeZoneSymbolParser())
    .appendPattern(" yyyy")
    .toFormatter();

LocalDate localDate = formatter.parseLocalDate("Tue Jan 05 00:00:00 AEDT 2016");

然后:

public class DiscardTimeZoneSymbolParser implements DateTimeParser {
    @Override
    public int estimateParsedLength() {
        return 4;
    }

    @Override
    public int parseInto(DateTimeParserBucket bucket, @NonNls String text, int position) {
        for (int positionFromStart = 0; positionFromStart < 4; positionFromStart++, position++) {
            boolean match;
            if (position >= text.length()) {
                match = false;
            } else {
                @NonNls
                char ch = text.charAt(position);
                match = ch >= 'A' && ch <= 'Z';
            }

            if (!match) {
                if (positionFromStart >= 3) { // require 3 characters
                    return position;
                } else {
                    return ~position;
                }
            }
        }

        return position;
    }
}

答案 1 :(得分:0)

您可以使用java.text中的解析工具:

DateFormat df = new SimpleDateFormat("EEE MMM dd HH:mm:ss Z yyyy", Locale.ENGLISH);
df.setLenient(false);
Date date = df.parse("Tue Jan 05 00:00:00 AEDT 2016");

然后转换Joda java.util.Date中的LocalDate。请注意:

  • Date和LocalDate都没有时区:Date是UTC,LocalDate是指年代,而不是瞬间
  • 我为解析器指定了Locale,但您可能需要使用JMV的默认语言环境,或者根据您的输入使用任何其他语言环境

答案 2 :(得分:0)

所以问题是DateTimeFormatter的巨大界面阻止你轻松编写自己的实现或装饰器。

  

...我正在通过此格式化程序,希望目前只有DateTimeFormatter

重构框架(&#34;事情&#34;)是不可能的:

步骤1:创建新界面:

public interface LocalDateTimeParser {
    LocalDate parseLocalDate(String text);
}

第2步:创建适配器:

public final class DateTimeFormatterAdapter implements LocalDateTimeParser {

    private final DateTimeFormatter adaptee;

    public DateTimeFormatterAdapter(DateTimeFormatter adaptee){
        this.adaptee = adaptee;
    }

    public LocalDate parseLocalDate(String text){
        return adaptee.parseLocalDate(text);
    }
}

步骤2:在框架中引用LocalDateTimeParser,只需要进行本地解析,并将现有的DateTimeFormatter包装在适配器中。

第3步:现在,您可以使用正则表达式预处理编写自己的LocalDateTimeParser实现,以删除时区并将其余部分传递给DateTimeFormatter