别着急,用java.time
java.time
让我们看看使用 java.time 类添加六个小时的结果。
定义日期和时间部分。
LocalDate ld = LocalDate.of ( 2015, Month.OCTOBER, 24 ); // 24th Oct 2015 at 10:00am per the Question.
LocalTime lt = LocalTime.of ( 10, 0 );
为Europe/London 定义时区,ZoneId 对象。
ZoneId z = ZoneId.of ( "Europe/London" );
组合创建一个ZonedDateTime 对象。
ZonedDateTime zdtStart = ZonedDateTime.of ( ld, lt, z );
从ZonedDateTime 中提取Instant。 Instant 类代表UTC 时间线上的时刻,分辨率为nanoseconds(最多九 (9) 位小数)。
Instant instantStart = zdtStart.toInstant ( );
将我们的时间跨度(六个小时)定义为Duration。 java.time 类可以通过添加Duration 对象来执行日期时间数学。
Duration 未附加到时间线,实际上存储了秒数和纳秒数。因此,这门课中没有关于“六小时”以及时钟和夏令时等方面的聪明才智。当我们要求 Duration 为 6 小时时,该课程立即计算出 (6 小时 * 60 分钟/小时 * 60 秒/分钟) = 总共 21,600 秒。
Duration sixHours = Duration.ofHours ( 6 ); // 21,600 seconds = ( 6 hours * 60 minutes per hour * 60 seconds per minute ).
循环十次。第一个循环,将Duration 添加到ZonedDateTime,并将结果转换为Instant。
// Increment the `ZonedDateTime`.
ZonedDateTime zdt = zdtStart;
for ( int i = 1 ; i <= 10 ; i++ ) {
System.out.println ( ">zdt.toString() " + zdt + " | zdt.toInstant().toString(): " + zdt.toInstant ( ) + "\n");
// Set up next loop.
zdt = zdt.plus ( sixHours );
}
运行时。请注意伦敦时间的时间跳跃。这是Daylight Saving Time (DST) 切换,秋季的“回退”时间,当英格兰从+01:00 的UTC 偏移量到+00:00 的祖鲁语偏移量切换回标准时间时,在凌晨2 点时钟跳回以重复凌晨 1 点。因此,如果我们原本预计 22:00 加上 6 小时会导致凌晨 4 点,我们会看到凌晨 3 点。您可以在 Instant 值中看到六个小时确实过去了。诀窍是伦敦人大约在那时将时钟拨回一个小时。
请参阅history of DST cutovers 以获取Europe/London。
zdt.toString() 2015-10-24T10:00+01:00[欧洲/伦敦] | zdt.toInstant().toString(): 2015-10-24T09:00:00Z
zdt.toString() 2015-10-24T16:00+01:00[欧洲/伦敦] | zdt.toInstant().toString(): 2015-10-24T15:00:00Z
zdt.toString() 2015-10-24T22:00+01:00[欧洲/伦敦] | zdt.toInstant().toString(): 2015-10-24T21:00:00Z
zdt.toString() 2015-10-25T03:00Z[欧洲/伦敦] | zdt.toInstant().toString(): 2015-10-25T03:00:00Z
zdt.toString() 2015-10-25T09:00Z[欧洲/伦敦] | zdt.toInstant().toString(): 2015-10-25T09:00:00Z
zdt.toString() 2015-10-25T15:00Z[欧洲/伦敦] | zdt.toInstant().toString(): 2015-10-25T15:00:00Z
zdt.toString() 2015-10-25T21:00Z[欧洲/伦敦] | zdt.toInstant().toString(): 2015-10-25T21:00:00Z
zdt.toString() 2015-10-26T03:00Z[欧洲/伦敦] | zdt.toInstant().toString(): 2015-10-26T03:00:00Z
zdt.toString() 2015-10-26T09:00Z[欧洲/伦敦] | zdt.toInstant().toString(): 2015-10-26T09:00:00Z
zdt.toString() 2015-10-26T15:00Z[欧洲/伦敦] | zdt.toInstant().toString(): 2015-10-26T15:00:00Z
为了好玩,我们交换,将六个小时连续添加到Instant 并将结果转换为伦敦时间。
// Increment the `Instant`.
Instant instant = instantStart;
for ( int i = 1 ; i <= 10 ; i++ ) {
System.out.println ( ">instant.toString() " + instant + " | instant.atZone(z).toString(): " + instant.atZone ( z ) + "\n");
// Set up next loop.
instant = instant.plus ( sixHours );
}
运行时,我们看到相同的值输出。
instant.toString() 2015-10-24T09:00:00Z | instant.atZone(z).toString(): 2015-10-24T10:00+01:00[欧洲/伦敦]
instant.toString() 2015-10-24T15:00:00Z | instant.atZone(z).toString(): 2015-10-24T16:00+01:00[欧洲/伦敦]
instant.toString() 2015-10-24T21:00:00Z | instant.atZone(z).toString(): 2015-10-24T22:00+01:00[欧洲/伦敦]
instant.toString() 2015-10-25T03:00:00Z | instant.atZone(z).toString(): 2015-10-25T03:00Z[欧洲/伦敦]
instant.toString() 2015-10-25T09:00:00Z | instant.atZone(z).toString(): 2015-10-25T09:00Z[欧洲/伦敦]
instant.toString() 2015-10-25T15:00:00Z | instant.atZone(z).toString(): 2015-10-25T15:00Z[欧洲/伦敦]
instant.toString() 2015-10-25T21:00:00Z | instant.atZone(z).toString(): 2015-10-25T21:00Z[欧洲/伦敦]
instant.toString() 2015-10-26T03:00:00Z | instant.atZone(z).toString(): 2015-10-26T03:00Z[欧洲/伦敦]
instant.toString() 2015-10-26T09:00:00Z | instant.atZone(z).toString(): 2015-10-26T09:00Z[欧洲/伦敦]
instant.toString() 2015-10-26T15:00:00Z | instant.atZone(z).toString(): 2015-10-26T15:00Z[欧洲/伦敦]
看到这个code run live at IdeOne.com。
关于java.time
java.time 框架内置于 Java 8 及更高版本中。这些类取代了麻烦的旧 legacy 日期时间类,例如 java.util.Date、Calendar 和 SimpleDateFormat。
Joda-Time 项目现在位于maintenance mode,建议迁移到java.time 类。
要了解更多信息,请参阅Oracle Tutorial。并在 Stack Overflow 上搜索许多示例和解释。规格为JSR 310。
从哪里获得 java.time 类?
ThreeTen-Extra 项目通过附加类扩展了 java.time。该项目是未来可能添加到 java.time 的试验场。您可以在这里找到一些有用的类,例如Interval、YearWeek、YearQuarter 和more。