5

我正在使用以下 ISO8601 格式:

YYYY-MM-DDThh:mm:ssZ

我曾经OffsetDateTime.parse()解析过这种格式。我能够通过在这里传递t(而不是T)和z(而不是)来解析日期时间Z

那么任何人都可以判断它是否在ISO8601中被允许,还是仅在解析逻辑中被遗漏?

4

3 回答 3

3

那么任何人都可以判断它是否在 ISO8601 中被允许,还是仅在解析逻辑中被遗漏?

我不认为生成它们是有效的,尽管我猜解析器允许它很好(虽然不是很好)。

我可以访问的规范 EBNF(8601-1 DIS 附录 A)对所有指示符使用大写拉丁字母,无论它们是 Z、T、W、R、P、Y、M、D、H、M 还是 S,与(非 A)BNF 不同,据我所知,EBNF 终端区分大小写。

于 2020-12-01T08:35:04.833 回答
3

Z不一样z

DateTimeFormatter将前者评估为zone-offset,而将后者评估为time-zone name

另一个例子是M它用于month-of-yearm它用于minute-of-hour

日期、时间、时区等组件的符号区分大小写。检查 DateTimeFormatter以了解有关这些符号的更多信息。

快速演示:

import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;

public class Main {
    public static void main(String[] args) {
        ZonedDateTime odt = ZonedDateTime.now(ZoneId.of("Asia/Calcutta"));
        System.out.println(DateTimeFormatter.ofPattern("uuuu-MM-dd'T'HH:mm:ssZ").format(odt));
        System.out.println(DateTimeFormatter.ofPattern("uuuu-MM-dd'T'HH:mm:ssz").format(odt));
    }
}

输出:

2020-12-22T00:14:44+0530
2020-12-22T00:14:44IST

区域偏移量与时区不同。时区在表单中有一个 ID,Continent/City例如Asia/Calcutta,区域偏移量以小时和分钟表示,它表明一个地点的日期和时间与日期和时间偏移了多少小时和分钟UTC。因此,许多时区 ID 可以具有相同的时区偏移量。换句话说,区域偏移量可以从时区 ID 派生,但反过来是不可能的,例如在下面的演示中,OffsetDateTime将能够从时区 ID 确定区域偏移量,Asia/Calcutta但尝试获取时区名称(如上面的例子)使用z将失败。

import java.time.OffsetDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;

public class Main {
    public static void main(String[] args) {
        OffsetDateTime odt = OffsetDateTime.now(ZoneId.of("Asia/Calcutta"));
        System.out.println(DateTimeFormatter.ofPattern("uuuu-MM-dd'T'HH:mm:ssZ").format(odt));
        System.out.println(DateTimeFormatter.ofPattern("uuuu-MM-dd'T'HH:mm:ssz").format(odt));
    }
}

输出:

2020-12-22T00:30:40+0530
Exception in thread "main" java.time.DateTimeException: Unable to extract ZoneId from temporal 2020-12-22T00:30:40.865087+05:30
    at java.base/java.time.format.DateTimePrintContext.getValue(DateTimePrintContext.java:289)
    at java.base/java.time.format.DateTimeFormatterBuilder$ZoneTextPrinterParser.format(DateTimeFormatterBuilder.java:4072)
    at java.base/java.time.format.DateTimeFormatterBuilder$CompositePrinterParser.format(DateTimeFormatterBuilder.java:2341)
    at java.base/java.time.format.DateTimeFormatter.formatTo(DateTimeFormatter.java:1843)
    at java.base/java.time.format.DateTimeFormatter.format(DateTimeFormatter.java:1817)
    at Main.main(Main.java:9)

我使用“OffsetDateTime.parse()”(在 java 中)来解析这种格式。我可以通过在这里传递“t”(而不是“T”)和“z”(而不是“Z”)来解析日期时间。

我已经解释了Zz。让我们专注于Tt。如果你仔细观察,你会发现我在Tie周围使用了单引号,'T'这使它成为在日期时间字符串中使用的字符串文字。这意味着它可以是任何东西,例如't'or'Foo''Bar'。只要DateTimeFormatter匹配中的文字与日期时间字符串中的文字相同,它就可以正常工作。我在下面的演示中展示了它:

import java.time.OffsetDateTime;
import java.time.format.DateTimeFormatter;

public class Main {
    public static void main(String[] args) {
        String strDateTime = "2020-12-22T00:45:50+05:30";

        // The given string is already in the format which is use by OffsetDateTime for
        // parsing without a DateTimeFormatter
        OffsetDateTime odt = OffsetDateTime.parse(strDateTime);

        // Let's try to parse it using different types of DateTimeFormatter instances
        System.out.println(OffsetDateTime.parse(strDateTime, DateTimeFormatter.ofPattern("uuuu-MM-dd'T'HH:mm:ssXXX")));
        
        //The following line will fail as the literal does not match case-wise
        //System.out.println(OffsetDateTime.parse(strDateTime, DateTimeFormatter.ofPattern("uuuu-MM-dd't'HH:mm:ssXXX")));
        
        strDateTime = "2020-12-22t00:45:50+05:30";// Now, DateTimeFormatter with 't' will work successfully
        System.out.println(OffsetDateTime.parse(strDateTime, DateTimeFormatter.ofPattern("uuuu-MM-dd't'HH:mm:ssXXX")));
    }
}

输出:

2020-12-22T00:45:50+05:30
2020-12-22T00:45:50+05:30

从Trail: Date Time了解有关现代日期时间 API 的更多信息。

于 2020-12-21T19:37:20.703 回答
2

TL;博士

虽然我在这一点上不了解 ISO 8601,但据记载,Java 的 one-argOffsetDateTime.parse(CharSequence)允许大小写TZ.

跟踪文档

文档说:

该字符串必须表示一个有效的日期时间,并使用 DateTimeFormatter.ISO_OFFSET_DATE_TIME.

的文档DateTimeFormatter.ISO_OFFSET_DATE_TIME说格式包括:

  • ISO_LOCAL_DATE_TIME
  • 偏移 ID。… 解析不区分大小写。

最后一句允许大写Z和小写z进行偏移。的文档ISO_LOCAL_DATE_TIMET

  • 字母“T”。解析不区分大小写。

所以这允许大写T和小写t

我们不应该相信 Java 会告诉我们有关标准的真相。似乎 ISO 8601 标准是一个秘密,除非您支付副本费用(说服人们遵循标准恕我直言的有趣方式)。有一篇关于标准的精美维基百科文章。它以大写字母给出字母,但也没有提及是否也允许小写字母。

链接

于 2020-12-21T21:35:55.660 回答