java.time 相当于 Joda-Time `withTimeAtStartOfDay`? (获取当天的第一刻)
java.time equivalent of Joda-Time `withTimeAtStartOfDay`? (get first moment of the day)
在Joda-Time library, the DateTime
class offers a method withTimeAtStartOfDay
获得当天的第一刻。您可能会认为那一刻是 "midnight"。第一时刻通常是 00:00:00.000
但并非总是如此。
在 Java 8 及更高版本中找到的 java.time package 是否具有等效功能?
您可以使用 LocalDate
来执行此操作:
// or a similar factory method to get the date you want
LocalDateTime startOfDay = LocalDate.now().atStartOfDay();
Combines this date with the time of midnight to create a LocalDateTime at the start of this date. This returns a LocalDateTime formed from this date at the time of midnight, 00:00, at the start of this date.
https://docs.oracle.com/javase/8/docs/api/java/time/LocalDate.html#atStartOfDay--
等同于使用一种特殊的方法,atStartOfDay, in the class LocalDate
:
ZoneId zoneId = ZoneId.of("America/New_York");
ZonedDateTime zdt = LocalDate.now(zoneId).atStartOfDay(zoneId);
另请注意,在巴西相当于 Joda-Time DateTime
is not LocalDateTime
, but ZonedDateTime
. The zoneId
parameter matters here. Concrete example for migration - see also timezone website for details about 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(…) 的文档:
In most cases, there is only one valid offset for a local date-time. In the case of an overlap, when clocks are set back, there are two valid offsets. This method uses the earlier offset typically corresponding to "summer".
In the case of a gap, when clocks jump forward, there is no valid offset. Instead, the local date-time is adjusted to be later by the length of the gap. For a typical one hour daylight savings change, the local date-time will be moved one hour later into the offset typically corresponding to "summer".
不可能 100% 迁移所有细节,例如异常行为和应用的 DST 转换策略,因为两个库差异太大。但这是你的指导方针:
- 将
DateTime
替换为ZonedDateTime
- 考虑切换到
LocalDate
进行中间计算(参见示例)
- 使用对时区的显式引用并将
DateTimeZone
替换为 ZoneId
TemporalAdjuster
每个 LocalTime
is also a 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]")));
}
Java时间truncatedTo
虽然这是一个老问题,但我刚刚发现了另一种方法,使用 truncation,对我来说感觉更优雅:
ZonedDateTime now = ZonedDateTime.now();
ZonedDateTime today = now.truncatedTo(ChronoUnit.DAYS); // today, midnight
这更便于输入,并且在代码中需要更少的中间值。据我所知,语义与接受的答案相同。
在Joda-Time library, the DateTime
class offers a method withTimeAtStartOfDay
获得当天的第一刻。您可能会认为那一刻是 "midnight"。第一时刻通常是 00:00:00.000
但并非总是如此。
在 Java 8 及更高版本中找到的 java.time package 是否具有等效功能?
您可以使用 LocalDate
来执行此操作:
// or a similar factory method to get the date you want
LocalDateTime startOfDay = LocalDate.now().atStartOfDay();
Combines this date with the time of midnight to create a LocalDateTime at the start of this date. This returns a LocalDateTime formed from this date at the time of midnight, 00:00, at the start of this date.
https://docs.oracle.com/javase/8/docs/api/java/time/LocalDate.html#atStartOfDay--
等同于使用一种特殊的方法,atStartOfDay, in the class LocalDate
:
ZoneId zoneId = ZoneId.of("America/New_York");
ZonedDateTime zdt = LocalDate.now(zoneId).atStartOfDay(zoneId);
另请注意,在巴西相当于 Joda-Time DateTime
is not LocalDateTime
, but ZonedDateTime
. The zoneId
parameter matters here. Concrete example for migration - see also timezone website for details about 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(…) 的文档:
In most cases, there is only one valid offset for a local date-time. In the case of an overlap, when clocks are set back, there are two valid offsets. This method uses the earlier offset typically corresponding to "summer".
In the case of a gap, when clocks jump forward, there is no valid offset. Instead, the local date-time is adjusted to be later by the length of the gap. For a typical one hour daylight savings change, the local date-time will be moved one hour later into the offset typically corresponding to "summer".
不可能 100% 迁移所有细节,例如异常行为和应用的 DST 转换策略,因为两个库差异太大。但这是你的指导方针:
- 将
DateTime
替换为ZonedDateTime
- 考虑切换到
LocalDate
进行中间计算(参见示例) - 使用对时区的显式引用并将
DateTimeZone
替换为ZoneId
TemporalAdjuster
每个 LocalTime
is also a 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]")));
}
Java时间truncatedTo
虽然这是一个老问题,但我刚刚发现了另一种方法,使用 truncation,对我来说感觉更优雅:
ZonedDateTime now = ZonedDateTime.now();
ZonedDateTime today = now.truncatedTo(ChronoUnit.DAYS); // today, midnight
这更便于输入,并且在代码中需要更少的中间值。据我所知,语义与接受的答案相同。