java.time.LocalDate 与 Instant 的“业务日期”

Oli*_*Oli 4 java java-time java.time.instant

我想代表一个“营业日期”,例如“2019 年 6 月 3 日”发生的交易。为此,我们主动忽略时区,因为我们完全知道日本的“2019 年 6 月 3 日”可能是美国的“2019 年 6 月 2 日”——而在“一天”内订购同样无关紧要。所有日期都是今天或之前的日期。

我显而易见的答案是,这是一个LocalDate. 但是,其他人建议将其表示为Instantof更好2019-06-03T00:00:00.000Z

除了在 UI 中将其转换/格式化为人类可读的日期时我们必须进行的不同调用,这两种方法之间实际上有什么区别吗?

这是一个与Instant 和 LocalDateTime 之间有什么区别的不同问题因为时间与这个问题无关,它只与过去(或当前)日期有关。

And*_*ner 9

我曾经在开发一种产品时犯了将出生日期表示为瞬间的错误。

这是我们多年后仍在处理的那些“微小”设计错误之一。

问题是当用户更改时区时,您无法在 UI 中可靠地显示它;在后端转换很容易出错,因为开发人员在不同的时区工作与服务器运行的地方。它有点在一个时区工作,但随着产品扩展到其他时区,它变得令人头疼。

瞬间是时间线上的一个;本地日期是一个时间范围(而不是一个明确定义的时间范围,因为它可以代表不同时区的不同瞬间范围)。它们代表不同的事物。

如果要表示日期,请存储日期。我的意思不是 a java.util.Date,它真的是一瞬间。

使用一个LocalDate.

  • 使用本地日期,您就有了年、月、日。就是这样。你不能不小心把它当作别的东西。瞬间可能会被意外地解释为“某个时区中的时间”,然后如果您弄错了时区,您就会错误地转换。 (2认同)
  • 我只是想提一下,存储出生日期只是使用“LocalDate”可能有意义的少数边缘情况之一。如果我于 2020 年 1 月 1 日凌晨 1:00 在德国出生,那么对于美国某个时区的某人来说,将我的生日显示为 2019/12/31 是没有意义的。话虽这么说,在几乎所有其他情况下,我认为记录 TZ 或使用“即时”之类的内容是完全有意义的,其中 TZ 是默认定义的。 (2认同)

Bas*_*que 5

LocalDate 可能不明确

安迪·特纳答案是正确且有价值的。另外,我想指出LocalDate.

LocalDate级表示日期,只值,没有时间的天,没有时区。对于任何给定时刻,日期在全球各地因时区而异。在某个特定时刻,它可能是日本东京的“明天”,同时是美国俄亥俄州托莱多的“昨天”。两个不同的日期同时生效。

因此,虽然您可能认为日期包含 24 小时,定义了特定的时刻范围,但事实并非如此。您必须将日期放在时区的上下文中才能确定时刻。(顺便说一下,日子并不总是 24 小时。)

LocalDate localDate = LocalDate.of( 2021 , Month.JANUARY , 24 ) ;
ZoneId zoneTokyo = ZoneId.of( "Asia/Tokyo" ) ;
ZonedDateTime startOfDayTokyo = localDate.atStartOfDay( zoneTokyo ) ;  // Determine a specific moment. 
Run Code Online (Sandbox Code Playgroud)

startOfDayTokyo.toString(): 2021-01-24T00:00+09:00[亚洲/东京]

要在 UTC 中查看同一时刻,请提取一个Instant对象。

Instant instant = startOfDayTokyo.toInstant() ;
Run Code Online (Sandbox Code Playgroud)

请注意,日期是 23 日而不是 24 日。

Instant.toString(): 2021-01-23T15:00:00Z

通过第三个挂钟时间看到同一时刻,美国俄亥俄州托莱多的时区America/New_York

ZonedDateTime zdtToledo = instant.atZone( ZoneId.of( "America/New_York" ) ) ;
Run Code Online (Sandbox Code Playgroud)

请注意,日期是 23 日而不是 24 日。

zdtToledo.toString(): 2021-01-23T10:00-05:00[美国/纽约]

查看此代码在 IdeOne.com 上实时运行

因此,在存储 a 时LocalDate,您可能还想存储时区名称。在数据库表中,这意味着两列。

举个例子,想想生日。如果知道某人当天的年龄至关重要,那么仅日期值是不够的。只有一个约会对象,在日本东京看起来年满 18 岁的人在美国俄亥俄州托莱多仍然是 17 岁。再举一个例子,考虑合同中的到期日。如果仅声明为日期,日本的一个利益相关者会将任务视为逾期,而托莱多的另一个利益相关者则认为该任务准时完成。

相反,当您指的是某个时刻、时间线上的特定点时,请使用Instant(或OffsetDateTimeZonedDateTime)。


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