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