在Joda-Time库中,DateTime
类提供方法withTimeAtStartOfDay
以获取当天的第一时刻。你可能会认为那个时刻是“午夜”。第一个时刻通常是时间COMPRESS_OFFLINE = False
,但并非总是如此。
Java 8及更高版本中的java.time package是否具有等效功能?
答案 0 :(得分:5)
您可以使用LocalDate
执行此操作:
// or a similar factory method to get the date you want
LocalDateTime startOfDay = LocalDate.now().atStartOfDay();
将此日期与午夜时间相结合,以便在此日期开始时创建LocalDateTime。这将返回此日期在午夜00:00(此日期开始时)形成的LocalDateTime。
https://docs.oracle.com/javase/8/docs/api/java/time/LocalDate.html#atStartOfDay--
答案 1 :(得分:4)
等效的是在班级atStartOfDay中使用特殊方法LocalDate
:
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"。
的早期偏移量在间隙的情况下,当时钟向前跳跃时,没有有效的偏移。而是将本地日期时间调整为稍后的间隙长度。对于典型的一小时夏令时变化,本地日期时间将在一小时后移动到通常对应于"夏天"的偏移。
所有细节(如异常行为和应用的DST转换策略)的100%迁移是不可能的,因为两个库都太不同了。但这是你的准则:
DateTime
替换为ZonedDateTime
LocalDate
进行中间计算(参见示例)DateTimeZone
替换为ZoneId
答案 2 :(得分:3)
虽然这是一个老问题,但我刚刚发现了另一种方法,使用truncation,这让我觉得更优雅:
ZonedDateTime now = ZonedDateTime.now();
ZonedDateTime today = now.truncateTo(ChronoUnit.DAYS); // today, midnight
键入的时间更短,代码中的中间值更少。据我所知,语义与接受的答案相同。
答案 3 :(得分:1)
TemporalAdjuster
每个LocalTime
也是TemporalAdjuster
,因此可以传递给大多数时态类型的with()
方法,并更新时间字段以匹配。
那是:
@Test
public void date_time_at_start_of_day() throws Exception {
assertThat(LocalDateTime.parse("2015-05-22T12:27:00")
.with(LocalTime.MIDNIGHT),
equalTo(LocalDateTime.parse("2015-05-22T00:00:00")));
assertThat(OffsetDateTime.parse("2015-05-22T12:27:00+01:00")
.with(LocalTime.MIDNIGHT),
equalTo(OffsetDateTime.parse("2015-05-22T00:00:00+01:00")));
assertThat(ZonedDateTime.parse("2015-05-22T12:27:00+01:00[Europe/London]")
.with(LocalTime.MIDNIGHT),
equalTo(ZonedDateTime.parse("2015-05-22T00:00:00+01:00[Europe/London]")));
}