为什么Java的java.time.format.DateTimeFormatter#format(LocalDateTime)增加了一年?



这是代码:

LocalDateTime localDateTime = LocalDateTime.ofInstant(Instant.ofEpochMilli(1451438792953L), ZoneId.of("UTC"));
DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("YYYY-MM-dd'T'HH:mm:ss.SSS'Z'");
String output = dateTimeFormatter.format(localDateTime);

这是localDateTime:的值

2015-12-30T01:26:32.953

这是output:的值

2016-12-30T01:26:32.953Z

为什么它增加了一年?

java.time.temporal.WeekFields中,有几种方法的newYearWeek有时会使年份增加1。为什么?

这是一个奇怪的虫子。

来自维基百科:

[YYYY]表示ISO周编号年份,略不同于传统的公历年(见下文)。

  1. YYYY是一个ISO-8601风格的年份表示
  2. yyyy是表示时代的公历年份

由于两者的计算可以相差+1或-1,因此格式化。有关YEAR_OF_ERAYEARweekBasedYear的更多有用信息。

您的代码中有五个问题

问题#1

LocalDateTime不应该有时区信息,但您通过在DateTimeFormatter模式中强制放置'Z'来格式化它。

问题#2

请注意,"Z"与Z不同。因此,您不应在API的日期时间格式化/解析中使用"Z"。

问题#3

Y(基于周的年份)与y(年代的年份)不同。查看此问答,了解更多关于这两者之间的区别。

问题#4

如果只需要指定UTC时区偏移量,则应使用ZoneOffset.UTCZoneId更适合以地区/时区参考城市格式指定时区ID,例如Europe/London

问题#5

对于所需的输出,不需要DateTimeFormatterjava.time API基于ISO 8601标准,因此java.time类型的toString实现默认返回ISO 8601格式的字符串。您所需要的只是Instant:的字符串表示

String output = Instant.ofEpochMilli(1451438792953L).toString();

输出中的Z(代表祖鲁语)以UTC表示日期时间,ZoneOffset+00:00

演示

import java.time.Instant;
public class Main {
    public static void main(String[] args) {
        String output = Instant.ofEpochMilli(1451438792953L).toString();
        System.out.println(output);
    }
}

输出

2015-12-30T01:26:32.953Z

跟踪:日期时间了解有关现代日期时间API的更多信息。

最新更新