Java 使用with*函数、TemporalAdjuster或通过设置TemporalFields来调整ZonedDateTime之间是否有任何区别?

Java 使用with*函数、TemporalAdjuster或通过设置TemporalFields来调整ZonedDateTime之间是否有任何区别?,java,datetime,java-8,dayofweek,Java,Datetime,Java 8,Dayofweek,假设我有以下代码: java.time.ZonedDateTime inputZonedDateTime = inputDate.toInstant().atZone(zoneId); ZonedDateTime flattenedDateTime = inputZonedDateTime.withDayOfYear(1); 奇怪的是,这种实用方法几周内都不存在,所以几周来我都是这样实现的: flattenedDateTime = inputZonedDateTime.with(java.ti

假设我有以下代码:

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的特定场景中始终交替使用它们。尤其是因为“周”案例没有实用方法。

如果您怀疑这是否是正确的查找方法:

  • 将我的约会时间划分为一周中的一天,并将其调整为周一

    示例:05-03-2019….->04-03-2019 ....

  • 让我把日期时间划分为一个月的第一天

    示例:05-03-2019….->01-03-2019 ....

  • 那么答案是肯定的。
    我理解你的困惑。不同之处并不在于
    with xx
    方法与
    临时调整器的工作方式不同。区别在于:

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

    如果你确信你只想考虑ISO周,即星期一是第一天,UpPuxOnDeDeTime.Of(TeaField.Day-YoFo.PayWea,1)对于你的目的是很好的。否则,正确的解决方案是使用

    WeekFields
    对象及其
    dayOfWeek​()
    时间字段。将此字段设置为1将根据
    WeekFields
    对象表示的周定义设置为一周的第一天

    根据维基百科:

    • 在中东大部分地区,本周从周六开始
    • 在加拿大、美国、印度、日本、台湾、香港、澳门、以色列、埃及、南非、菲律宾和大部分拉丁语美国,从星期日开始。
    • 欧盟和大多数其他欧洲国家、大部分亚洲和大洋洲使用星期一(与ISO达成协议)
    我试图考虑到周日可能是一周中的第一天,例如在美国

    示例代码

        // 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));
    
    苏丹一周的第一天是2019年3月2日星期六下午12:00:00

    当然,您可以通过其他方式获得
    WeekFields.Of
    的正确区域设置。与几个其他地区的输出包括:

    • es PY: 巴拉圭一周的第一天是2019年3月3日星期日下午12:00:00

    • 毫克: 马达加斯加一周的第一天是2019年2月25日星期一下午12:00:00


    链接:

    我不太确定你的问题。你到底在找什么@Sebastiaan van den BroekI知道我可以找到像这样的日期,并且基本场景已经过测试,我特别想找出是否存在行为差异的边缘情况。是的,它们在功能上总是等同于被调用的应用程序情况。Java时间库经过了很多改进,它的完整性现在一点也不值得怀疑。(当然,使用上面提到的正确方法)@SebastiaanvandenBroekAround 96%的文化(>98%的世界人口)使用ISO或非ISO日历来定义一周7天,因此,相同的编号系统用于表示一周中的天数@Ole V.V.这是个好消息,因为我想把周日作为一周的第一天,比如在美国。但如果我的时区设置为美国的时区,我希望它仍能正常工作?或者我应该采取额外的步骤吗?好的,很不幸,这意味着如果我不能从时区推断它,系统将需要另一个设置。用户可以有不同时区的项目,他们也可能希望一周从正确的日期开始。看起来我的项目对象中需要另一个字段。@SebastiaanvandenBroek我添加了示例代码,说明如何根据特定区域设置及其周定义将datetime对象调整到每周的第一天。谢谢,我提出了
    ZonedDateTime FlattedDateTime=inputZonedDateTime.with(TemporalAdjusters.PreviousorName)(wf.getFirstDayOfWeek());
    但是你的看起来更简单。
        // 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));