Java Instant 和 LocalDateTime 有什么区别?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/32437550/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-11 12:33:07  来源:igfitidea点击:

What's the difference between Instant and LocalDateTime?

javadatetimejava-8

提问by manuel aldana

I know that:

我知道:

  • Instantis rather a "technical" timestamp representation (nanoseconds) for computing.
  • LocalDateTimeis rather date/clock representation including time-zones for humans.
  • Instant是用于计算的“技术”时间戳表示(纳秒)。
  • LocalDateTime更像是日期/时钟表示,包括人类的时区。

Still in the end IMO both can be taken as type for most application use-cases. As example: Currently I am running a batch job where I need to calculate a next run based on dates and I am struggling to find a pros/cons between these two types (apart from the nanosecond precision advantage of Instant and the time-zone part of LocalDateTime).

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

Can you name some application examples, where only Instant or LocalDateTime should be used?

你能说出一些应用程序示例,其中应该只使用 Instant 或 LocalDateTime 吗?

Edit: Beware misread documentations for LocalDateTime regarding precision and time-zone

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

采纳答案by Basil Bourque

Table of types of date-time class in modern java.time versus legacy.

现代 java.time 与旧版中日期时间类的类型表。

tl;dr

tl;博士

Instantand LocalDateTimeare two entirely different animals: One represents a moment, the other does not.

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

  • Instantrepresents a moment, a specific point in the timeline.
  • LocalDateTimerepresents a date and a time-of-day. But lacking a time zone or offset-from-UTC, this class cannotrepresent a moment. It represents potentialmoments along a range of about 26 to 27 hours, the range of all time zones around the globe.
  • Instant代表一个时刻,时间线中的一个特定点。
  • LocalDateTime表示日期和时间。但是由于缺少时区或 UTC 偏移量,这个类不能代表 moment。它代表了大约 26 到 27 小时范围内的潜在时刻,这是全球所有时区的范围。

Incorrect Presumption

错误推定

LocalDateTimeis rather date/clock representation including time-zones for humans.

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

Your statement is incorrect: A LocalDateTimehas notime zone. Having no time zone is the entire point of that class.

你的说法是错误的:A LocalDateTimehas notime zone。没有时区是该课程的重点。

To quote that class' doc:

引用该类的文档:

This class does not store or represent a time-zone. Instead, it is a description of the date, as used for birthdays, combined with the local time as seen on a wall clock. It cannot represent an instant on the time-line without additional information such as an offset or time-zone.

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

So Local…means “not zoned, no offset”.

所以Local…意思是“没有分区,没有偏移”。

Instant

Instant

enter image description here

在此处输入图片说明

An Instantis a moment on the timeline in UTC, a count of nanosecondssince the epoch of the first moment of 1970 UTC (basically, see class doc for nitty-gritty details). Since most of your business logic, data storage, and data exchange should be in UTC, this is a handy class to be used often.

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

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

OffsetDateTime

OffsetDateTime

The class OffsetDateTimeclass represents a moment as a date and time with a context of some number of hours-minutes-seconds ahead of, or behind, UTC. The amount of offset, the number of hours-minutes-seconds, is represented by the ZoneOffsetclass.

OffsetDateTime类将时刻表示为日期和时间,其上下文为 UTC 之前或之后的某些小时-分钟-秒数。偏移量,即小时-分钟-秒数,由ZoneOffset类表示。

If the number of hours-minutes-seconds is zero, an OffsetDateTimerepresents a moment in UTC the same as an Instant.

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

ZoneOffset

ZoneOffset

The ZoneOffsetclass represents an offset-from-UTC, a number of hours-minutes-seconds ahead of UTC or behind UTC.

所述ZoneOffset类表示偏移从-UTC,若干小时-分钟-秒比UTC或后面UTC。

A ZoneOffsetis merely a number of hours-minutes-seconds, nothing more. A zone is much more, having a name and a history of changes to offset. So using a zone is always preferable to using a mere offset.

