Instant和LocalDateTime有什么区别?

man*_*ana 205 java datetime java-8

我知道:

  • Instant是用于计算的"技术"时间戳表示(纳秒).
  • LocalDateTime是日期/时钟表示,包括人类的时区.

仍然最终IMO都可以作为大多数应用程序用例的类型.例如:目前我正在运行一个批处理作业,我需要根据日期计算下一次运行,我很难找到这两种类型之间的优缺点(除了Instant的纳秒级精度优势和时区部分) of LocalDateTime).

您能说出一些应用示例,其中只应使用Instant或LocalDateTime吗?

编辑:注意有关精度和时区的LocalDateTime的误读文档

Bas*_*que 634

推定不正确

Instant 是日期/时钟表示,包括人类的时区.

你的说法是不正确:一个LocalDateTime没有时区.没有时区是该课程的全部内容.

引用该类的文档:

此类不存储或表示时区.相反,它是用于生日的日期的描述,结合在挂钟上看到的当地时间.如果没有附加信息(如偏移或时区),它不能代表时间线上的瞬间.

所以Instant意味着"没有划分".

LocalDateTime

在此输入图像描述

An LocalDateTimeUTC时间轴上的一个时刻,自UTC 1970年第一个时刻以来的纳秒数(基本上,请参阅类文档了解细节).由于您的大多数业务逻辑,数据存储和数据交换都应该是UTC,因此这是一个经常使用的方便类.

Instant instant = Instant.now() ;  // Capture the current moment in UTC.
Run Code Online (Sandbox Code Playgroud)

类似于LocalDateTime班级Local….此类表示一个时刻作为日期和时间,其上下文是UTC之前或之后的某些小时 - 分钟 - 秒.如果数字为零,则a Instant表示UTC中的时刻与a相同Instant.

OffsetDateTime

在此输入图像描述

A OffsetDateTime时区.

时区是距离UTC数小时和分钟的偏移量.例如,巴黎的新日早些时候比蒙特利尔早.因此,对于给定区域,我们需要移动时钟的指针以更好地反映中午(当太阳直接在头顶上时).从西欧/非洲的UTC线向东/向西越远,偏移越大.

此外,时区是一组用于处理当地社区或地区实施的调整和异常的规则.最常见的异常是被称为夏令时(DST)的非常流行的疯狂.

时区具有过去规则的历史,现有规则以及近期确认的规则.

这些规则的更改频率高于您的预期.请务必保留日期时间库的规则,通常是"tz"数据库的副本,最新的.在Java 8中发布Timezone Updater Tool时,保持最新状态比以往任何时候都更容易.

使用适当的时区名称.这些名称采用大陆加SLASH加上城市或地区的形式.避免3-4个字母代码,如ZoneOffsetOffsetDateTime.它们既不标准也不独特.他们进一步混淆了夏令时的混乱.

时区=偏移+调整规则

ZoneId z = ZoneId.of( “Africa/Tunis” ) ; 
Run Code Online (Sandbox Code Playgroud)

有时我们只有一个没有规则的偏移量.Java Instant为此目的提供了一个子类ZoneOffset.注意那里定义的方便常量ZoneOffset.

ZonedDateTime zdt = ZonedDateTime.now( z ) ;  // Pass a `ZoneId` object such as `ZoneId.of( "Europe/Paris" )`. 
Run Code Online (Sandbox Code Playgroud)

ZoneOffset

在此输入图像描述

ZoneId概念上讲,将ZoneId其视为已分配的Continent/Region.

ZonedDateTime =(Instant + ZoneId)

几乎所有的后端,数据库,业务逻辑,数据持久性,数据交换都应该是UTC.但是,为了向用户呈现,您需要调整到用户期望的时区.这是America/Montreal类和用于生成这些日期时间值的String表示的格式化程序类的目的.

ZonedDateTime zdt = instant.atZone( z ) ;
String output = zdt.toString() ;                 // Standard ISO 8601 format.
Run Code Online (Sandbox Code Playgroud)

Africa/Casablanca,Pacific/Auckland,EST

