等效的方法是在 LocalDate 类中使用特殊方法 atStartOfDay:
ZoneId zoneId = ZoneId.of("America/New_York");
ZonedDateTime zdt = LocalDate.now(zoneId).atStartOfDay(zoneId);
还请注意,Joda-Time DateTime 的等价物不是LocalDateTime,而是ZonedDateTime。 zoneId 参数在这里很重要。迁移的具体示例 - 另请参阅 timezone website 了解有关巴西 Daylight Saving Time (DST) 转换的详细信息:
Joda-Time(旧方式)
DateTime dt =
new DateTime(2015, 10, 18, 12, 0, DateTimeZone.forID("America/Sao_Paulo"));
dt = dt.withTimeAtStartOfDay();
System.out.println(dt); // 2015-10-18T01:00:00.000-02:00
请注意,此代码甚至会在第一行调用constructor 时引发午夜异常。
java.time(新方式)
ZoneId zoneId = ZoneId.of("America/Sao_Paulo");
ZonedDateTime zdt =
ZonedDateTime.of(2015, 10, 18, 12, 0, 0, 0, zoneId);
zdt = zdt.toLocalDate().atStartOfDay(zoneId);
System.out.println(zdt); // 2015-10-18T01:00-02:00[America/Sao_Paulo]
第二个程序语句的行为与 Joda-Time 不同,因为它不会抛出异常,而是将本地时间静默地移动所讨论的间隙大小,这里是一小时。这意味着,如果您选择了午夜,结果将是相同的(即 1:00)。如果您选择了 00:30,那么结果将是 01:30。上面给出的示例选择中午作为输入。
引用ZonedDateTime.of(…)的文档:
在大多数情况下,本地日期时间只有一个有效偏移量。在重叠的情况下,当时钟被调回时,有两个有效的偏移量。此方法使用通常对应于“summer”的较早偏移量。
在间隙的情况下,当时钟向前跳时,没有有效的偏移量。相反,本地日期时间会根据间隙的长度进行调整。对于典型的一小时夏令时更改,本地日期时间将在一小时后移动到通常对应于“夏季”的偏移量中。
不可能 100% 迁移所有细节,例如异常行为和应用的 DST 转换策略,因为这两个库差异太大。但这是你的指导方针:
- 将
DateTime 替换为ZonedDateTime
- 考虑切换到
LocalDate 进行中间计算(参见示例)
- 使用对时区的显式引用并将
DateTimeZone 替换为ZoneId