AZoneOffset只是几个小时-分钟-秒,仅此而已。一个区域远不止这些,有一个名称和一个要偏移的更改历史。因此,使用区域总是比仅使用偏移更可取。

ZoneId

ZoneId

enter image description here

在此处输入图片说明

A time zoneis represented by the ZoneIdclass.

时区是由表示ZoneId类。

A new day dawns earlier in Paristhan in Montréal, for example. So we need to move the clock's hands to better reflect noon(when the Sun is directly overhead) for a given region. The further away eastward/westward from the UTC line in west Europe/Africa the larger the offset.

例如,巴黎蒙特利尔更早开始新的一天。因此,我们需要移动时钟指针以更好地反映给定区域的中午(当太阳位于正上方时)。西欧/非洲的UTC线向东/向西越远,偏移量越大。

A time zone is a set of rules for handling adjustments and anomalies as practiced by a local community or region. The most common anomaly is the all-too-popular lunacy known as Daylight Saving Time (DST).

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

A time zone has the history of past rules, present rules, and rules confirmed for the near future.

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

These rules change more often than you might expect. Be sure to keep your date-time library's rules, usually a copy of the 'tz' database, up to date. Keeping up-to-date is easier than ever now in Java 8 with Oracle releasing a Timezone Updater Tool.

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

Specify a proper time zone namein the format of Continent/Region, such as America/Montreal, Africa/Casablanca, or Pacific/Auckland. Never use the 2-4 letter abbreviation such as ESTor ISTas they are nottrue time zones, not standardized, and not even unique(!).

以、、 或等格式指定正确的时区名称。永远不要使用 2-4 个字母的缩写,例如或因为它们不是真正的时区,不是标准化的,甚至不是唯一的(!)。Continent/RegionAmerica/MontrealAfrica/CasablancaPacific/AucklandESTIST

Time Zone = Offset + Rules of Adjustments

时区 = 偏移量 + 调整规则

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

ZonedDateTime

ZonedDateTime

enter image description here

在此处输入图片说明

Think of ZonedDateTimeconceptually as an Instantwith an assigned ZoneId.

ZonedDateTime概念上将其视为Instant具有分配的ZoneId

ZonedDateTime = ( Instant + ZoneId )

ZonedDateTime = ( 即时 + ZoneId )

To capture the current moment as seen in the wall-clock time used by the people of a particular region (a time zone):

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

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

Nearly all of your backend, database, business logic, data persistence, data exchange should all be in UTC. But for presentation to users you need to adjust into a time zone expected by the user. This is the purpose of the ZonedDateTimeclass and the formatter classesused to generate String representations of those date-time values.

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

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

You can generate text in localized format using DateTimeFormatter.

您可以使用DateTimeFormatter.

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

mardi 30 avril 2019 à 23 h 22 min 55 s heure de l'Inde

狂欢节 2019 年 4 月 30 日 à 23 h 22 min 55 s heure de l'Inde

LocalDate, LocalTime, LocalDateTime

LocalDate, LocalTime,LocalDateTime

Diagram showing only a calendar for a <code>LocalDate</code>.

图表仅显示 <code>LocalDate</code>的日历。

Diagram showing only a clock for a <code>LocalTime</code>.

图表仅显示 <code>LocalTime</code>的时钟。

Diagram showing a calendar plus clock for a <code>LocalDateTime</code>.

图表显示了 <code>LocalDateTime</code>的日历和时钟。

The "local" date time classes, LocalDateTime, LocalDate, LocalTime, are a different kind of critter. The are not tied to any one locality or time zone. They are not tied to the timeline. They have no real meaninguntil you apply them to a locality to find a point on the timeline.

“本地”的日期时间类,LocalDateTimeLocalDateLocalTime,有一种别样的小动物的。与任何一个地点或时区无关。它们与时间线无关。在您将它们应用到某个地点以在时间线上找到一个点之前,它们没有真正的意义

