java.time.DateTimeFormatter :需要始终呈现毫秒的 ISO_INSTANT

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/38042134/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-11-03 03:02:58  来源:igfitidea点击:

java.time.DateTimeFormatter : Need ISO_INSTANT that always renders milliseconds

javajava-8datetime-format

提问by Florent

I'm trying to cleanup a mix of various code around datetime management to only Java 8 java.timenamespace. Right now I have a small issue with the default DateTimeFormatterfor Instant. The DateTimeFormatter.ISO_INSTANTformatter only shows milliseconds when they are not equal to zero.

我正在尝试将有关日期时间管理的各种代码混合清理到 Java 8java.time命名空间。现在我有一个小问题用默认DateTimeFormatterInstant。该DateTimeFormatter.ISO_INSTANT格式只能说明毫秒时,他们不等于零。

The epoch is rendered as 1970-01-01T00:00:00Zinstead of 1970-01-01T00:00:00.000Z.

时代被呈现为1970-01-01T00:00:00Z而不是1970-01-01T00:00:00.000Z

I made a unit test to explain the problem and how we need to final dates to be compared one to each other.

我做了一个单元测试来解释这个问题以及我们需要如何将最终日期相互比较。

@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)));
    }
}

采纳答案by Florent

OK, I looked at the the source code and it's pretty straightforward:

好的,我查看了源代码,它非常简单:

DateTimeFormatter formatter = new DateTimeFormatterBuilder().appendInstant(3).toFormatter();

I hope it works for all scenarios, and it can help someone else. Don't hesitate to add a better/cleaner answer.

我希望它适用于所有场景,并且可以帮助其他人。不要犹豫,添加一个更好/更清晰的答案。

Just to explain where it comes from, in the JDK's code,

只是为了解释它的来源,在 JDK 的代码中

ISO_INSTANTis defined like this:

ISO_INSTANT定义如下:

public static final DateTimeFormatter ISO_INSTANT;
static {
    ISO_INSTANT = new DateTimeFormatterBuilder()
            .parseCaseInsensitive()
            .appendInstant()
            .toFormatter(ResolverStyle.STRICT, null);
}

And DateTimeFormatterBuilder::appendInstantis declared as:

DateTimeFormatterBuilder::appendInstant声明为:

public DateTimeFormatterBuilder appendInstant() {
    appendInternal(new InstantPrinterParser(-2));
    return this;
}

And the constructor InstantPrinterParsersignature is:

构造函数InstantPrinterParser签名是:

InstantPrinterParser(int fractionalDigits)

回答by Basil Bourque

The accepted Answer by Florentis correct and good.

由弗洛朗接受的答案是正确的,好的。

I just want to add some clarification.

我只想补充一些说明。

The mentioned formatter, DateTimeFormatter.ISO_INSTANT, is default only for the Instantclass. Other classes such as OffsetDateTimeand ZonedDateTimemay use other formatters by default.

提到的格式化程序DateTimeFormatter.ISO_INSTANT仅适用于Instant该类。其他类,例如OffsetDateTimeZonedDateTime可能默认使用其他格式化程序。

The java.time classes offer a resolution up to nanosecond, much finer granularity than milliseconds. That means up to 9 digits in the decimal fraction rather than merely 3 digits.

java.time 类提供高达纳秒的分辨率,比毫秒更精细的粒度。这意味着小数部分最多有 9 位数字,而不仅仅是 3 位数字。

The behavior of DateTimeFormatter.ISO_INSTANTvaries by the number of digits in the decimal fraction. As the doc says (emphasis mine):

的行为DateTimeFormatter.ISO_INSTANT因小数部分的位数而异。正如文档所说(强调我的):

When formatting, the second-of-minute is always output. The nano-of-second outputs zero, three, six or nine digitsas necessary.

格式化时,总是输出分钟的秒数。纳秒根据需要输出零、三、六或九位数字

So depending on the data value contained within the Instantobject, you may see any of these outputs:

因此,根据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

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

The Instantclass is meant to be the basic building block of java.time. Use it frequently for data passing, data storage, and data exchange. When generating String representations of the data for presentation to users, use OffsetDateTimeor ZonedDateTime.

Instant班,就是要java.time的基本构建块。经常将其用于数据传递、数据存储和数据交换。在生成数据的字符串表示以呈现给用户时,请使用OffsetDateTimeZonedDateTime