我知道:
即时是用于计算的“技术”时间戳表示(纳秒)。 LocalDateTime是日期/时钟表示形式,包括人类的时区。 最后,对于大多数应用程序用例,IMO都可以视为两种类型。例如:当前我正在运行一个批处理作业,我需要根据日期计算下一次运行,并且我正在努力寻找这两种类型之间的优缺点(除了Instant和时区部分的纳秒级精度优势)的LocalDateTime)。
您可以列举一些应用示例,仅应使用Instant或LocalDateTime吗?
编辑:提防有关精度和时区的LocalDateTime的误读文档
tl; dr
Instant和LocalDateTime是两个完全不同的动物:一个表示了一下,其他没有。
Instant
LocalDateTime
Incorrect Presumption
LocalDateTime 而是日期/时钟表示,包括人类的时区。
你的说法是不正确:一个LocalDateTime有没有时区。没有时区是该课程的重点。
引用该类的文档:
此类不存储或表示时区。相反,它是对用于生日的日期的描述,以及在墙上时钟上看到的本地时间。如果没有其他信息(例如偏移或时区),则无法在时间线上表示时刻。
因此Local…意味着“不分区,不偏移”。
Local…
An Instant是UTC时间轴上的一刻,是自1970年UTC的第一刻的纪元以来的十亿分之一秒(基本上,请参阅class doc了解更多细节)。由于大多数业务逻辑,数据存储和数据交换都应使用UTC,因此这是经常使用的方便类。
An Instant
class doc
Instant instant = Instant.now() ; // Capture the current moment in UTC.
OffsetDateTime
class OffsetDateTime类将时刻表示为日期和时间,上下文比UTC早或晚一些小时-分钟-秒。偏移量(小时-分钟-秒的数量)由此ZoneOffset类表示。
class OffsetDateTime
ZoneOffset
如果时分秒数为零,则OffsetDateTime表示UTC中与相同的时刻Instant。
所述ZoneOffset类表示偏移从-UTC,若干小时-分钟-秒比UTC或后面UTC。
A ZoneOffset仅是小时-分钟-秒的数量,仅此而已。区域更多,具有名称和偏移更改的历史记录。因此,使用区域总是优于仅使用偏移量。
A ZoneOffset
ZoneId
在此处输入图片说明
阿时区是由表示ZoneId类。
例如,巴黎的新黎明比蒙特利尔早。因此,我们需要移动时钟指针以更好地反映给定区域的正午(当太阳直接在头顶上方)。西欧/非洲的UTC线向东/向西越远,偏移量越大。
时区是一组规则,用于处理本地社区或区域所实施的调整和异常情况。最常见的异常是称为“ 夏令时(DST)”的太流行的疯狂。
时区具有过去规则,当前规则和在不久的将来已确认的规则的历史。
这些规则更改的频率超出你的预期。确保保持日期时间库的规则(通常是’tz’数据库的副本)是最新的。通过Oracle发布Timezone Updater Tool,在Java 8中保持最新状态比以往更加容易。
Oracle
Timezone Updater Tool
Java 8
指定适当的时区名称,格式Continent/Region,如America/Montreal,Africa/Casablanca或Pacific/Auckland。切勿使用2-4字母的缩写,例如EST或,IST因为它们不是真实的时区,不是标准化的,甚至不是唯一的(!)。
America/Montreal,Africa/Casablanca
Pacific/Auckland
Time Zone = Offset + Rules of Adjustments
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。但是要向用户演示,你需要调整到用户期望的时区。这是用于生成这些日期时间值的String表示形式的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 ) ;
mardi 30 avril 2019à23 h 22 min 55 s heure de l'Inde
LocalDate,LocalTime,LocalDateTime
“本地”的日期时间类,LocalDateTime,LocalDate,LocalTime,有一种别样的小动物的。不受任何地区或时区的限制。它们不受时间限制。除非你将它们应用于某个地方以在时间轴上找到一个点,否则它们没有真正的意义。
LocalDateTime,LocalDate,LocalTime
这些类名称中的“本地”一词可能与未使用的单词相反。该词表示任何地点,或每个地点,但不是特定地点。
因此,对于商务应用程序,“本地”类型不常用,因为它们仅表示可能的日期或时间的一般概念,而不是时间轴上的特定时刻。商业应用程序倾向于关心发票到达的确切时间,运送产品的运输,雇用员工或出租车离开车库的确切时间。因此,业务应用程序开发人员最常使用Instant和ZonedDateTime分类。
那我们LocalDateTime什么时候用?在以下三种情况下:我们要在多个位置应用特定的日期和时间,我们要预约的位置,或者我们有一个尚未确定的时区。请注意,这三种情况都不是时间轴上的某个特定点,所有这些都不是片刻。
One time-of-day, multiple moments
有时我们想代表某个日期的某个特定时间,但又想将其应用于跨时区的多个地区。
例如,“圣诞节从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.
另一个示例是“ Acme公司有一项政策,即在全球每个工厂的午餐时间开始于12:30 PM” LocalTime。要具有实际意义,你需要将其应用于时间轴,以计算斯图加特工厂的12:30时刻或拉巴特工厂的12:30时刻或悉尼工厂的12:30时刻。
LocalTime
预约预约
使用的另一种情况LocalDateTime是用于预订将来的事件(例如:牙医约会)。这些任命将来可能远远不够,你可能会冒着政治家重新定义时区的风险。政客们很少发出警告,甚至根本没有警告。如果你的意思是“明年1月23日下午3点”,无论政客如何打钟,那么你就无法记录时刻-如果该地区采用或取消了夏时制,那将导致下午3点变成下午2点或下午4点,例如。
对于约会,请分别存储a LocalDateTime和a ZoneId。稍后,在生成时间表时,通过调用LocalDateTime::atZone( ZoneId )生成ZonedDateTime对象来即时确定时刻。
a LocalDateTime
a ZoneId
LocalDateTime::atZone( ZoneId )
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类放在更大的上下文中。
Instant&LocalDateTime
Java(现代和传统)以及SQL标准中所有日期时间类型的表格。
注意Java团队在设计JDBC 4.2时所做出的奇怪选择。他们选择支持所有java.time时间……,除了两个最常用的类:Instant&ZonedDateTime。
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。
java.util.Date
Calendar
SimpleDateFormat
现在处于维护模式的Joda-Time项目建议迁移到java.time类。
要了解更多信息,请参见Oracle教程。并在Stack Overflow中搜索许多示例和说明。规格为JSR 310。
你可以直接与数据库交换java.time对象。使用与JDBC 4.2或更高版本兼容的JDBC驱动程序。不需要字符串,不需要类。java.sql.*
在哪里获取java.time类?
该ThreeTen-额外项目与其他类扩展java.time。该项目是将来可能向java.time添加内容的试验场。你可能在这里找到一些有用的类,比如Interval,YearWeek,YearQuarter,和更多。
Interval,YearWeek,YearQuarter