在 Java 中使用 LocalDate 时未通过的时间

Hours not coming through when using LocalDate in Java

我正在尝试将今天的日期格式化为 "MM/dd/yyy HH:00",其中分钟总是被清零。使用此格式时,时间显示不正确:

LocalDate date = DateTime.now().withZone(DateTimeZone.forID("America/New_York")).toLocalDate();
String format = date.toString("MM/dd/yyyy HH:00");

logger.info(format);

输出

是否有其他方法可以使用 LocalDate 来抢占时间?

来自 LocalDate 的 JavaDoc:

A date without a time-zone in the ISO-8601 calendar system, such as 2007-12-03.

和:

This class does not store or represent a time or time-zone. Instead, it is a description of the date, as used for birthdays. It cannot represent an instant on the time-line without additional information such as an offset or time-zone.

改用LocalDateTime

tl;博士

ZonedDateTime.now( ZoneId.of( "America/New_York" ) )
         .truncatedTo( java.time.temporal.ChronoUnit.HOURS )
         .format( DateTimeFormatter.ofPattern( "MM/dd/uuuu HH:mm" , Locale.US ) )

02/27/2017 23:00

详情

正确。

java.time 对比 Joda-Time

一个更大的问题:您似乎正在使用 Joda-Time classes but labeled your question with java-time meaning the java.time 类。

Meno Hochschild 对问题发表了评论,指出了这种明显的库混淆。

Joda-Time 项目是一个单独的库,未内置到 Java 中。该项目为 java.time 提供了灵感和经验。虽然在概念上相似,但 java.time 是完全重新设计的,根本不是直接替代品。 Joda-Time 和 java.time 都由同一个人领导,Stephen Colebourne (“jodastephen”). The Joda-Time project is now in maintenance mode, with the team advising migration to the java.time 类.

java.time中没有DateTimeDateTimeZone类。

使用java.time

在java.time中,你的代码应该是这样的。

ZoneId z = ZoneId.of( "America/New_York" ) ;
LocalDate localDate = LocalDate.now( z ) ;

但是您想要一天中的时间,并且 , you need to use another class as LocalDate is date-only without any time-of-day. Instead use ZonedDateTime to get the date and the time-of-day as seen through a particular region’s wall-clock time determined by a ZoneId

ZoneId z = ZoneId.of( "America/New_York" ) ;
ZonedDateTime zdt = ZonedDateTime.now( z ) ;

格式化模式的误用

另一个问题:对格式化模式进行硬编码以显示零而不是分钟是实现您的目标的一种棘手方法。这样做并不能使您的意图明确。阅读您的代码的其他程序员可能会错过您的操作。

我发现如果“说实话”的代码更易于维护。因此,与其用硬编码的零数字更改分钟的显示来“撒谎”,不如更改基础数据本身。好处包括明确您的意图,并使调试器中看到的值与您的字符串输出相匹配。

truncatedTo

我建议您显式更改日期时间对象的值。调用truncatedTo方法去掉分秒和小数秒。那些被砍掉的值变成零。

java.time 使用 immutable objects。因此,我们不是更改对象的值(“变异”),而是生成一个新对象,其值基于原始对象的值。

ZoneId z = ZoneId.of( "America/New_York" ) ;
ZonedDateTime zdt = ZonedDateTime.now( z ) ;
ZonedDateTime zdtTruncatedToHour = zdt.truncatedTo( java.time.temporal.ChronoUnit.HOURS ) ;

zdtTruncatedToHour.toString(): 2017-02-27T23:00-05:00[America/New_York]

从那里,您可以使用通常的 toStringDateTimeFormatter 方法生成字符串,在分、秒和小数秒中只出现零。

DateTimeFormatter f = DateTimeFormatter.ofPattern( "MM/dd/uuuu HH:mm" , Locale.US );
String output = zdtTruncatedToHour.format( f );

02/27/2017 23:00

查看此示例 code running live in IdeOne.com


关于java.time

java.time framework is built into Java 8 and later. These classes supplant the troublesome old legacy date-time classes such as java.util.Date, Calendar, & SimpleDateFormat.

Joda-Time project, now in maintenance mode, advises migration to the java.time 类.

要了解更多信息,请参阅 Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310

java.time类在哪里获取?

  • Java SE 8 and SE 9 及更高版本
    • 内置。
    • 标准 Java API 的一部分,带有捆绑实施。
    • Java 9 添加了一些小功能和修复。
  • Java SE 6 and SE 7
  • Android
    • ThreeTenABP 项目专门为 Android 改编 ThreeTen-Backport(如上所述)。
    • 参见

ThreeTen-Extra project extends java.time with additional classes. This project is a proving ground for possible future additions to java.time. You may find some useful classes here such as Interval, YearWeek, YearQuarter, and more.