我正在使用以下 ISO8601 格式:
YYYY-MM-DDThh:mm:ssZ
我曾经OffsetDateTime.parse()
解析过这种格式。我能够通过在这里传递t
(而不是T
)和z
(而不是)来解析日期时间Z
。
那么任何人都可以判断它是否在ISO8601中被允许,还是仅在解析逻辑中被遗漏?
我正在使用以下 ISO8601 格式:
YYYY-MM-DDThh:mm:ssZ
我曾经OffsetDateTime.parse()
解析过这种格式。我能够通过在这里传递t
(而不是T
)和z
(而不是)来解析日期时间Z
。
那么任何人都可以判断它是否在ISO8601中被允许,还是仅在解析逻辑中被遗漏?
那么任何人都可以判断它是否在 ISO8601 中被允许,还是仅在解析逻辑中被遗漏?
我不认为生成它们是有效的,尽管我猜解析器允许它很好(虽然不是很好)。
我可以访问的规范 EBNF(8601-1 DIS 附录 A)对所有指示符仅使用大写拉丁字母,无论它们是 Z、T、W、R、P、Y、M、D、H、M 还是 S,与(非 A)BNF 不同,据我所知,EBNF 终端区分大小写。
Z
不一样z
。DateTimeFormatter
将前者评估为zone-offset,而将后者评估为time-zone name。
另一个例子是M
它用于month-of-year和m
它用于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”)来解析日期时间。
我已经解释了Z
和z
。让我们专注于T
和t
。如果你仔细观察,你会发现我在T
ie周围使用了单引号,'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 的更多信息。
虽然我在这一点上不了解 ISO 8601,但据记载,Java 的 one-argOffsetDateTime.parse(CharSequence)
允许大小写T
和Z
.
文档说:
该字符串必须表示一个有效的日期时间,并使用
DateTimeFormatter.ISO_OFFSET_DATE_TIME
.
的文档DateTimeFormatter.ISO_OFFSET_DATE_TIME
说格式包括:
- 这
ISO_LOCAL_DATE_TIME
- 偏移 ID。… 解析不区分大小写。
最后一句允许大写Z
和小写z
进行偏移。的文档ISO_LOCAL_DATE_TIME
说T
:
- 字母“T”。解析不区分大小写。
所以这允许大写T
和小写t
。
我们不应该相信 Java 会告诉我们有关标准的真相。似乎 ISO 8601 标准是一个秘密,除非您支付副本费用(说服人们遵循标准恕我直言的有趣方式)。有一篇关于标准的精美维基百科文章。它以大写字母给出字母,但也没有提及是否也允许小写字母。