java.time相当于Joda-Time`withTimeAtStartOfDay`? (获得当天的第一时刻)

时间:2015-05-18 01:06:43

标签: java datetime java-time

Joda-Time库中,DateTime类提供方法withTimeAtStartOfDay以获取当天的第一时刻。你可能会认为那个时刻是“午夜”。第一个时刻通常是时间COMPRESS_OFFLINE = False,但并非总是如此。

Java 8及更高版本中的java.time package是否具有等效功能?

4 个答案:

答案 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,而是ZonedDateTimezoneId参数在此处很重要。迁移的具体示例 - 有关巴西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]")));
}