Java 独立于区域设置的年-周日期格式

Java 独立于区域设置的年-周日期格式,java,datetime,datetime-format,java-time,Java,Datetime,Datetime Format,Java Time,我想以独立于区域设置的方式打印一个即时,在一周的第一天(星期一)和第一周的最短天数(4)中使用ISO设置 我当前的设置是: private String print(Instant i) { DateTimeFormatter formatter = DateTimeFormatter .ofPattern("YYYY-ww") .withZone(UTC); return formatter.format(i); } @Test

我想以独立于区域设置的方式打印一个
即时
,在一周的第一天(星期一)和第一周的最短天数(4)中使用ISO设置

我当前的设置是:

private String print(Instant i) {
    DateTimeFormatter formatter = DateTimeFormatter
            .ofPattern("YYYY-ww")
            .withZone(UTC);
    return formatter.format(i);
}

@Test
public void test() {
    System.out.format("First day of week      : %s%n",
            WeekFields.of(Locale.getDefault()).getFirstDayOfWeek());
    System.out.format("Min days in 1st week   : %s%n",
            WeekFields.of(Locale.getDefault()).getMinimalDaysInFirstWeek());
    Instant instant = Instant.parse("1998-12-31T00:00:00Z");
    System.out.println(print(instant));
}
对于系统区域设置“en_US”,测试打印:

First day of week      : SUNDAY
Min days in 1st week   : 1
1999-01
First day of week      : MONDAY
Min days in 1st week   : 4
1998-53
对于系统区域设置“de_de”,测试打印:

First day of week      : SUNDAY
Min days in 1st week   : 1
1999-01
First day of week      : MONDAY
Min days in 1st week   : 4
1998-53
“de_de”区域设置与ISO设置一致,我知道我可以将格式化程序设置为

DateTimeFormatter formatter = DateTimeFormatter
        .ofPattern("YYYY-ww")
        .withZone(UTC)
        .withLocale(Locale.GERMANY);
但是,我可以在不指定绑定到特定国家/地区的任何语言环境的情况下执行此操作吗?我找到了
java.time.temporal.WeekFields\ISO

public static final WeekFields ISO = new WeekFields(DayOfWeek.MONDAY, 4);

这正是我想要的,但我不知道如何将它与
DateTimeFormatter

相结合。您可以使用
java.time.format.DateTimeFormatterBuilder
WeekFields.ISO
的相应字段:

public static final WeekFields ISO = new WeekFields(DayOfWeek.MONDAY, 4);
  • 以周为基础的年份(即
  • 以周为单位的年(即
代码是:

DateTimeFormatter formatter = new DateTimeFormatterBuilder()
    // append week year
    .appendValue(WeekFields.ISO.weekBasedYear(), 4)
    // separator
    .appendLiteral('-')
    // append week of week year field
    .appendValue(WeekFields.ISO.weekOfWeekBasedYear(), 2)
    // create formatter
    .toFormatter().withZone(ZoneOffset.UTC);
不要创建新的
WeekFields
实例(使用
WeekFields.of(locale)
),只需使用
WeekFields.ISO

System.out.format("First day of week      : %s%n", WeekFields.ISO.getFirstDayOfWeek());
System.out.format("Min days in 1st week   : %s%n", WeekFields.ISO.getMinimalDaysInFirstWeek());
Instant instant = Instant.parse("1998-12-31T00:00:00Z");
System.out.println(formatter.format(instant));
输出为:

每周第一天:星期一
第一周的最小天数:4
1998-53


即使我更改了格式化程序的区域设置:

formatter = formatter.withLocale(Locale.GERMANY);
或:


输出保持不变。

根据DateTimeFormatter的文档,“如果[withZone]被覆盖,则在格式化之前,日期时间值将使用请求的ZoneId转换为ZonedDateTime。在解析期间,在返回值之前应用ZoneId”。因此,我认为解析过程会创建一个美国本地时间,然后在格式化过程中将区域重新划分为UTC。@daniu我最初的想法与您相同,但现在我认为它与区域ID无关。即使我创建了一个没有区域的格式化程序(
DateTimeFormatter.ofPattern(“YYYY ww”)
),并使用它格式化
LocalDate
(没有时区信息),每个区域设置的输出也会发生变化。week字段
Y
w
的行为似乎确实是特定于区域设置的,而不考虑时区。谢谢,这正是我要找的!不过有一点小小的改进:使用
.appendLiteral('-')
而不是
.appendPattern(“-”
),并使用
.appendValue(WeekFields.ISO.weekBasedYear(),4)
指定年和周部分的宽度。appendValue(WeekFields.ISO.weekKofWeekBaseDyear(),2)
@AdamMichalik不客气!事实上,我忘了田地的宽度。在这种情况下,使用
appendLiteral
更加清晰。我已经更新了答案,谢谢!