The word “Local” in these class names may be counter-intuitive to the uninitiated. The word means anylocality, or everylocality, but nota particular locality.

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

So for business apps, the "Local" types are not often used as they represent just the general idea of a possible date or time not a specific moment on the timeline. Business apps tend to care about the exact moment an invoice arrived, a product shipped for transport, an employee was hired, or the taxi left the garage. So business app developers use Instantand ZonedDateTimeclasses most commonly.

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

So when would we use LocalDateTime? In three situations: where we want to apply a certain date and time-of-day across multiple locations, where we are booking appointments, or where we have an intended yet undetermined time zone. Notice that none of these three cases are a single certain specific point on the timeline, none of these are a moment.

那么我们LocalDateTime什么时候使用?在三种情况下:我们想要在多个位置应用某个日期和时间,我们在那里预订约会,或者我们有一个预期但未确定的时区。请注意,这三个案例都不是时间线上的某个特定点,它们都不是一个时刻。

One time-of-day, multiple moments

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

Sometimes we want to represent a certain time-of-day on a certain date, but want to apply that into multiple localities across time zones.

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

For example, "Christmas starts at midnight on the 25th of December 2015" is a LocalDateTime. Midnight strikes at different moments in Paris than in Montréal, and different again in Seattleand in Auckland.

例如,“圣诞节从 2015 年 12 月 25 日午夜开始”是一个LocalDateTime. 午夜在巴黎和蒙特利尔发生的时间不同,在西雅图奥克兰也有所不同。

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

Another example, "Acme Company has a policy that lunchtime starts at 12:30 PM at each of its factories worldwide" is a LocalTime. To have real meaning you need to apply it to the timeline to figure the moment of 12:30 at the Stuttgartfactory or 12:30 at the Rabatfactory or 12:30 at the Sydneyfactory.

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

Booking appointments

预约面谈

Another situation to use LocalDateTimeis for booking future events (ex: Dentist appointments). These appointments may be far enough out in the future that you risk politicians redefining the time zone. Politicians often give little forewarning, or even no warning at all. If you mean "3 PM next January 23rd" regardless of how the politicians may play with the clock, then you cannot record a moment – that would see 3 PM turn into 2 PM or 4 PM if that region adopted or dropped Daylight Saving Time, for example.

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

For appointments, store a LocalDateTimeand a ZoneId, kept separately. Later, when generating a schedule, on-the-fly determine a moment by calling LocalDateTime::atZone( ZoneId )to generate a ZonedDateTimeobject.

对于约会,存储 aLocalDateTime和 a 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.

If needed, you can adjust to UTC. Extract an Instantfrom the ZonedDateTime.

如果需要,您可以调整为 UTC。提取InstantZonedDateTime

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

Unknown zone

未知区域

Some people might use LocalDateTimein a situation where the time zone or offset is unknown.

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

I consider this case inappropriate and unwise. If a zone or offset is intended but undetermined, you have bad data. That would be like storing a price of a product without knowing the intended currency. Not a good idea.

我认为这个案子不恰当和不明智。如果区域或偏移量是预期的但未确定,则您的数据是错误的。这就像在不知道预期货币的情况下存储产品价格一样。不是个好主意。

All date-time types

所有日期时间类型

For completeness, here is a table of all the possible date-time types, both modern and legacy in Java, as well as those defined by the SQL standard. This might help to place the Instant& LocalDateTimeclasses in a larger context.

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

Table of all date-time types in Java (both modern & legacy) as well as SQL standard.

Java(现代和传统)以及 SQL 标准中所有日期时间类型的表。

Notice the odd choices made by the Java team in designing JDBC 4.2. They chose to support all the java.timetimes… except for the two most commonly used classes: Instant& ZonedDateTime.

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

But not to worry. We can easily convert back and forth.

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

Converting Instant.

转换Instant.

// Storing
OffsetDateTime odt = instant.atOffset( ZoneOffset.UTC ) ;
myPreparedStatement.setObject( … , odt ) ;

