【发布时间】:2021-11-15 11:59:06
【问题描述】:
在为某些日期助手编写单元测试时,我偶然发现了 DateTimeFormatter 的特定行为,我想了解如何解决。
当输出年份 >9999 时,总是在年份数字前面加上一个加号。一些快速代码来说明这一点:
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"))
);
现在docs 表示年份模式:
如果字母数少于四个(但不是两个),则仅根据 SignStyle.NORMAL 输出负年份的符号。否则,如果超出焊盘宽度,则按照 SignStyle.EXCEEDS_PAD 输出符号。
所以这给出了一个提示,但我仍然一无所知:
如何使DateTimeFormatter 在我的示例中输出与SimpleDateFormat.format() 完全相同的Y10K+ 日期字符串(=无符号表示正数>9999)?
【问题讨论】:
-
我建议您放弃使用旧的日期类,包括
Date、Calendar和DateTimeFormatter。这些可怕的类在几年前被 JSR 310 中定义的现代 java.time 类所取代。 -
好建议——Java 生态系统确实充满了遗留(pre java8+)库,这些库遭受古怪的接口或产生有趣的结果。希望有一个硬(er)的弃用政策或更清楚地暗示最现代的图书馆在集成文档中是什么,目前对于没有经验的人来说,看到那些是什么感觉比必要的困难。展望未来,我正在努力只将最现代的库用于新代码——但由于我目前的任务是为现有代码编写单元测试,因此详细了解这些细微差异以及如何解决它们非常重要。
-
@BasilBourque
DateTimeFormatter实际上是一个 java.time 类——我假设你的意思是建议放弃java.text.SimpleDateFormat,对吗? -
@Philsen,哎呀!是的,我上面的第一条评论应该是:我建议你放弃使用旧的日期类,包括
Date、Calendar和SimpleDateFormat。这些可怕的类在几年前被 JSR 310 中定义的现代 java.time 类所取代,例如LocalDate和DateTimeFormatter。
标签: java datetime simpledateformat datetimeformatter y10k