首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >是否有用于SimpleDateFormat的格式字符串来获得毫秒的日期-时间值,而不是人类可读的形式?

是否有用于SimpleDateFormat的格式字符串来获得毫秒的日期-时间值,而不是人类可读的形式?
EN

Stack Overflow用户
提问于 2020-01-11 09:49:48
回答 2查看 96关注 0票数 0

通过像SimpleDateFormat这样的类,可以以适当的格式格式化时间和日期。

这里的例子

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

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

有时,有这个值而不是人类可读的形式是有用的。

示例:

如果我没有错的话,1578738100000值只是指世界协调时的数值,时间是2020年1月11日10:21:40。

是否有可能有一个格式字符串产生一个毫秒的字符串,而不是人类可读的形式?

我知道可以直接从Date类获得毫秒值,但我在这里要问的是,毫秒是否是向SimpleDateFormat (或类似类)提供数据的可能格式字符串之一。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2020-01-11 10:27:15

要清楚地理解日期时间值对象和格式化程序对象扮演着不同的角色。

  • 日期时间对象没有格式,它表示一个日期和/或一天中有或没有时区上下文或偏离-UTC的时间。
  • 格式化程序没有价值,没有日期,也没有时间。格式化程序的工作是使用日期对象生成特定格式的文本,表示日期时间对象的值。

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

而且,不,您不应该使用毫秒数来通信日期时间值.这样的数字对人类读者来说没有任何意义,这会导致容易丢失错误的数据。而这些数据本身并不容易识别--是整秒、毫秒、微秒还是纳秒?什么是划时代参考日期,几十个常用的历元中哪一个(https://en.wikipedia.org/wiki/Epoch_(computing%29#Notable_epoch_dates_in_computing)?)?

相反,使用ISO 8601标准格式将日期-时间值作为文本进行通信.

另一个问题是:您正在使用几年前被JSR 310中定义的现代java.time类取代的糟糕的日期时间类。

如果您的数字是自世界协调时1970年第一时刻的历次引用以来的毫秒数,则解析为Instant

代码语言:javascript
复制
Instant instant = Instant.ofEpochMilli( 1_578_738_100_000L ) ;

如果你不听我的建议,坚持与一个划时代的伯爵合作,你可以审问Instant

代码语言:javascript
复制
long milliseconds = instant.toEpochMilli() ;

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

代码语言:javascript
复制
String output = instant.toString() ;

对于其他格式,可以将Instant调整为OffsetDateTimeZonedDateTime对象,并使用DateTimeFormatter生成文本。所有这一切已经被讨论了很多次了。因此,搜索堆栈溢出以了解更多信息。

代码语言:javascript
复制
instant
.atZone( 
    ZoneId.of( "America/Montreal" ) 
)
.format(
    DateTimeFormatter
    .ofLocalizedDateTime( FormatStyle.FULL )
    .withLocale( Locale.CANADA_FRENCH )
)

最后,请注意,虽然遗留类的分辨率仅为毫秒,但java.time类的分辨率却要高得多。因此,当调用Instant::toEpochMilli时要注意数据丢失,因为忽略了任何毫秒或纳秒,

票数 2
EN

Stack Overflow用户

发布于 2020-01-11 12:14:48

旧的和过时的SimpleDateFormat类无法做到这一点。它的替代品,现代DateTimeFormatter,可以。

代码语言:javascript
复制
    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()的第二个参数所做的。

是否可能有格式字符串生成毫秒…的字符串??

不,使用格式模式字符串是不可能的,无论是用SimpleDateFormat还是用DateTimeFormatter。您可以查看每一个可能的模式字母,并看到自该时代以来,没有模式字母的时间没有秒,也没有毫秒。

您确实想要吗?,即使这是用于存储或在系统之间进行数据交换,也可以使用毫秒数,因为通常不推荐使用这个时代,因为它们不是人类可读的,因此在调试和特殊查询中很麻烦。在大多数情况下,您最好使用ISO 8601格式的字符串,比如2020-01-11T10:21:40Z。详见Basil Bourque的另一个答案。ISO 8601格式已设计成可供人和计算机阅读。

无论如何,您都不应该使用SimpleDateFormat。

SimpleDateFormat类是出了名的麻烦(尽管更多的是用于解析而不是格式化)。它也早已过时。您提到的Date类设计很差,而且也长期过时。我建议您像上面所做的那样使用java.time,这是一种现代的java.time和time。

链接

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/59693308

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档