Ern*_*dis 4 datetime date java-8 java-time zoneddatetime
我有这个方法来计算midnigt和当前时间作为长值:
/**
* Returns the time range between the midnight and current time in milliseconds.
*
* @param zoneId time zone ID.
* @return a {@code long} array, where at index: 0 - midnight time; 1 - current time.
*/
public static long[] todayDateRange(ZoneId zoneId) {
long[] toReturn = new long[2];
LocalTime midnight = LocalTime.MIDNIGHT;
LocalDate today = LocalDate.now(zoneId);
LocalDateTime todayMidnight = LocalDateTime.of(today, midnight);
ZonedDateTime todayMidnightZdt = todayMidnight.atZone(zoneId);
toReturn[0] = todayMidnightZdt.toInstant().toEpochMilli();
ZonedDateTime nowZdt = LocalDateTime.now().atZone(zoneId);
toReturn[1] = nowZdt.toInstant().toEpochMilli();
return toReturn;
}
Run Code Online (Sandbox Code Playgroud)
也许有更简单的方法可以做到这一点?
小智 7
你也可以这样做:
ZonedDateTime nowZdt = ZonedDateTime.now(zoneId);
ZonedDateTime todayAtMidnightZdt = nowZdt.with(LocalTime.MIDNIGHT);
Run Code Online (Sandbox Code Playgroud)
我想不出更简单的方法.
LocalDateTime.now().atZone(zoneId)和之间存在(棘手的)差异ZonedDateTime.now(zoneId).
对于下面的代码,我使用的是默认时区为的JVM America/Sao_Paulo,并将尝试在另一个时区(Europe/London)中获取当前日期和时间.在我运行此代码的那一刻,这是8月20 日 2017年,但在圣保罗的时间是17时56分,在伦敦是21:56.
当我做:
LocalDateTime nowLdt = LocalDateTime.now();
Run Code Online (Sandbox Code Playgroud)
它LocalDateTime使用JVM默认时区中的当前日期和时间创建一个.在这种情况下,它将获得圣保罗时区(即2017年8月20 日17:56)的当前日期和时间:
2017-08-20T 17:56:05.159
当我调用该atZone方法时,它会在指定的区域中创建一个ZonedDateTime与此日期和时间对应的内容:
ZoneId zoneId = ZoneId.of("Europe/London");
ZonedDateTime nowAtZone = nowLdt.atZone(zoneId);
Run Code Online (Sandbox Code Playgroud)
该nowAtZone变量将是:
2017-08-20T 17:56:05.159 + 01:00 [欧洲/伦敦]
同日(8月20 日 2017年)和一次在伦敦的时区(17:56).请注意,它不是伦敦的当前日期/时间.如果我得到相同的epochMilli:
System.out.println(nowAtZone.toInstant().toEpochMilli());
Run Code Online (Sandbox Code Playgroud)
这将是:
1503248165159
现在,如果我不使用LocalDateTime和direclty使用ZonedDateTime而不是:
ZonedDateTime nowZdt = ZonedDateTime.now(zoneId);
Run Code Online (Sandbox Code Playgroud)
它将获得伦敦的当前日期和时间,这将是:
2017-08-20T 21 :56:05.170 + 01:00 [欧洲/伦敦]
请注意,时间改变了(这是21:56).那是因为现在,在这一刻,这是伦敦的当前时间.如果我得到epochMilli值:
System.out.println(nowZdt.toInstant().toEpochMilli());
Run Code Online (Sandbox Code Playgroud)
价值将是:
1503262565170
请注意,它与使用的第一种情况不同LocalDateTime(即使您忽略毫秒值的差异,因为小时不同).如果您想要在指定时区使用当前日期和时间,则必须使用ZonedDateTime.now(zoneId).
使用LocalDateTime.now().atZone()不仅会产生不同的结果,但如果您在不同的JVM中运行,或者JVM默认时区发生更改(有人可能会错误配置它,或者在同一VM调用中运行的另一个应用程序),它也会发生变化TimeZone.setDefault().
只需提醒由于DST(夏令时)问题导致的角落案件.我将使用我居住的时区作为示例(America/Sao_Paulo).
在圣保罗,DST于2016年10月16 日开始:在午夜,时钟从午夜向上移动1小时到凌晨1点(偏移量-03:00从而变为-02:00).因此,在这个时区中,00:00到00:59之间的所有当地时间都不存在(你也可以认为时钟从23:59:59.999999999直接变为01:00).如果我在此间隔中创建本地日期,则会将其调整为下一个有效时刻:
ZoneId zone = ZoneId.of("America/Sao_Paulo");
// October 16th 2016 at midnight, DST started in Sao Paulo
LocalDateTime d = LocalDateTime.of(2016, 10, 16, 0, 0, 0, 0);
ZonedDateTime z = d.atZone(zone);
System.out.println(z);// adjusted to 2017-10-15T01:00-02:00[America/Sao_Paulo]
Run Code Online (Sandbox Code Playgroud)
当夏令时结束:在2月19日第 2017在午夜,时钟偏移回 1小时后,从午夜到23 PM的18 个(和从偏移变化-02:00到-03:00).所以从23:00到23:59的所有当地时间都存在两次(在两个偏移中:-03:00和-02:00),你必须决定你想要哪一个.默认情况下,它使用DST结束前的偏移量,但您可以使用该withLaterOffsetAtOverlap()方法在DST结束后获取偏移量:
// February 19th 2017 at midnight, DST ends in Sao Paulo
// local times from 23:00 to 23:59 at 18th exist twice
LocalDateTime d = LocalDateTime.of(2017, 2, 18, 23, 0, 0, 0);
// by default, it gets the offset before DST ends
ZonedDateTime beforeDST = d.atZone(zone);
System.out.println(beforeDST); // before DST end: 2018-02-17T23:00-02:00[America/Sao_Paulo]
// get the offset after DST ends
ZonedDateTime afterDST = beforeDST.withLaterOffsetAtOverlap();
System.out.println(afterDST); // after DST end: 2018-02-17T23:00-03:00[America/Sao_Paulo]
Run Code Online (Sandbox Code Playgroud)
请注意,DST结束前后的日期具有不同的偏移量(-02:00和-03:00).这会影响epochMilli的价值.
如果使用with方法调整时间,也会发生上述情况.
| 归档时间: |
|
| 查看次数: |
771 次 |
| 最近记录: |