使用Joda Time

时间:2016-08-09 09:30:47

标签: jodatime simpledateformat java-time

我正在处理以下字符串:0022 GMT (0822 HKT) July 21, 2016

显然,这些字符串为两个不同的时区指定了两天的时间。 Joda Time' DateTimeFormat.forPattern()的模式语法可以处理这种冗余信息吗?

一种可能性是忽略两个时间表达式0022 GMT0822 HKT中的一个。这将需要某种通配符,该通配符可以与要忽略的时间表达式的部分匹配,这看起来像Hm z '(*)' MMM dd, y

在Joda Time的模式语法中是否存在可解析上述时间字符串的通配符或其他任何内容?

1 个答案:

答案 0 :(得分:1)

为了忽略潜在的矛盾部分(在其他区域重复小时,分钟和区域名称),您必须在 Joda-Time 中编写自己的DateTimeParser

DateTimeFormatter dtf =
    new DateTimeFormatterBuilder().appendPattern("HHmm 'GMT' (").append(
        new DateTimeParser() {
            @Override
            public int estimateParsedLength() {
                return 10;
            }
            @Override
            public int parseInto(DateTimeParserBucket bucket, String text, int position) {
                int pos = position;
                while (text.charAt(pos) != ')') {
                    pos++;
                }
                return pos;
            }
        }
    )
    .appendPattern(") MMMM dd, yyyy")
    .toFormatter()
    .withLocale(Locale.US)
    .withZoneUTC();

String input = "0022 GMT (0822 HKT) July 21, 2016";    
DateTime dt = dtf.parseDateTime(input);
System.out.println("Joda: " + dt); // 2016-07-21T00:22:00.000Z

为了您的信息,我认为没有办法在 Java-8 (没有输入预处理)中执行此操作,请参阅此示例,即使使用可选节也会引发异常。 Java-8缺乏编写自己的解析器的机制。

DateTimeFormatter dtf = 
  DateTimeFormatter.ofPattern("HHmm z ([HHmm z]) MMMM dd, uuuu", Locale.US);
ZonedDateTime zdt = ZonedDateTime.parse(input, dtf); // throws exception!!!
// java.time.format.DateTimeParseException: 
// Text '0022 GMT (0822 HKT) July 21, 2016' could not be parsed at index 10

旁注:当你可以探索我的库 Time4J 时,它提供了一个适合Java-8的替代性和更高性能的解析引擎,那么它提供了比Joda-Time更简单的解决方案,请看这个小{{ {3}}

另外,使用字符串预处理编写 hackish workaround 总是可行的(当不允许使用第三方库时很有趣):

String input = "0022 GMT (0822 HKT) July 21, 2016";
StringBuilder sb = new StringBuilder();
boolean markedForRemoval = false;
for (int i = 0; i < input.length(); i++) {
    char c = input.charAt(i);
    if (c == ')') {
        markedForRemoval = false;
    }
    if (!markedForRemoval) {
        sb.append(c);
    }
    if (c == '(') {
        markedForRemoval = true;
    }
}
input = sb.toString();
System.out.println(input); // 0022 GMT () July 21, 2016
// continue parsing the changed input based on a formatter of your choice