相关文章推荐
含蓄的炒饭  ·  mysql循环查询select语句 - ...·  2 年前    · 
知识渊博的刺猬  ·  js两个数组对象找出id一致的数据并放到其中 ...·  2 年前    · 
俊秀的灌汤包  ·  MySql主键ID推荐以及原因 - 掘金·  3 年前    · 
心软的热带鱼  ·  android中HorizontalScro ...·  3 年前    · 
潇洒的书签  ·  集成 QR 或条码扫描仪功能 - ...·  3 年前    · 
Code  ›  java - Instant 和 LocalDateTime 有什么区别? -
时间线 utc时间转换
https://segmentfault.com/q/1010000042494441
卖萌的滑板
3 年前
segmentfault segmentfault
注册登录
问答 博客 标签 活动
发现
✓ 使用“Bing”搜本站 使用“Google”搜本站 使用“百度”搜本站 站内搜索
注册登录
  1. 首页
  2. 问答
  3. Stack Overflow 翻译
  4. 问答详情

Instant 和 LocalDateTime 有什么区别?

社区维基
1
发布于
2022-09-16
新手上路,请多包涵

我知道:

  • Instant 是用于计算的“技术”时间戳表示(纳秒)。
  • LocalDateTime 是日期/时钟表示,包括人类的时区。
  • 最后,IMO 都可以作为大多数应用程序用例的类型。举个例子:目前我正在运行一个批处理作业,我需要根据日期计算下一次运行,我正在努力寻找这两种类型之间的优缺点(除了 Instant 的纳秒精度优势和时区部分本地日期时间)。

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

    编辑:小心误读 LocalDateTime 关于精度和时区的文档

    原文由 manuel aldana 发布,翻译遵循 CC BY-SA 4.0 许可协议

    Stack Overflow 翻译 java datetime java8 jsr310
    阅读 839
    2 个回答
    得票 最新
    社区维基
    1
    发布于
    2022-09-16
    ✓ 已被采纳

    Java 中所有日期时间类型的表,包括现代和传统

    tl;博士

    Instant 和 LocalDateTime 是两种完全不同的动物:一种代表片刻,另一种不代表。

  • Instant 代表时刻,时间线中的特定点。
  • LocalDateTime 代表日期和时间。但是缺少时区或与 UTC 的偏移量, 此类 不能 代表 moment 。它代表了大约 26 到 27 小时范围内的 潜在 时刻,即全球所有时区的范围。 LocalDateTime 值 本质上是不明确 的。
  • 不正确的推定

    LocalDateTime 相当日期/时钟表示,包括人类的时区。

    您的说法不正确: A LocalDateTime has no time zone 。没有时区是该课程的重点。

    引用该类的文档:

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

    所以 Local… 表示“未分区,无偏移”。

    Instant

    Instant 是 UTC 时间线上的一个时刻,自 1970 年 UTC 第一个时刻的纪元以来的 纳秒 计数(基本上,请参阅类文档了解详细信息)。由于您的大部分业务逻辑、数据存储和数据交换都应该使用 UTC,因此这是一个经常使用的方便类。

     Instant instant = Instant.now() ;  // Capture the current moment in UTC.
    

    OffsetDateTime

    类 OffsetDateTime 类将时刻表示为日期和时间,其上下文比 UTC 早或晚一些小时-分钟-秒。偏移量,即小时-分钟-秒数,由 ZoneOffset 类表示。

    如果小时-分钟-秒数为零,则 OffsetDateTime 表示与 Instant 相同的 UTC 时刻。

    ZoneOffset

    ZoneOffset 类表示与 UTC 的 偏移量,比 UTC 早或晚于 UTC 数小时-分钟-秒。

    A ZoneOffset 只是几个小时-分钟-秒,仅此而已。一个区域要多得多,它有一个名称和一个偏移变化的历史。因此,使用区域总是比仅使用偏移量更可取。

    ZoneId

    时区 由 ZoneId 类表示。

    例如, 巴黎 的新一天比 蒙特利尔 更早。所以我们需要移动时钟的指针以更好地反映给定区域的 中午(当太阳直接在头顶时)。从西欧/非洲的 UTC 线向东/向西越远,偏移量越大。

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

    时区具有过去规则、现在规则和在不久的将来确认的规则的历史。

    这些规则的变化比您预期的要频繁。确保保持你的日期时间库的规则,通常是 ‘tz’ 数据库 的副本,是最新的。随着 Oracle 发布了 Timezone Updater Tool ,在 Java 8 中保持最新比以往任何时候都容易。

    Specify a proper time zone name in the format of Continent/Region , such as America/Montreal , Africa/Casablanca , or Pacific/Auckland .切勿使用 2-4 个字母的缩写,例如 EST 或 IST 因为它们 不是 真正的时区,不是标准化的,甚至不是唯一的(!)。

    时区 = 偏移量 + 调整规则

    ZoneId z = ZoneId.of( “Africa/Tunis” ) ;
    

    ZonedDateTime

    将 ZonedDateTime 从概念上视为 Instant 并分配有 ZoneId 。

    ZonedDateTime = ( Instant + ZoneId )

    要捕捉特定地区(时区)人们使用的挂钟时间中看到的当前时刻:

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

    几乎所有的后端、数据库、业务逻辑、数据持久性、数据交换都应该使用 UTC。但是为了向用户展示,您需要调整到用户期望的时区。这是 ZonedDateTime 类和用于生成这些日期时间值的字符串表示形式的 格式化程序类 的目的。

     ZonedDateTime zdt = instant.atZone( z ) ;
    String output = zdt.toString() ;                 // Standard ISO 8601 format.
    

    您可以使用 DateTimeFormatter 生成本地化格式的文本。

     DateTimeFormatter f = DateTimeFormatter.ofLocalizedDateTime( FormatStyle.FULL ).withLocale( Locale.CANADA_FRENCH ) ;
    String outputFormatted = zdt.format( f ) ;
    

    “本地”日期时间类 LocalDateTime 、 LocalDate 、 LocalTime 是另一种生物。它们不依赖于任何一个地区或时区。它们与时间线无关。在您将它们应用到某个地方以在时间线上找到一个点之前, 它们没有真正的意义。

    这些类名中的“Local”这个词对于外行来说可能是违反直觉的。这个词的意思是 任何 地方,或 每一个 地方,但 不是 一个特定的地方。

    因此,对于商业应用程序,“本地”类型并不经常使用,因为它们仅代表可能日期或时间的一般概念,而不是时间线上的特定时刻。商业应用程序往往关心发票到达的确切时间、运输的产品、雇用员工或出租车离开车库的确切时间。所以商业应用程序开发人员最常使用 Instant 和 ZonedDateTime 类。

    那么我们什么时候使用 LocalDateTime ?在三种情况下:

  • 我们希望在多个位置应用特定的日期和时间。
  • 我们正在预约。
  • 我们有一个预定但尚未确定的时区。
  • 请注意,这三种情况都没有涉及时间线上的某个特定点,这些都不是片刻。

    一天中的一个时间,多个时刻

    有时我们想表示某个日期的某个时间,但希望将其应用于跨时区的多个地点。

    例如,“圣诞节从 2015 年 12 月 25 日午夜开始”是 LocalDateTime 。巴黎的午夜罢工时间与蒙特利尔不同, 西雅图 和 奥克兰 也不同。

     LocalDate ld = LocalDate.of( 2018 , Month.DECEMBER , 25 ) ;
    LocalTime lt = LocalTime.MIN ;   // 00:00:00
    LocalDateTime ldt = LocalDateTime.of( ld , lt ) ;  // Christmas morning anywhere.
    

    另一个例子,“Acme 公司的政策是全球每个工厂的午餐时间从下午 12:30 开始”是 LocalTime 。要获得真正的意义,您需要将其应用于时间线,以计算 斯图加特 工厂的 12:30 或 拉巴特 工厂的 12:30 或 悉尼 工厂的 12:30 的时刻。

    使用 LocalDateTime 的另一种情况是预订未来的活动(例如:牙医预约)。这些约会在未来可能已经足够遥远,以至于你冒着政治家重新定义时区的风险。政客们往往很少预先警告,甚至根本没有警告。如果你的意思是“明年 1 月 23 日下午 3 点”,不管政客们如何玩弄时钟,那么你就不能记录一个时刻——如果该地区采用或取消夏令时,那将看到下午 3 点变成下午 2 点或 4 点,例如。

    对于约会,存储一个 LocalDateTime 和一个 ZoneId ,分开保存。稍后,在生成计划时,通过调用 LocalDateTime::atZone( ZoneId ) 即时确定时刻以生成 ZonedDateTime 对象。

     ZonedDateTime zdt = ldt.atZone( z ) ;  // Given a date, a time-of-day, and a time zone, determine a moment, a point on the timeline.
    

    如果需要,您可以调整为 UTC。从 — Instant ZonedDateTime 。

     Instant instant = zdt.toInstant() ;  // Adjust from some zone to UTC. Same moment, same point on the timeline, different wall-clock time.
    

    有些人可能会在时区或偏移量未知的情况下使用 LocalDateTime 。

    我认为这种情况是不恰当和不明智的。如果打算使用区域或偏移量但未确定,则您的数据不正确。这就像在不知道预期货币(美元、英镑、欧元等)的情况下存储产品价格。不是一个好主意。

    所有日期时间类型

    为了完整起见,这里是所有可能的日期时间类型的表,包括 Java 中的现代和传统类型,以及 SQL 标准定义的类型。这可能有助于将 Instant 和 LocalDateTime 类放在更大的上下文中。

    请注意 Java 团队在设计 JDBC 4.2 时做出的奇怪选择。他们选择支持所有 java.time 时间……除了两个最常用的类: Instant & ZonedDateTime 。

    但不用担心。我们可以轻松地来回转换。

    转换 Instant 。

     // Storing
    OffsetDateTime odt = instant.atOffset( ZoneOffset.UTC ) ;
    myPreparedStatement.setObject( … , odt ) ;
    // Retrieving
    OffsetDateTime odt = myResultSet.getObject( … , OffsetDateTime.class ) ;
    Instant instant = odt.toInstant() ;
    

    转换 ZonedDateTime 。

     // Storing
    OffsetDateTime odt = zdt.toOffsetDateTime() ;
    myPreparedStatement.setObject( … , odt ) ;
    // Retrieving
    OffsetDateTime odt = myResultSet.getObject( … , OffsetDateTime.class ) ;
    ZoneId z = ZoneId.of( "Asia/Kolkata" ) ;
    ZonedDateTime zdt = odt.atZone( z ) ;
    

    关于 java.time

    java.time 框架内置于 Java 8 及更高版本中。这些类取代了麻烦的旧 旧 日期时间类,例如 java.util.Date 、 Calendar 和 SimpleDateFormat 。

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

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

    您可以直接与您的数据库交换 java.time 对象。使用符合 JDBC 4.2 或更高版本的 JDBC 驱动程序。不需要字符串,不需要 java.sql.* 类。 Hibernate 5 & JPA 2.2 支持 java.time 。

    从哪里获得 java.time 类?

  • Java SE 8 、 Java SE 9 、 Java SE 10 、 Java SE 11 及更高版本 - 标准 Java API 的一部分,具有捆绑实现。
  • Java 9 带来了一些小功能和修复。
  • Java SE 6 和 Java SE 7
  • 大多数 java.time 功能在 ThreeTen- Backport 中向后移植到 Java 6 和 7。
  • 更高版本的 Android (26+) 捆绑了 java.time 类的实现。
  • 对于早期的 Android (<26),称为 API 脱糖 的过程带来了最初未内置于 Android 中的 java.time 功能的子集。
  • 如果脱糖不能提供您所需要的, ThreeTenABP 项目 会将 ThreeTen-Backport (上面提到的)适配到 Android。请参阅 如何使用 ThreeTenABP…… 。
  • ThreeTen-Extra 项目通过附加类扩展了 java.time。该项目是未来可能添加到 java.time 的试验场。您可以在这里找到一些有用的类,例如 Interval 、 YearWeek 、 YearQuarter 等等。

    原文由 Basil Bourque 发布,翻译遵循 CC BY-SA 4.0 许可协议

    社区维基
    1
    发布于
    2022-09-16

    一个主要区别是 LocalDateTime 的“本地”部分。如果你住在德国并创建一个 LocalDateTime 实例,而其他人住在美国并在同一时刻创建另一个实例(前提是时钟设置正确) - 这些对象的值实际上会有所不同.这不适用于 Instant ,它是独立于时区计算的。

    LocalDateTime 存储不带时区的日期和时间,但其初始值取决于时区。 Instant 不是。

    此外, LocalDateTime 提供了操作日期组件(如日、小时和月)的方法。 Instant 没有。

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

     
    推荐文章
    含蓄的炒饭  ·  mysql循环查询select语句 - CSDN文库
    2 年前
    知识渊博的刺猬  ·  js两个数组对象找出id一致的数据并放到其中一个数组中 - CSDN文库
    2 年前
    俊秀的灌汤包  ·  MySql主键ID推荐以及原因 - 掘金
    3 年前
    心软的热带鱼  ·  android中HorizontalScrollView和ScrollView横竖屏切换错误?_百度知道
    3 年前
    潇洒的书签  ·  集成 QR 或条码扫描仪功能 - Teams | Microsoft Learn
    3 年前
    今天看啥   ·   Py中国   ·   codingpro   ·   小百科   ·   link之家   ·   卧龙AI搜索
    删除内容请联系邮箱 2879853325@qq.com
    Code - 代码工具平台
    © 2024 ~ 沪ICP备11025650号