java - 使用 with* 函数、TemporalAdjusters 或设置 TemporalFields 调整 ZonedDateTimes 之间有什么区别吗?

标签 java datetime java-8 dayofweek

假设我有以下代码:

java.time.ZonedDateTime inputZonedDateTime = inputDate.toInstant().atZone(zoneId);
ZonedDateTime flattenedDateTime = inputZonedDateTime.withDayOfYear(1);

奇怪的是,这个实用方法已经几周不存在了,所以几周以来我都是这样实现的:

flattenedDateTime = inputZonedDateTime.with(java.time.temporal.ChronoField.DAY_OF_WEEK, 1);

然后你也可以这样做:

flattenedDateTime = inputZonedDateTime.with(TemporalAdjusters.firstDayOfMonth());

(几周后也无法使用)

这三种调整日期的方式有什么区别吗?我想确保它们始终在功能上等效,这样我确信在将 ChronoUnit 调整为 1 的特定场景中我可以始终互换使用它们。特别是因为“没有实用程序方法”周”案例。

最佳答案

我理解你的困惑。区别不在于 withXx 方法与 TemporalAdjusters 的工作方式不同。区别在于:

  • 一年的第一天和一个月的第一天被明确定义,因此很容易构建到 withXx 方法或时间调整器中。
  • 一周的第一天因文化而异。在某些地方,一周从星期日或其他日期开始。将 ChronoField.DAY_OF_WEEK 设置为 1 将星期几设置为星期一。因此,withFirstDayOfWeek 方法或 firstDayOfWeek 时间调整器都是危险的,并且会给一些用户带来令人惊讶的结果。

如果您确定只想考虑 ISO 周(其中星期一是第一天),则 inputZonedDateTime.with(ChronoField.DAY_OF_WEEK, 1) 适合您的目的。否则,正确的解决方案是使用 WeekFields 对象及其 dayOfWeek​() 时间字段。将此字段设置为 1 将根据 WeekFields 对象表示的周定义设置为一周的第一天。

根据维基百科:

  • 在中东大部分地区,一周从周六开始。
  • 在加拿大、美国、印度、日本、台湾、香港、澳门、以色列、埃及、南非、菲律宾和拉丁美洲大部分地区,该 Activity 于周日开始。
  • 欧盟和大多数其他欧洲国家、亚洲和大洋洲的大部分地区使用星期一(与 ISO 一致)。

I was trying to take into account that Sunday can be the first day of the week in for example the US.

示例代码

    // Don’t set default locale from production code, it’s for demonstration only
    Locale.setDefault(Locale.forLanguageTag("ar-SD"));

    WeekFields wf = WeekFields.of(Locale.getDefault());
    DateTimeFormatter formatter = DateTimeFormatter
            .ofLocalizedDateTime(FormatStyle.FULL, FormatStyle.MEDIUM)
            .withLocale(Locale.ENGLISH);

    ZonedDateTime inputZonedDateTime
            = ZonedDateTime.of(2019, 3, 3, 12, 0, 0, 0, ZoneId.of("Asia/Amman"));
    ZonedDateTime flattenedDateTime = inputZonedDateTime.with(wf.dayOfWeek(), 1);
    System.out.println("First day of week in "
            + Locale.getDefault().getDisplayCountry(Locale.ENGLISH)
            + " is " + flattenedDateTime.format(formatter));

First day of week in Sudan is Saturday, March 2, 2019, 12:00:00 PM

当然,您可以通过其他方式获取 WeekFields.of 的正确区域设置。其他几个语言环境的输出包括:

  • es-PY:

    First day of week in Paraguay is Sunday, March 3, 2019, 12:00:00 PM

  • 毫克-MG:

    First day of week in Madagascar is Monday, February 25, 2019, 12:00:00 PM

链接: Wikipedia article: week

关于java - 使用 with* 函数、TemporalAdjusters 或设置 TemporalFields 调整 ZonedDateTimes 之间有什么区别吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54998612/

相关文章:

c# - 如何将特定时区的午夜正确转换为 Utc 时间?

本地应用程序和 Jenkins 部署之间的 Java 日期时间不一致

java - 也使用@NonNull 来检查类成员

java - 有没有一种优雅的方式来分块处理流?

java - 将 Java-8 Stream 收集到 Guava ImmutableList 的最佳方式

Java 代码可以在一台机器上编译,但不能在另一台机器上编译

Java RegEx 字符串包含在引号内,但有附加要求

java - 如何修剪通过使用 Java 反射获得的同一方法的变体?

java - 查找应用程序在java中运行的服务器的端口

c# - 以 MM/YYYY 格式获取日期之间的所有月份