java.time.DateTimeFormatter :需要 ISO_INSTANT 始终呈现毫秒
java.time.DateTimeFormatter : Need ISO_INSTANT that always renders milliseconds
我正在尝试将围绕日期时间管理的各种代码混合清理为仅 Java 8 java.time
namespace. Right now I have a small issue with the default DateTimeFormatter
for Instant
. The DateTimeFormatter.ISO_INSTANT
格式化程序仅在不等于零时显示毫秒。
纪元呈现为 1970-01-01T00:00:00Z
而不是 1970-01-01T00:00:00.000Z
。
我做了一个单元测试来解释这个问题以及我们如何需要最终日期来相互比较。
@Test
public void java8Date() {
DateTimeFormatter formatter = DateTimeFormatter.ISO_INSTANT;
String epoch, almostEpoch, afterEpoch;
{ // before epoch
java.time.Instant instant = java.time.Instant.ofEpochMilli(-1);
almostEpoch = formatter.format(instant);
assertEquals("1969-12-31T23:59:59.999Z", almostEpoch );
}
{ // epoch
java.time.Instant instant = java.time.Instant.ofEpochMilli(0);
epoch = formatter.format(instant);
// This fails, I get 1970-01-01T00:00:00Z instead
assertEquals("1970-01-01T00:00:00.000Z", epoch );
}
{ // after epoch
java.time.Instant instant = java.time.Instant.ofEpochMilli(1);
afterEpoch = formatter.format(instant);
assertEquals("1970-01-01T00:00:00.001Z", afterEpoch );
}
// The end game is to make sure this rule is respected (this is how we order things in dynamo):
assertTrue(epoch.compareTo(almostEpoch) > 0);
assertTrue(afterEpoch.compareTo(epoch) > 0); // <-- This assert would also fail if the second assert fails
{ // to confirm we're not showing nanos
assertEquals("1970-01-01T00:00:00.000Z", formatter.format(Instant.EPOCH.plusNanos(1)));
assertEquals("1970-01-01T00:00:00.001Z", formatter.format(Instant.EPOCH.plusNanos(1000000)));
}
}
好的,我查看了源代码,它非常简单:
DateTimeFormatter formatter = new DateTimeFormatterBuilder().appendInstant(3).toFormatter();
我希望它适用于所有场景,并且它可以帮助到其他人。不要犹豫,添加 better/cleaner 答案。
只是为了解释它的来源,in the JDK's code,
ISO_INSTANT
定义如下:
public static final DateTimeFormatter ISO_INSTANT;
static {
ISO_INSTANT = new DateTimeFormatterBuilder()
.parseCaseInsensitive()
.appendInstant()
.toFormatter(ResolverStyle.STRICT, null);
}
而DateTimeFormatterBuilder::appendInstant
声明为:
public DateTimeFormatterBuilder appendInstant() {
appendInternal(new InstantPrinterParser(-2));
return this;
}
构造函数InstantPrinterParser
签名为:
InstantPrinterParser(int fractionalDigits)
正确而且很好。
我只是想补充一些说明。
提到的格式化程序,DateTimeFormatter.ISO_INSTANT, is default only for the Instant
class. Other classes such as OffsetDateTime
and ZonedDateTime
可能默认使用其他格式化程序。
java.time classes 提供高达 nanosecond, much finer granularity than milliseconds 的分辨率。这意味着小数部分最多有 9 位数字,而不仅仅是 3 位数字。
DateTimeFormatter.ISO_INSTANT
的行为因小数位数而异。正如医生所说(强调我的):
When formatting, the second-of-minute is always output. The nano-of-second outputs zero, three, six or nine digits as necessary.
因此,根据 Instant
对象中包含的数据值,您可能会看到以下任何输出:
2011-12-03T10:15:30Z
2011-12-03T10:15:30.100Z
2011-12-03T10:15:30.120Z
2011-12-03T10:15:30.123Z
2011-12-03T10:15:30.123400Z
2011-12-03T10:15:30.123456Z
2011-12-03T10:15:30.123456780Z
2011-12-03T10:15:30.123456789Z
Instant
class 是 java.time 的基本组成部分。经常使用它进行数据传递、数据存储和数据交换。生成数据的字符串表示形式以呈现给用户时,请使用 OffsetDateTime
or ZonedDateTime
.
我正在尝试将围绕日期时间管理的各种代码混合清理为仅 Java 8 java.time
namespace. Right now I have a small issue with the default DateTimeFormatter
for Instant
. The DateTimeFormatter.ISO_INSTANT
格式化程序仅在不等于零时显示毫秒。
纪元呈现为 1970-01-01T00:00:00Z
而不是 1970-01-01T00:00:00.000Z
。
我做了一个单元测试来解释这个问题以及我们如何需要最终日期来相互比较。
@Test
public void java8Date() {
DateTimeFormatter formatter = DateTimeFormatter.ISO_INSTANT;
String epoch, almostEpoch, afterEpoch;
{ // before epoch
java.time.Instant instant = java.time.Instant.ofEpochMilli(-1);
almostEpoch = formatter.format(instant);
assertEquals("1969-12-31T23:59:59.999Z", almostEpoch );
}
{ // epoch
java.time.Instant instant = java.time.Instant.ofEpochMilli(0);
epoch = formatter.format(instant);
// This fails, I get 1970-01-01T00:00:00Z instead
assertEquals("1970-01-01T00:00:00.000Z", epoch );
}
{ // after epoch
java.time.Instant instant = java.time.Instant.ofEpochMilli(1);
afterEpoch = formatter.format(instant);
assertEquals("1970-01-01T00:00:00.001Z", afterEpoch );
}
// The end game is to make sure this rule is respected (this is how we order things in dynamo):
assertTrue(epoch.compareTo(almostEpoch) > 0);
assertTrue(afterEpoch.compareTo(epoch) > 0); // <-- This assert would also fail if the second assert fails
{ // to confirm we're not showing nanos
assertEquals("1970-01-01T00:00:00.000Z", formatter.format(Instant.EPOCH.plusNanos(1)));
assertEquals("1970-01-01T00:00:00.001Z", formatter.format(Instant.EPOCH.plusNanos(1000000)));
}
}
好的,我查看了源代码,它非常简单:
DateTimeFormatter formatter = new DateTimeFormatterBuilder().appendInstant(3).toFormatter();
我希望它适用于所有场景,并且它可以帮助到其他人。不要犹豫,添加 better/cleaner 答案。
只是为了解释它的来源,in the JDK's code,
ISO_INSTANT
定义如下:
public static final DateTimeFormatter ISO_INSTANT;
static {
ISO_INSTANT = new DateTimeFormatterBuilder()
.parseCaseInsensitive()
.appendInstant()
.toFormatter(ResolverStyle.STRICT, null);
}
而DateTimeFormatterBuilder::appendInstant
声明为:
public DateTimeFormatterBuilder appendInstant() {
appendInternal(new InstantPrinterParser(-2));
return this;
}
构造函数InstantPrinterParser
签名为:
InstantPrinterParser(int fractionalDigits)
我只是想补充一些说明。
提到的格式化程序,DateTimeFormatter.ISO_INSTANT, is default only for the Instant
class. Other classes such as OffsetDateTime
and ZonedDateTime
可能默认使用其他格式化程序。
java.time classes 提供高达 nanosecond, much finer granularity than milliseconds 的分辨率。这意味着小数部分最多有 9 位数字,而不仅仅是 3 位数字。
DateTimeFormatter.ISO_INSTANT
的行为因小数位数而异。正如医生所说(强调我的):
When formatting, the second-of-minute is always output. The nano-of-second outputs zero, three, six or nine digits as necessary.
因此,根据 Instant
对象中包含的数据值,您可能会看到以下任何输出:
2011-12-03T10:15:30Z
2011-12-03T10:15:30.100Z
2011-12-03T10:15:30.120Z
2011-12-03T10:15:30.123Z
2011-12-03T10:15:30.123400Z
2011-12-03T10:15:30.123456Z
2011-12-03T10:15:30.123456780Z
2011-12-03T10:15:30.123456789Z
Instant
class 是 java.time 的基本组成部分。经常使用它进行数据传递、数据存储和数据交换。生成数据的字符串表示形式以呈现给用户时,请使用 OffsetDateTime
or ZonedDateTime
.