我在这里使用 java.time 正确吗?看来旧的 API 会更容易

Chr*_*ltz 1 java datetime java-time

我没有java.time经常使用该 API,因为我的工作主要涉及捕获、存储和显示日期和时间,而不以任何方式操作它们。但有时,我必须做这样的事情:

  • 获取过去 30 天的日期

我还认为,基于其他不相关的经验,人类倾向于认为“过去 30 天”实际上意味着“过去 30 天的一天的开始”,而不仅仅是“现在减去30*24*60*60*1000过去的毫秒”。只需 System.currentTimeMillis 和算术即可轻松完成。

所以我的要求是:

  • 获取我所在时区 30 天前的日期

如果我要使用旧的 API 来执行此操作,我会这样做:

TimeZone zone = ...; // However I get my time zone
Locale locale = ...; // However I get my locale
Calendar now = Calendar.getInstance(zone, locale);
// Reset to midnight
now.set(Calendar.HOUR, 0);
now.set(Calendar.MINUTE, 0);
now.set(Calendar.SECOND, 0);
now.set(Calendar.MILLISECOND, 0);
// Now go back 30 days
now.add(Calendar.DAY, -30);
// done
Run Code Online (Sandbox Code Playgroud)

除了重复调用以清空 的时间部分之外Calendar,它非常简单。它只使用了 3 个类,其中两个是 和TimeZoneLocale,只有其中一个是真正必要的 ( TimeZone)。

这一次,我决定使用java.time,因为,它“更好”。我真的不知道如何解决它,所以我在网上进行了大量搜索以找出如何做各种事情,最后我想出了下面的代码。这不是应该“更容易”吗?

TimeZone zone = ...; // However I get my time zone
ZoneId zid = zone.toZoneId(); // Convert to new kind of time zone
ZonedDateTime date = ZonedDateTime.now(zid);
date = date.minus(Period.ofDays(30)); // Rewind 30 days
date = date.truncatedTo(ChronoUnit.DAYS);
Instant instant = date.toInstant(); // Convert to Instant for comparisons
Run Code Online (Sandbox Code Playgroud)

现在我正在使用6 个不同的类。好吧,其中有两个是常量类型的东西,所以我们可以忽略它们。我必须使用,Instant因为我必须用于比较的所有日期都是java.util.DateInstant是弥合所有差距的类。

问题是这是一个“简单的问题”并且java.time旨在解决更复杂的问题吗?

Thi*_*ilo 8

获取过去 30 天的日期

听上去像

java.time.LocalDate.now().minusDays(30)

  • @ChristopherSchultz 不,“LocalDate”代表仅日期值。没有时间、没有时区、没有与 UTC 的偏移。阅读[Javadoc](https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/time/LocalDate.html)将对您有很大帮助。 (2认同)

Mik*_*Hay 6

中多个不同类的目的java.time正是对您在问题中提到的许多事物进行建模。

\n
\n

人们倾向于认为“过去 30 天”实际上意味着“过去 30 天的开始”

\n
\n

是的,你不关心时间,所以你不需要 a DateTime,只需要LocalDate.

\n
LocalDate prev = LocalDate.now().minusDays(30);\n
Run Code Online (Sandbox Code Playgroud)\n

如果必须转换为Instant,则需要指定时区。

\n
Instant asInstant = prev.atStartOfDay\xe2\x80\x8b(zone).toInstant();\n
Run Code Online (Sandbox Code Playgroud)\n

但是,如果您不关心时间,那么您可能不应该转换为 Instant,只需坚持使用LocalDate.

\n
\n

我必须使用 Instant,因为我必须用于比较的所有日期都是 java.util.Date

\n
\n

Date包括时间部分。您是否也将它们截断到一天的开始?执行此操作并返回 a 的一种方法LocalDate是:

\n
date.toInstant().atZone(zone).toLocalDate();\n
Run Code Online (Sandbox Code Playgroud)\n