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
What's the difference between Instant and LocalDateTime?
提问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
tl;dr
tl;博士
Instant
and LocalDateTime
are two entirely different animals: One represents a moment, the other does not.
Instant
并且LocalDateTime
是两种完全不同的动物:一种代表片刻,另一种则不代表。
Instant
represents a moment, a specific point in the timeline.LocalDateTime
represents 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
错误推定
LocalDateTime
is rather date/clock representation including time-zones for humans.
LocalDateTime
而是日期/时钟表示,包括人类的时区。
Your statement is incorrect: A LocalDateTime
has notime zone. Having no time zone is the entire point of that class.
你的说法是错误的:A LocalDateTime
has 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
An Instant
is 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.
AnInstant
是UTC时间线上的一个时刻,是自 1970 UTC 第一个时刻以来的纳秒计数(基本上,请参阅课程文档以获取详细信息)。由于您的大部分业务逻辑、数据存储和数据交换都应采用 UTC,因此这是一个经常使用的方便类。
Instant instant = Instant.now() ; // Capture the current moment in UTC.
OffsetDateTime
OffsetDateTime
The class OffsetDateTime
class 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 ZoneOffset
class.
类OffsetDateTime
类将时刻表示为日期和时间,其上下文为 UTC 之前或之后的某些小时-分钟-秒数。偏移量,即小时-分钟-秒数,由ZoneOffset
类表示。
If the number of hours-minutes-seconds is zero, an OffsetDateTime
represents a moment in UTC the same as an Instant
.
如果小时-分钟-秒数为零,则 anOffsetDateTime
表示与 UTC 相同的 UTC 时刻Instant
。
ZoneOffset
ZoneOffset
The ZoneOffset
class represents an offset-from-UTC, a number of hours-minutes-seconds ahead of UTC or behind UTC.
所述ZoneOffset
类表示偏移从-UTC,若干小时-分钟-秒比UTC或后面UTC。
A ZoneOffset
is 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
A time zoneis represented by the ZoneId
class.
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 EST
or IST
as they are nottrue time zones, not standardized, and not even unique(!).
以、、 或等格式指定正确的时区名称。永远不要使用 2-4 个字母的缩写,例如或因为它们不是真正的时区,不是标准化的,甚至不是唯一的(!)。Continent/Region
America/Montreal
Africa/Casablanca
Pacific/Auckland
EST
IST
Time Zone = Offset + Rules of Adjustments
时区 = 偏移量 + 调整规则
ZoneId z = ZoneId.of( “Africa/Tunis” ) ;
ZonedDateTime
ZonedDateTime
Think of ZonedDateTime
conceptually as an Instant
with 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 ZonedDateTime
class 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
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.
“本地”的日期时间类,LocalDateTime
,LocalDate
,LocalTime
,有一种别样的小动物的。与任何一个地点或时区无关。它们与时间线无关。在您将它们应用到某个地点以在时间线上找到一个点之前,它们没有真正的意义。
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 Instant
and ZonedDateTime
classes most commonly.
因此,对于商业应用程序,“本地”类型并不常用,因为它们仅代表可能的日期或时间的一般概念,而不是时间线上的特定时刻。商业应用程序往往关心发票到达、运输产品、雇用员工或出租车离开车库的确切时间。因此,商业应用程序开发人员最常使用Instant
和ZonedDateTime
类。
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 LocalDateTime
is 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 LocalDateTime
and a ZoneId
, kept separately. Later, when generating a schedule, on-the-fly determine a moment by calling LocalDateTime::atZone( ZoneId )
to generate a ZonedDateTime
object.
对于约会,存储 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 Instant
from the ZonedDateTime
.
如果需要,您可以调整为 UTC。提取Instant
自ZonedDateTime
。
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 LocalDateTime
in 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
& LocalDateTime
classes in a larger context.
为了完整起见,这里是所有可能的日期时间类型的表,包括 Java 中的现代和遗留,以及 SQL 标准定义的那些。这可能有助于将Instant
&LocalDateTime
类放在更大的上下文中。
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 类?
- Java SE 8, Java SE 9, Java SE 10, and later
- Built-in.
- Part of the standard Java API with a bundled implementation.
- Java 9 adds some minor features and fixes.
- Java SE 6and Java SE 7
- Much of the java.time functionality is back-ported to Java 6 & 7 in ThreeTen-Backport.
- Android
- Later versions of Android bundle implementations of the java.time classes.
- For earlier Android (<26), the ThreeTenABPproject adapts ThreeTen-Backport(mentioned above). See How to use ThreeTenABP….
- Java SE 8、Java SE 9、Java SE 10及更高版本
- 内置。
- 具有捆绑实现的标准 Java API 的一部分。
- Java 9 添加了一些小功能和修复。
- Java SE 6和Java SE 7
- 多的java.time功能后移植到Java 6和7在ThreeTen-反向移植。
- 安卓
- java.time 类的更高版本的 Android 捆绑实现。
- 对于早期的 Android(<26),ThreeTenABP项目采用了ThreeTen-Backport(上面提到过)。请参阅如何使用ThreeTenABP ...。
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 的试验场。你可能在这里找到一些有用的类,比如Interval
,YearWeek
,YearQuarter
,和更多。
回答by Dariusz
One main difference is the Local
part of LocalDateTime
. If you live in Germany and create a LocalDateTime
instance 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
独立于时区计算的 。
LocalDateTime
stores date and time without timezone, but it's initial value is timezone dependent. Instant
's is not.
LocalDateTime
存储没有时区的日期和时间,但它的初始值取决于时区。Instant
不是。
Moreover, LocalDateTime
provides methods for manipulating date components like days, hours, months. An Instant
does 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. LocalDateTime
does not store timezone. Read javadocs thoroughly, because you may make a big mistake with such invalid assumptions: Instantand LocalDateTime.
两个类具有相同的精度。LocalDateTime
不存储时区。彻底阅读 javadocs,因为您可能会因为这样无效的假设而犯大错误:Instant和LocalDateTime。
回答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 Instant
represents an offset from the Epoch (01-01-1970) and, as such, represents a particular instant on the time-line. Two Instant
objects 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
Instant
corresponds to time on the prime meridian (Greenwich).
Instant
对应于本初子午线(格林威治)上的时间。
Whereas LocalDateTime
relative to OS time zone settings, and
而LocalDateTime
相对于操作系统时区设置,以及
cannot represent an instant without additional information such as an offset or time-zone.
如果没有附加信息(例如偏移量或时区),则无法表示瞬间。