该图仅显示<code>IST</code></a>,<a rel=ZonedDateTime,ZonedDateTime,有一种别样的小动物的.它们与任何一个地区或时区无关.它们与时间表无关.在将它们应用到某个位置以在时间轴上找到一个点之前,它们没有任何实际意义.

例如,"圣诞节从2015年12月25日午夜开始"是一个Instant.在巴黎不同时刻的午夜罢工比在蒙特利尔,在西雅图奥克兰再次不同.

DateTimeFormatter f = DateTimeFormatter.ofLocalizedDateTime( FormatStyle.FULL ).withLocale( Locale.CANADA_FRENCH ) ; 
String outputFormatted = zdt.format( f ) ;
Run Code Online (Sandbox Code Playgroud)

另一个例子,"Acme公司制定了一项政策,午餐时间从下午12:30开始在全球各工厂开展"是一个例子ZoneId.为了拥有真正的意义,您需要将其应用到时间线,以便在斯图加特工厂12:30或12:30在拉巴特工厂或12:30在悉尼工厂进行计算.

因此,对于商业应用程序,通常不使用"本地"类型,因为它们仅代表可能的日期或时间的一般概念,而不是时间轴上的特定时刻.商业应用程序倾向于关注发票到达的确切时刻,运输的产品,雇用员工或出租车离开车库.所以业务应用程序开发人员使用ZonedDateTime,并DateTimeFormatter几乎完全.另一方面,你应该考虑使用这些LocalDate类型来预订未来事件(例如:牙医约会),将来你可能会像往常那样在没有预警的情况下改善时区的风险.


关于java.time

java.time框架是建立在Java 8和更高版本.这些类取代麻烦的老传统日期时间类,如LocalTime,LocalDateTime,和LocalDateTime.

现在处于维护模式Joda-Time项目建议迁移到java.time类.

要了解更多信息,请参阅Oracle教程.并搜索Stack Overflow以获取许多示例和解释.规范是JSR 310.

您可以直接与数据库交换java.time对象.使用符合JDBC 4.2或更高版本的JDBC驱动程序.不需要字符串,不需要课程.LocalDate

从哪里获取java.time类?

ThreeTen-额外项目与其他类扩展java.time.该项目是未来可能添加到java.time的试验场.您可以在此比如找到一些有用的类LocalTime,Instant,ZonedDateTime,和更多.

  • 很好的答案.我认为一些混乱(至少是我的)来自于`Local`命名.我对"本地"的直觉意味着我和我在哪里(?!),这让我相信它实际上就是"ZonedDateTime". (30认同)
  • 是的,这令人困惑.这就是为什么java.time巧妙地将"Zoned"这个词添加到其前任Joda-Time(生成`ZonedDateTime`)使用的`DateTime`类名中,以强调与"Local"类的区别.可以将"Local"这个名称视为"需要应用于某个特定地点"的简写. (4认同)
  • 用"Local"这个词作为前缀可能也是一种区别于java.util包的方法,虽然不知何故我觉得可能有更好的单词选择. (2认同)
  • @simonh相反...当新员工签署其聘用文件,定义其福利(包括人寿保险),然后新员工走出屋外喝咖啡而被卡车撞伤时,将会有很多这样的人作为人力资源经理,保险代理人和律师,他们想知道新工作生效的确切时间。 (2认同)
  • @simonh是的,在某些情况下,“本地”日期时间合适。除了“我的答案”中提到的那些事项外,另一种常见的业务情况是约会要在未来数月之内完成,远远超出了政治人物可能会更改时区规则的时间,通常很少发出警告。政客经常进行这些更改,例如更改开/关夏令时(DST)的日期或永久性开/关DST的日期。 (2认同)
  • @specializt我建议您发布自己的问答,以教育其他人了解这种神秘的追溯和容错计算概念。我好奇。 (2认同)

Dar*_*usz 20

一个主要区别是Local的一部分LocalDateTime.如果您居住在德国并创建一个LocalDateTime实例并且其他人居住在美国并在同一时刻创建另一个实例(假设时钟已正确设置) - 这些对象的值实际上会有所不同.这不适用于Instant,独立于时区计算.

LocalDateTime存储没有时区的日期和时间,但它的初始值取决于时区.Instant不是.

