当前位置: 首页 > 知识库问答 >
问题:

实现DateTimeFormatter Y10K输出等于SimpleDateFormat?

张卓
2023-03-14

在为一些日期助手编写单元测试时,我偶然发现了DateTimeForware的特定行为,我想了解如何解决这个问题。

输出年份时

LocalDate localDate = LocalDate.of(9999, 1, 1);
Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("UTC"));
cal.set(9999, 0, 1, 12, 0 , 0);

// following assertion passes as both strings are "01-01-9999"
Assertions.assertEquals(
    new SimpleDateFormat("dd-MM-yyyy").format(cal.getTime()),
    localDate.format(DateTimeFormatter.ofPattern("dd-MM-yyyy"))
);


localDate = localDate.plusDays(365);
cal.add(Calendar.DAY_OF_MONTH, 365);

// following assertion passes (lengthy workaround using SimpleDateFormat)
Assertions.assertEquals(
    new SimpleDateFormat("dd-MM-yyyy").format(cal.getTime()),
    new SimpleDateFormat("dd-MM-yyyy").format(Timestamp.valueOf(localDate.atTime(LocalTime.MIDNIGHT)))
);

// following assertion fails:
// Expected : "01-01-10000"
// Actual   : "01-01-+10000"
Assertions.assertEquals(
    new SimpleDateFormat("dd-MM-yyyy").format(cal.getTime()),
    localDate.format(DateTimeFormatter.ofPattern("dd-MM-yyyy"))
);

现在文档说明了年份模式:

如果字母数少于四个(但不是两个),则符号仅按符号样式输出负年份。正常。否则,如果超出焊盘宽度,则根据SignStyle输出符号。超过PAD。

这给了我一个提示,但我仍然不知道:

如何使DateTimeForware输出完全相同的字符串为Y10K日期,SimpleDateFormat.format()在我的例子(=无符号的正年份

共有1个答案

白志勇
2023-03-14

ISO 8601确实允许今年的格式。来自维基百科:

为了表示0000之前或9999之后的年份,该标准还允许扩展年份表示,但只能通过发送方和接收方之间的事先协议。扩展的年份表示[±YYYYY]必须有超出四位数最小值的商定额外年份位数,并且必须以或-符号为前缀,而不是更常见的AD/BC(或CE/BCE)表示法;

然而,由于它只允许“通过发送者和接收者之间的事先协议”,添加符号是LocalDate.toString的默认行为是很奇怪的。

根据文件:

年份:字母数决定使用填充的最小字段宽度。如果字母数为2,则使用缩减的两位数形式。对于打印,这将输出最右边的两位数字。对于解析,这将使用2000的基值进行解析,结果是2000到2099(含)之间的一年。如果字母数少于四个(但不是两个),则符号仅按符号样式输出负年份。正常。否则,如果超过焊盘宽度,则根据SignStyle输出符号。超过PAD。

所以如果你不想要这个符号,你可以用3个“y”,或者只是1个“y”,因为3和1都“小于4个(但不是2个)”。

此外,由于“y”表示“纪年”,因此不会有任何负年份,因此您也不必担心它输出负年份的符号。

例子:

System.out.println(
    LocalDate.of(10000, 1, 1)
        .format(DateTimeFormatter.ofPattern("dd-MM-yyy"))
); // 01-01-10000

一般来说,您可以使用DateTimeFormatterBuilder中的appendValue(TemporalField,int,int,SignStyle)方法指定符号样式。您可以指定符号样式。从不,使其从不输出符号。

 类似资料:
  • 问题内容: 我正在用C#实现某种东西,为此我有一个单独的规范并且对我需要做的事情有很清楚的了解,但是与此同时,我有一个Java实现,并且希望在这种情况下遵循Java实现,例如尽我所能。 该代码涉及一个加密流,并且Java源代码在这里 。相关行在这里: 上面的Java BouncyCastle 是a ,允许处理少于Aes块大小的单个或少量字节。 在c#BouncyCastle中,唯一提供的Proce

  • 问题是: 我们将“根到叶路径”定义为树中的任意节点序列,从根节点开始向下延伸到叶。该路径的“根到叶路径和”是沿该路径的所有节点(包括根)的和。定义一个空树,使其不包含根到叶的路径(因此其和为零)。定义一个具有一个节点的树,使其根到叶的路径仅由根组成(因此其总和是根的值)。给定一个二叉树和一个值“sum”,如果该树有一些根到叶的路径,使得沿路径的所有值相加等于“sum”,则返回true。如果找不到这

  • 本文向大家介绍PHP实现即时输出、实时输出内容方法,包括了PHP实现即时输出、实时输出内容方法的使用技巧和注意事项,需要的朋友参考一下 老生长谈了。。纯备忘 对于运行时间较长的PHP程序来说可能都需要即时输出内容来查看运行情况。 例, 按例子测试,达到了PHP即时实时输出内容的效果。

  • 本文向大家介绍Node.js用readline模块实现输入输出,包括了Node.js用readline模块实现输入输出的使用技巧和注意事项,需要的朋友参考一下 什么是Readline Readline是Node.js里实现标准输入输出的封装好的模块,通过这个模块我们可以以逐行的方式读取数据流。使用require("readline")可以引用模块。 如何使用Readline 以使用为角度的话,学习

  • 问题内容: 我正在实现一个程序,将文件分解为git blob并适当地存储它。 我有一个基于git书的文章的ruby参考实现 我正在尝试在这里实施 但是,我遇到了一个问题,即每个实现中存储的压缩数据略有不同。 显示前2个字节是相同的(如从该测试脚本运行)(如果我没有看错)。这些字节分别存储压缩方法,标志和标志(根据https://tools.ietf.org/html/rfc1950)。第三个字节是

  • 本文向大家介绍java实现输入输出流代码分享,包括了java实现输入输出流代码分享的使用技巧和注意事项,需要的朋友参考一下 1,编写一个程序,读取文件test.txt的内容并在控制台输出。如果源文件不存在,则显示相应的错误信息。 2,编写一个程序实现如下功能,从当前目录下的文件fin.txt中读取80个字节(实际读到的字节数可能比80少)并将读来的字节写入当前目录下的文件fout.txt中 3,使