SimpleDateFormat 是否有格式字符串来获取毫秒日期时间值而不是人类可读的形式?

Is there a format string for SimpleDateFormat to get milliseconds date-time value instead of human-readable form?

通过像 SimpleDateFormat 这样的 classes 可以将时间和日期格式化为合适的格式。

示例在这里

https://developer.android.com/reference/java/text/SimpleDateFormat#examples

在 Java 中,它以毫秒值开头,然后将该值转换为人类可读的格式。

有时使用该值而不是人类可读的形式很有用。

示例:

如果我没记错的话,1578738100000 值仅表示 2020 年 1 月 11 日星期六的 UTC 值 10:21:40。

是否可以使用一种格式字符串来生成以毫秒为单位的字符串而不是人类可读的形式?

我知道可以直接从 Date class 中获取毫秒值,但我在这里要问的是,毫秒是否是提供给 SimpleDateFormat(或类似 classes) 与.

明确理解日期时间值对象和格式化程序对象扮演不同的角色。

  • 日期时间对象没有格式,它表示日期 and/or 时间,有或没有时区上下文或与 UTC 的偏移量。
  • 格式化程序没有值,没有日期,也没有时间。格式化程序的工作是使用日期时间对象来生成表示该日期时间对象值的特定格式的文本。

因此,跟踪自纪元引用以来的毫秒数是日期时间对象的工作,而不是格式化程序的工作。生成人类可读的文本是格式化程序的工作。所以,不,格式化程序不会产生毫秒数。

而且,不,您不应该使用毫秒计数来传达日期时间值。这些数字对人类 reader 没有任何意义,这会导致很容易丢失错误数据。并且这样的数据不容易自我识别——它是整数秒、毫秒、微秒还是纳秒?什么是纪元参考日期,couple dozen commonly used epochs

改为使用 ISO 8601 标准格式以文本形式传达日期时间值。

另一个问题:您使用的日期时间 类 多年前被现代 java.time 类 所取代JSR 310.

如果您的数字是自 UTC 1970 年第一时刻的纪元参考以来的毫秒数,请解析为 Instant

Instant instant = Instant.ofEpochMilli( 1_578_738_100_000L ) ;

如果你违背我的建议坚持使用纪元计数,你可以询问Instant

long milliseconds = instant.toEpochMilli() ;

以标准 ISO 8601 格式生成文本。

String output = instant.toString() ;

对于其他格式,将Instant调整为OffsetDateTimeZonedDateTime对象,并生成带有DateTimeFormatter的文本。所有这一切已经被覆盖了很多很多次。因此,搜索 Stack Overflow 以了解更多信息。

instant
.atZone( 
    ZoneId.of( "America/Montreal" ) 
)
.format(
    DateTimeFormatter
    .ofLocalizedDateTime( FormatStyle.FULL )
    .withLocale( Locale.CANADA_FRENCH )
)

最后,请注意,虽然旧版 类 仅限于毫秒分辨率,但 java.time 类更精细的纳秒。因此,调用 Instant::toEpochMilli 时要注意可能的数据丢失,因为任何微秒或纳秒都会被忽略,

陈旧过时的SimpleDateFormatclass做不到。它的替代品,现代的 DateTimeFormatter,可以。

    DateTimeFormatter epochMilliFormatter = new DateTimeFormatterBuilder()
            .appendValue(ChronoField.INSTANT_SECONDS)
            .appendValue(ChronoField.MILLI_OF_SECOND, 3)
            .toFormatter();

    Instant sampleInstant = OffsetDateTime
            .of(2020, 1, 11, 10, 21, 40, 0, ZoneOffset.UTC)
            .toInstant();

    String formattedValue = epochMilliFormatter.format(sampleInstant);
    System.out.println(formattedValue);

此代码段的输出是您提到的数字:

1578738100000

在格式化程序中使用 ChronoField.INSTANT_SECONDS 为我们提供了自纪元以来的 。我们想要 毫秒 ,所以我们需要立即附加 ChronoField.MILLI_OF_SECOND 并确保它们打印在准确的 3 个位置,零填充。这就是 3 作为 appendValue() 的第二个参数所做的。

Is it possible to have a format string that yields a string with milliseconds …?

不,使用格式模式字符串是不可能的,无论是 SimpleDateFormat 还是 DateTimeFormatter。您可以查看每个可能的模式字母,发现自纪元以来的秒数和毫秒数都没有模式字母。

不过你确定要它吗?即使这是为了存储或系统之间的数据交换,使用 milliseoncds 因为纪元通常不被推荐,因为它们不是人类可读的,因此在调试和临时查询中很麻烦。对于大多数用途,您最好使用 ISO 8601 格式的字符串,例如 2020-01-11T10:21:40Z。有关详细信息,请参阅 Basil Bourque 的其他答案。 ISO 8601 格式被设计为人和计算机都可读。

无论如何你都不应该使用 SimpleDateFormat

SimpleDateFormat class 是出了名的麻烦(虽然更多的是解析而不是格式化)。它也已经过时了。您提到的 Date class 设计不佳且早已过时。我建议您像我上面那样使用 java.time、现代 Java 日期和时间 API。

链接