此外,LocalDateTime还提供了操作日期,小时,月份等日期组件的方法.一个Instant没有.

除了Instant的纳秒精度优势和LocalDateTime的时区部分

两个类都具有相同的精度.LocalDateTime不存储时区.彻底阅读javadocs,因为你可能会犯这样无效的假设:InstantLocalDateTime.

  • 每当我需要日期和/或时间时,我都会采用 LocalDateTime 。几小时、几分钟左右。例如,我会使用 Instant 来测量执行时间,或者存储当时发生的事情的内部字段。计算下一次运行,就像你的情况一样?LocalDateTime 似乎合适,但这是一个意见。正如你所说,两者都可以使用。 (2认同)

Tun*_*aki 12

你错了LocalDateTime:它不存储任何时区信息,它具有纳秒精度.引用Javadoc(强调我的):

ISO-8601日历系统中没有时区的日期时间,例如2007-12-03T10:15:30.

LocalDateTime是一个不可变的日期时间对象,表示日期时间,通常被视为年 - 月 - 日 - 小时 - 分 - 秒.还可以访问其他日期和时间字段,例如日期,星期和星期.时间表示为纳秒精度.例如,值"2007年10月2日13:45.30.123456789"可以存储在LocalDateTime中.

两者之间的差异是Instant表示与Epoch(01-01-1970)的偏移,因此,表示时间线上的特定时刻.Instant在地球的两个不同位置同时创建的两个对象将具有完全相同的值.

  • @manuelaldana这更多的是品味问题.我更喜欢LocalDateTime用于任何与用户相关的事件(生日...)和Instant用于与机器相关的任何事情(执行时间......). (3认同)
  • @manuelaldana单个时区应用程序即使不存在也很少见.对于你为当地的巴洛克音乐俱乐部掀起的小应用程序,你可能会忽略时区.但只要你需要事件发布到谁旅行的人(和跨时区),他们会想是绑在一个时区的数据,以便在需要他们的日历应用程序可以调整.我建议您学会在所有应用中正确使用时区. (2认同)

Seb*_*ien 9

LocalDateTime 没有时区信息:一个 LocalDateTime 可能代表世界各地不同机器的不同时刻。因此,您不应尝试将其与隐式时区(系统的默认时区)一起使用。您应该将其用于它所代表的内容,例如“新年是 1 月 1 日 0:00”:这意味着地球上所有地点的时间都不同,但在本例中是需要的。

Instant 是格林威治时区的一个时间点。例如,除了用户的时区之外,还可以使用它来向他/她显示他/她所在时区的会议开始时间。

如果这两个类不代表您想要存储/交换的内容,那么也许 ZonedDateTime 或另一个类可能会做得更好。

下面是一个简单的综合模式,用于全面了解 java.time 包中的类及其与 ISO-8601 标准的关系,该标准用于在 Java 和其他语言或框架之间可靠且轻松地交换日期和时间:

java.time 包的类及其与 ISO-8601 标准的关系

该模式在这里详细解释: http: //slaout.linux62.org/java-date-time/


小智 6

在我的职业生涯中,我曾在许多项目中处理过时区问题。事后看来,我必须承认我们从来没有百分百正确,因为这个话题的复杂性令人惊讶。这就是为什么我决定写一篇博客文章来详细介绍该java.time包。

对于上面发布的问题已经有很多优秀的答案,但是这篇博文不仅仅局限于 Java,还涵盖了与关系数据库、NoSQL 数据库(例如 MongoDB)或 JavaScript 等技术的交互,这些技术通常比 Java 具有更严格的支持当谈到时区时。

虽然我确实建议阅读这篇文章以详细了解所有概念,但我想从我的帖子中添加两个模式以提供快速概述。

java.time第一个图总结了描述某个时间点的类的特征。有些类代表绝对(或明确)的时间点(称为时刻),而其他类LocalDateTime仅描述所谓的挂钟时间:

描述时间点的 java.time 类的特性总结

第二个模式提供了一个决策树,它将帮助您为您的用例选择正确的类。

决策树可帮助您为您的用例选择正确的类。

在此决策树中做出的一些决策绝非微不足道。我的博文中有更详细的解释。