使用 ThreetenBp 解析 DateTime 会导致 DateTimeParseException 或不完整的字符串错误
parsing DateTime with ThreetenBp causes DateTimeParseException or incomplete string error
我正在尝试检查日期是否已超过一天。
我在解析字符串时遇到了这些错误。
java.lang.IllegalArgumentException: Pattern ends with an incomplete string literal: uuuu-MM-dd'T'HH:mm:ss'Z
org.threeten.bp.format.DateTimeParseException: Text '2020-04-04T07:05:57+00:00' could not be parsed, unparsed text found at index 19
我的数据示例在这里:
val lastDate = "2020-04-04T07:05:57+00:00"
val serverFormat = "uuuu-MM-dd'T'HH:mm:ss'Z"
val serverFormatter =
DateTimeFormatter
.ofPattern(serverFormat)
val serverDateTime =
LocalDateTime
.parse(
lastDate,
serverFormatter
)
.atZone(ZoneId.of("GMT"))
val clientDateTime =
serverDateTime
.withZoneSameInstant(ZoneId.systemDefault())
val timeDiff =
ChronoUnit.DAYS.between(
serverDateTime,
clientDateTime
我试过这些:
uuuu-MM-dd\'T\'HH:mm:ss\'Z
yyyy-MM-dd\'T\'HH:mm:ss\'Z
uuuu-MM-dd\'T\'HH:mm:ss
uuuu-MM-dd'T'HH:mm:ss'Z
yyyy-MM-dd'T'HH:mm:ss'Z
uuuu-MM-dd'T'hh:mm:ss'Z
yyyy-MM-dd'T'hh:mm:ss'Z
yyyy-MM-dd HH:mm:ss
yyyy-MM-dd HH:mm:ssZ
yyyy-MM-dd'T'HH:mm:ss
yyyy-MM-dd'T'HH:mm:ssZ
yyyy-MM-dd'T'HH:mm:ss
其中 none 有效...正确的方法是什么?
您不需要任何明确的格式化程序。在Java(因为这是我能写的):
String lastDate = "2020-04-04T07:05:57+00:00";
OffsetDateTime serverDateTime = OffsetDateTime.parse(lastDate);
ZonedDateTime clientDateTime
= serverDateTime.atZoneSameInstant(ZoneId.systemDefault());
System.out.println("serverDateTime: " + serverDateTime);
System.out.println("clientDateTime: " + clientDateTime);
我所在时区的输出:
serverDateTime: 2020-04-04T07:05:57Z
clientDateTime: 2020-04-04T09:05:57+02:00[Europe/Copenhagen]
来自您的服务器的字符串格式是 ISO 8601。类 或 java.time 将最常见的 ISO 8601 变体解析为默认值,即没有指定任何格式器。
由于来自您服务器的字符串具有 UTC 偏移量 +00:00,并且没有时区,例如 Asia/Seoul,因此 OffsetDateTime
是使用它的最佳且最正确的时间。另一方面,客户端时间有时区,所以ZonedDateTime
在这里没问题。
由于服务器时间和客户端时间表示相同的时间,因此差异始终为零:
Duration difference = Duration.between(serverDateTime, clientDateTime);
System.out.println(difference);
PT0S
读取为 0 秒的时间段(这也是 ISO 8601 格式)。
如果你想知道当前时间和服务器时间的时差,使用now()
:
Duration difference = Duration.between(serverDateTime, OffsetDateTime.now());
System.out.println(difference);
你的代码出了什么问题?
首先,字符串中的 UTC 偏移量是 +00:00
。格式模式字母 Z
和文字 Z
都不会与此匹配。所以不要那样做。其次,从不 在格式模式字符串中将 Z
作为用单引号括起来的文字。当 Z
作为偏移量出现时,这很常见,您需要将其解析为偏移量,而不是文字。第三,格式模式字符串中的文字文本需要前后有一个单引号。您对中间的 T
做的是正确的。如果你不想 Z
是一个文字,不要在它前面加上单引号。如果你做了 意味着它是一个字面意思——就像我说的,那就不要。
链接
我正在尝试检查日期是否已超过一天。
我在解析字符串时遇到了这些错误。
java.lang.IllegalArgumentException: Pattern ends with an incomplete string literal: uuuu-MM-dd'T'HH:mm:ss'Z
org.threeten.bp.format.DateTimeParseException: Text '2020-04-04T07:05:57+00:00' could not be parsed, unparsed text found at index 19
我的数据示例在这里:
val lastDate = "2020-04-04T07:05:57+00:00"
val serverFormat = "uuuu-MM-dd'T'HH:mm:ss'Z"
val serverFormatter =
DateTimeFormatter
.ofPattern(serverFormat)
val serverDateTime =
LocalDateTime
.parse(
lastDate,
serverFormatter
)
.atZone(ZoneId.of("GMT"))
val clientDateTime =
serverDateTime
.withZoneSameInstant(ZoneId.systemDefault())
val timeDiff =
ChronoUnit.DAYS.between(
serverDateTime,
clientDateTime
我试过这些:
uuuu-MM-dd\'T\'HH:mm:ss\'Z
yyyy-MM-dd\'T\'HH:mm:ss\'Z
uuuu-MM-dd\'T\'HH:mm:ss
uuuu-MM-dd'T'HH:mm:ss'Z
yyyy-MM-dd'T'HH:mm:ss'Z
uuuu-MM-dd'T'hh:mm:ss'Z
yyyy-MM-dd'T'hh:mm:ss'Z
yyyy-MM-dd HH:mm:ss
yyyy-MM-dd HH:mm:ssZ
yyyy-MM-dd'T'HH:mm:ss
yyyy-MM-dd'T'HH:mm:ssZ
yyyy-MM-dd'T'HH:mm:ss
其中 none 有效...正确的方法是什么?
您不需要任何明确的格式化程序。在Java(因为这是我能写的):
String lastDate = "2020-04-04T07:05:57+00:00";
OffsetDateTime serverDateTime = OffsetDateTime.parse(lastDate);
ZonedDateTime clientDateTime
= serverDateTime.atZoneSameInstant(ZoneId.systemDefault());
System.out.println("serverDateTime: " + serverDateTime);
System.out.println("clientDateTime: " + clientDateTime);
我所在时区的输出:
serverDateTime: 2020-04-04T07:05:57Z clientDateTime: 2020-04-04T09:05:57+02:00[Europe/Copenhagen]
来自您的服务器的字符串格式是 ISO 8601。类 或 java.time 将最常见的 ISO 8601 变体解析为默认值,即没有指定任何格式器。
由于来自您服务器的字符串具有 UTC 偏移量 +00:00,并且没有时区,例如 Asia/Seoul,因此 OffsetDateTime
是使用它的最佳且最正确的时间。另一方面,客户端时间有时区,所以ZonedDateTime
在这里没问题。
由于服务器时间和客户端时间表示相同的时间,因此差异始终为零:
Duration difference = Duration.between(serverDateTime, clientDateTime);
System.out.println(difference);
PT0S
读取为 0 秒的时间段(这也是 ISO 8601 格式)。
如果你想知道当前时间和服务器时间的时差,使用now()
:
Duration difference = Duration.between(serverDateTime, OffsetDateTime.now());
System.out.println(difference);
你的代码出了什么问题?
首先,字符串中的 UTC 偏移量是 +00:00
。格式模式字母 Z
和文字 Z
都不会与此匹配。所以不要那样做。其次,从不 在格式模式字符串中将 Z
作为用单引号括起来的文字。当 Z
作为偏移量出现时,这很常见,您需要将其解析为偏移量,而不是文字。第三,格式模式字符串中的文字文本需要前后有一个单引号。您对中间的 T
做的是正确的。如果你不想 Z
是一个文字,不要在它前面加上单引号。如果你做了 意味着它是一个字面意思——就像我说的,那就不要。