java - 本地日期不一致

标签 java date time java-time localdate

我正在尝试从 LocalDate 对象 (java.time) 生成 Date 对象 (java.util.Date) .LocalDate),其中我有以下标准:

  • 允许使用可以从 Date 对象中减去特定天数的参数
  • 将日期和时间设置为当前 UTC 日期和时间
  • 在一天的开始时间,即 00:00:00
  • 时区标记(即 CDT 或 UTC)无关紧要,因为我将其从 String 中删除了

为了满足这个标准,我创建了一个测试程序,但是当我修改 LocalDate 的某个属性时,我得到了有趣的结果。请参阅下面的代码:

  public static void main (String args[]) {
    Long processingDaysInPast = 0L;
    LocalDate createdDate1 = LocalDate.now(Clock.systemUTC()).minusDays(processingDaysInPast);
    LocalDate createdDate2 = LocalDate.now(Clock.systemUTC()).minusDays(processingDaysInPast);
    System.out.println(createdDate1);
    System.out.println(createdDate1.atStartOfDay().toInstant(ZoneOffset.UTC));
    System.out.println(Date.from(createdDate1.atStartOfDay().toInstant(ZoneOffset.UTC)));
    System.out.println((createdDate2.atStartOfDay().atZone(ZoneId.systemDefault()).toInstant()));
    System.out.println(Date.from(createdDate2.atStartOfDay().atZone(ZoneId.systemDefault()).toInstant()));
}

输出:

 2017-08-14
 2017-08-14T00:00:00Z
 Sun Aug 13 19:00:00 CDT 2017
 2017-08-14
 2017-08-14T05:00:00Z
 Mon Aug 14 00:00:00 CDT 2017

当我添加值 Date.from(createdDate1.atStartOfDay().toInstant(ZoneOffset.UTC)) 时,我得到了日期的预期输出,其中 00:00: 00 时间字段。但是,如果我不添加此参数,例如: Date.from(createdDate2.atStartOfDay().atZone(ZoneId.systemDefault()).toInstant()) 我会得到结果 day before , 19:00:00 这是为什么?

我的主要目标是能够捕获 Date 对象,其中包含当前 UTC 日期,并且时间归零 (StartOfDay)。

最佳答案

当你这样做时:

createdDate2.atStartOfDay().atZone(ZoneId.systemDefault())

首先,createdDate2.atStartOfDay()返回 LocalDateTime ,相当于 2017-08-14在午夜。一个LocalDateTime不了解时区。

当您调用atZone(ZoneId.systemDefault())时,它创建一个ZonedDateTime以及系统默认时区中的相应日期 (2017-08-14) 和时间(午夜)( ZoneId.systemDefault() )。在您的情况下,默认时区不是 UTC(它是“CDT”,因此 CDT 已是午夜 - 只需执行 System.out.println(ZoneId.systemDefault()) 来检查您的默认时区是什么)。

要获取 UTC 午夜日期,您可以将默认区域 ( ZoneId.systemDefault() ) 替换为 UTC ( ZoneOffset.UTC ):

Date.from(createdDate2.atStartOfDay().atZone(ZoneOffset.UTC).toInstant())

或者(较短的版本):

Date.from(createdDate2.atStartOfDay(ZoneOffset.UTC).toInstant())

当然你也可以像 createdDate1 那样做。 :

Date.from(createdDate2.atStartOfDay().toInstant(ZoneOffset.UTC))

它们都是等效的,并且结果将是 UTC 的午夜。


简单说明一下:短时区名称,例如 CDTPST不是真正的时区。
API 使用IANA timezones names (始终采用 Region/City 格式,例如 America/ChicagoEurope/Berlin )。 避免使用 3 个字母的缩写(如 CDTPST ),因为它们是 ambiguous and not standard .

lots of different timezones可以使用CDT作为缩写。发生这种情况是因为时区是一个地区在历史上曾经、现在和将来的所有不同偏移量的集合。仅仅因为很多地方使用CDT今天,并不意味着它们在过去的同一时期都使用过,也不意味着将来也会被所有人使用。由于历史不同,每个地区都会创建一个时区。

关于java - 本地日期不一致,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45680464/

相关文章:

symfony - 奏鸣曲日期范围

date - 雅典娜日期格式无法将字符串转换为日期格式

PHP - 将日期转换为 YYYY-MM-DDTHH :MM:SS

php - SQL - 在特定时间(或 ID)后选择新值

Maven 中的 Java EE 7 First Cup 教程错误 : Could not find artifact org. glassfish.javaeetutorial.firstcup :firstcup:pom:7. 0.1-SNAPSHOT

java - 如何从 mongodb 或 java 查询 prolog 中的文件

java - 如何在没有 numpy 的情况下将 Python 代码转换为 Java

java - 如何使用 POM 在类路径中添加本地 jars 文件夹

php - 如何清除 15 分钟或更早的 MySQL 记录?

unix - log15 库将纪元时间从纳秒舍入到秒以进行日志记录