在Java中,如何获取时间戳为48962-08-06T23:16:59.000Z的即时对象

在Java中,如何获取时间戳为48962-08-06T23:16:59.000Z的即时对象,java,datetime,java-8,Java,Datetime,Java 8,我有一个日期字符串,我想将其解析为即时 48962-08-06T23:16:59.000Z但无法执行,因为大多数标准DateTimeFormatter规则都不支持它 参考: 下面是我使用自定义格式化程序尝试执行的操作 DateTimeFormatter formatter = new DateTimeFormatterBuilder() .appendValue(YEAR, 5, 10, SignStyle.EXCEEDS_PAD) .ap

我有一个日期字符串,我想将其解析为即时
48962-08-06T23:16:59.000Z
但无法执行,因为大多数标准DateTimeFormatter规则都不支持它

参考:

下面是我使用自定义格式化程序尝试执行的操作

    DateTimeFormatter formatter = new DateTimeFormatterBuilder()
            .appendValue(YEAR, 5, 10, SignStyle.EXCEEDS_PAD)
            .appendLiteral('-')
            .appendValue(MONTH_OF_YEAR, 2)
            .appendLiteral('-')
            .appendValue(DAY_OF_MONTH, 2)
            .appendLiteral('T')
            .appendValue(HOUR_OF_DAY, 2).appendLiteral(':')
            .appendValue(MINUTE_OF_HOUR, 2).appendLiteral(':')
            .appendValue(SECOND_OF_MINUTE, 2)
            .appendFraction(NANO_OF_SECOND, 0, 9, true)
            .appendLiteral('Z')
            .toFormatter();
    
    Instant value = Instant.from(formatter.parse("48962-08-06T23:16:59.000Z"));

但是它失败了,
无法从TemporalAccessor获取即时信息:{},ISO解析为+48962-08-06T23:16:59,类型为java.time.format.Parsed

在我的机器上,以下代码解析您未来的年份:

public static void main(String[] args) {
    String dateTime = "48962-08-06T23:16:59.000Z";
    DateTimeFormatter dtf = DateTimeFormatter.ofPattern("uuuuu-MM-dd'T'HH:mm:ss.SSSz");
    Instant instant = Instant.from(dtf.parse(dateTime));
    System.out.println(instant);
}
和产出

+48962-08-06T23:16:59Z
我认为您的代码的问题在于其中一行(或两行)

            .appendFraction(NANO_OF_SECOND, 0, 9, true)
            .appendLiteral('Z')
因为
字符串中
Z
前面和点后面的三位数字可能不是纳秒,而是秒的分数。
另外一条可能也有问题,但我不能告诉你原因。我只知道当模式中的
z
(小写)更改为
z
(大写)时,我的答案会引发异常


您可以在
DateTimeFormatter
中对其进行调整,然后再试一次,可能会奏效。

我同意您的看法,最好的解决方案是使用生成器。下面一个用4位和5位数字分析年份:

    DateTimeFormatter formatter = new DateTimeFormatterBuilder()
            .appendValue(ChronoField.YEAR, 4, 5, SignStyle.NOT_NEGATIVE)
            .appendPattern("-MM-dd'T'")
            .append(DateTimeFormatter.ISO_LOCAL_TIME)
            .appendOffsetId()
            .toFormatter();
    
    String dateTime = "48962-08-06T23:16:59.000Z";
    
    Instant i = formatter.parse(dateTime, Instant::from);
    
    System.out.println(i);
代码段的输出为:

+48962-08-06T23:16:59Z

您的基本问题是字符串不符合ISO 8601,这是java.time类默认解析的标准,也就是说,没有任何显式格式化程序。ISO 8601中允许使用4位数以上的年份,但需要一个符号(如上面的输出所示)

你的代码出了什么问题?Joachim Sauer的评论是正确的:硬编码
Z
作为文字是错误的。它与UTC的偏移量为0,需要将其解析为偏移量。由于格式化程序没有解析任何偏移量,因此无法根据解析的信息确定一个int时间点,即一个瞬间。这就是您的错误消息的含义:

无法从临时助理获取即时消息:{},ISO解析为+48962-08-06T23:16:59,类型为java.time.format.Parsed


这5位数字代表哪一年?是来自特定文化的日历,还是你真的想解析这么远的将来的一年?@Fildor Instant支持max to
+100000000-12-31T23:59:59.9999999z
,那么我们如何解析它呢?@Fildor对我来说,这个问题似乎很明显,尽管他可能应该提到它。这就是“如何获得时间戳为48962-08-06T23:16:59.000Z的即时对象?”@deHaar只是我们需要的某个未来日期parse@IvoBeckersUpdateEdit肯定是
Z
,这就是问题所在。OP解析基本上是
LocalDateTime
:即没有时区信息的日期和时间。如果不知道应用哪个时区,就不能将其转换为即时的。因此,他们需要从外部提供时区(通过转换为
LocalDateTime
,然后使用
toInstant()
,提供时区),或者通过将
.appendLiteral('Z')
替换为
.appendZoneId()
来更改解析规则,将
Z
解释为UTC指示符。