Java的8 DateTimeFormatter拒绝正确的ISO 8601日期/时间偏移

问题描述 投票:4回答:3

我用DateTimeFormatter格式字符串:★★★★-MM-dd'T'HH:MM:SSX

其必须支持时区的所有可能的格式偏移,包括:Z,00,00:00,0000

据官方DateTimeFormatter文件,“X”限定符必须匹配这些格式,以抵消:

X区偏移 'Z' 为零点偏移-X Z; -08; -0830; -08:30; -083015; -08:30:15;

但事实上,它不

输入字符串: “2014-01-01T00:30:00 + 00:00”

结果:java.time.format.DateTimeParseException:文本 '2014-01-01T00:30:00 + 00:00' 无法解析,索引22发现未解析文本

输入字符串: “2014-01-01T00:30:00Z”

结果:正确

编码:

DateTimeFormatter formatter = DateTimeFormatter.ofPattern("uuuu-MM-dd'T'HH:mm:ssX");
OffsetDateTime parsed = OffsetDateTime.parse(dateTimeAsString, formatter);

JDK 1.8.0_192(甲骨文,而不是OpenJDK的)

java date time iso8601
3个回答
6
投票

这是一个有点复杂。 As jvdmr says,各X事项的计数。 XXXXX将认识-08:30:15,但不-083015XXXX会认识后者,而不是前者。

要采取一切可能的例子格式考虑,我们需要指定不同的可能性。这可以用方括号中的格式模式字符串内完成。这些包含可选部分。一些实验表明,以下模式涵盖了所有的例子:

uuuu-MM-dd'T'HH:mm:ss[XXXXX][XXXX][X]

让我们来尝试一下:

    DateTimeFormatter formatter
            = DateTimeFormatter.ofPattern("uuuu-MM-dd'T'HH:mm:ss[XXXXX][XXXX][X]");
    for (String dts : new String[] {
            "2014-01-01T00:30:00-08:30:15", "2014-01-01T00:30:00-083015",
            "2014-01-01T00:30:00-08:30", "2014-01-01T00:30:00-0830",
            "2014-01-01T00:30:00-08", "2014-01-01T00:30:00Z",
    }) {
        System.out.println(OffsetDateTime.parse(dts, formatter));
    }

从这个片断的输出是:

2014-01-01T00:30-08:30:15
2014-01-01T00:30-08:30:15
2014-01-01T00:30-08:30
2014-01-01T00:30-08:30
2014-01-01T00:30-08:00
2014-01-01T00:30Z

编辑

VelNaga suggests没有硬编码ISO日期时间格式。由于书写格式模式字符串容易出错,这可能是一个好主意。例如:

    DateTimeFormatter formatter = new DateTimeFormatterBuilder()
            .append(DateTimeFormatter.ISO_LOCAL_DATE_TIME)
            .appendPattern("[XXXXX][XXXX][X]")
            .toFormatter();

使用该格式器输出是相同的,与使用上述的一个。这是wordier,但我们可以很容易地最终认为这是值得的,因为它是容易出错以下,可更清晰,更易于阅读。


5
投票

docs(重点煤矿):

偏移x和x:该格式化偏移基于模式字母的数目。一个字母就在小时的输出,如“01”,除非分钟非零在这种情况下,分也被输出,如“0130”。两个字母输出的小时和分钟,没有结肠,如“0130”。三个字母输出小时和分钟,以冒号,例如“01:30”。四个字母输出小时和分钟和任选的第二未经结肠,如“013015”。五个字母输出小时和分钟和任选的第二,以冒号,例如“01:30:15”。六个或多个字母抛出IllegalArgumentException异常。图案字母“X”(大写)会输出“Z”当偏移要输出将为零,而图案字母“X”(小写)会输出“00”,“0000”,或“00 :00' 。

这也适用于反向解析日期。你想既没有冒号解析,这意味着你将不得不使用可选的部分,因为没有单一的模式支持这一点。试试这个模式:"uuuu-MM-dd'T'HH:mm:ss[XXX][XXXX]"


0
投票

不要硬编码任何ISO日期格式。 DateFormatter已经为ISO日期格式转换的静态方法。使用下面的代码,

DateTimeFormatter格式化= DateTimeFormatter.ISO_ZONED_DATE_TIME;

OffsetDateTime解析= OffsetDateTime.parse(dateTimeAsString,格式化器);

这将肯定工作。详情请见link更多的格式选项。

© www.soinside.com 2019 - 2024. All rights reserved.