// Retrieving
OffsetDateTime odt = myResultSet.getObject( … , OffsetDateTime.class ) ;
Instant instant = odt.toInstant() ;

Converting ZonedDateTime.

转换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 ) ; 


About java.time

关于java.time

The java.timeframework is built into Java 8 and later. These classes supplant the troublesome old legacydate-time classes such as java.util.Date, Calendar, & SimpleDateFormat.

java.time框架是建立在Java 8和更高版本。这些类取代了麻烦的旧的遗留日期时间类,例如java.util.Date, Calendar, & SimpleDateFormat

The Joda-Timeproject, now in maintenance mode, advises migration to the java.timeclasses.

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

To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310.

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

You may exchange java.timeobjects directly with your database. Use a JDBC drivercompliant with JDBC 4.2or later. No need for strings, no need for java.sql.*classes.

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

Where to obtain the java.time classes?

从哪里获得 java.time 类?

Table of which java.time library to use with which version of Java or Android

哪个 java.time 库与哪个版本的 Java 或 Android 一起使用的表

The ThreeTen-Extraproject extends java.time with additional classes. This project is a proving ground for possible future additions to java.time. You may find some useful classes here such as Interval, YearWeek, YearQuarter, and more.

ThreeTen-额外项目与其他类扩展java.time。该项目是未来可能添加到 java.time 的试验场。你可能在这里找到一些有用的类,比如IntervalYearWeekYearQuarter,和更多

回答by Dariusz

One main difference is the Localpart of LocalDateTime. If you live in Germany and create a LocalDateTimeinstance and someone else lives in USA and creates another instance at the very same moment (provided the clocks are properly set) - the value of those objects would actually be different. This does not apply to Instant, which is calculated independently from time zone.

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

LocalDateTimestores date and time without timezone, but it's initial value is timezone dependent. Instant's is not.

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

Moreover, LocalDateTimeprovides methods for manipulating date components like days, hours, months. An Instantdoes not.

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

apart from the nanosecond precision advantage of Instant and the time-zone part of LocalDateTime

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

Both classes have the same precision. LocalDateTimedoes not store timezone. Read javadocs thoroughly, because you may make a big mistake with such invalid assumptions: Instantand LocalDateTime.

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

回答by Tunaki

You are wrong about LocalDateTime: it does not store any time-zone information and it has nanosecond precision. Quoting the Javadoc (emphasis mine):

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

A date-time without a time-zone in the ISO-8601 calendar system, such as 2007-12-03T10:15:30.

LocalDateTime is an immutable date-time object that represents a date-time, often viewed as year-month-day-hour-minute-second. Other date and time fields, such as day-of-year, day-of-week and week-of-year, can also be accessed. Time is represented to nanosecond precision. For example, the value "2nd October 2007 at 13:45.30.123456789" can be stored in a LocalDateTime.

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

LocalDateTime 是一个不可变的日期时间对象,表示日期时间,通常被视为年-月-日-时-分-秒。也可以访问其他日期和时间字段,例如一年中的某一天、一周中的某一天和一年中的一周。时间以纳秒精度表示。例如,值“2nd October 2007 at 13:45.30.123456789”可以存储在 LocalDateTime 中。

The difference between the two is that Instantrepresents an offset from the Epoch (01-01-1970) and, as such, represents a particular instant on the time-line. Two Instantobjects created at the same moment in two different places of the Earth will have exactly the same value.

两者之间的区别在于Instant代表与纪元 (01-01-1970) 的偏移,因此,代表时间线上的特定时刻。Instant在地球的两个不同地方同时创建的两个对象将具有完全相同的值。

回答by user2418306

Instantcorresponds to time on the prime meridian (Greenwich).

Instant对应于本初子午线(格林威治)上的时间。

Whereas LocalDateTimerelative to OS time zone settings, and

LocalDateTime相对于操作系统时区设置,以及

cannot represent an instant without additional information such as an offset or time-zone.

如果没有附加信息(例如偏移量或时区),则无法表示瞬间。