【问题标题】:java.time.format.DateTimeFormatter.withZone - Not Calculating Year Correctly [duplicate]java.time.format.DateTimeFormatter.withZone - 未正确计算年份 [重复]
【发布时间】:2021-05-07 22:35:30
【问题描述】:

当前使用java.time.format.DateTimeFormatter 将瞬间格式化为不同的区域,并且当区域覆盖向后跨越到上一年时,所有日期部分都会更改,但年份除外。例子:

import java.time.OffsetDateTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.time.temporal.TemporalAccessor;

public class Example {

    final static ZoneId NYC = ZoneId.of("America/New_York");
    final static ZoneId CHI = ZoneId.of("America/Chicago");
    
    final static DateTimeFormatter FMT_YEAR = DateTimeFormatter.ofPattern("YYYY");
    final static DateTimeFormatter FMT_YEAR_NYC = FMT_YEAR.withZone(NYC);
    final static DateTimeFormatter FMT_YEAR_CHI = FMT_YEAR.withZone(CHI);

    final static DateTimeFormatter FMT_YEAR_MONTH = DateTimeFormatter.ofPattern("YYYY-MM");
    final static DateTimeFormatter FMT_YEAR_MONTH_NYC = FMT_YEAR_MONTH.withZone(NYC);
    final static DateTimeFormatter FMT_YEAR_MONTH_CHI = FMT_YEAR_MONTH.withZone(CHI);

    final static DateTimeFormatter FMT_YEAR_MONTH_DAY = DateTimeFormatter.ofPattern("YYYY-MM-dd");
    final static DateTimeFormatter FMT_YEAR_MONTH_DAY_NYC = FMT_YEAR_MONTH_DAY.withZone(NYC);
    final static DateTimeFormatter FMT_YEAR_MONTH_DAY_CHI = FMT_YEAR_MONTH_DAY.withZone(CHI);

    public static void main(String[] args) {
        // Starting point at midnight on January 1, 2021
        ZonedDateTime pit = ZonedDateTime.of(2021,1,1,0,0,0,0,NYC);
        System.out.println("ZonedDateTime Constructed :");
        formatAndPrint("Year", pit, FMT_YEAR, FMT_YEAR_NYC, FMT_YEAR_CHI);
        formatAndPrint("YearMonth", pit, FMT_YEAR_MONTH, FMT_YEAR_MONTH_NYC, FMT_YEAR_MONTH_CHI);
        formatAndPrint("YearMonthDay", pit, FMT_YEAR_MONTH_DAY, FMT_YEAR_MONTH_DAY_NYC, FMT_YEAR_MONTH_DAY_CHI);
        
        pit = ZonedDateTime.parse("2021-01-01T00:00:00.000-05:00");
        System.out.println();
        System.out.println("ZonedDateTime Parsed :");
        formatAndPrint("Year", pit, FMT_YEAR, FMT_YEAR_NYC, FMT_YEAR_CHI);
        formatAndPrint("YearMonth", pit, FMT_YEAR_MONTH, FMT_YEAR_MONTH_NYC, FMT_YEAR_MONTH_CHI);
        formatAndPrint("YearMonthDay", pit, FMT_YEAR_MONTH_DAY, FMT_YEAR_MONTH_DAY_NYC, FMT_YEAR_MONTH_DAY_CHI);
        
        OffsetDateTime off = OffsetDateTime.parse("2021-01-01T00:00:00.000-05:00");
        System.out.println();
        System.out.println("OffsetDateTime Parsed :");
        formatAndPrint("Year", off, FMT_YEAR, FMT_YEAR_NYC, FMT_YEAR_CHI);
        formatAndPrint("YearMonth", off, FMT_YEAR_MONTH, FMT_YEAR_MONTH_NYC, FMT_YEAR_MONTH_CHI);
        formatAndPrint("YearMonthDay", off, FMT_YEAR_MONTH_DAY, FMT_YEAR_MONTH_DAY_NYC, FMT_YEAR_MONTH_DAY_CHI);
    }
    
    public static void formatAndPrint(String header, TemporalAccessor pit, 
            DateTimeFormatter fmt, DateTimeFormatter fmt_nyc, DateTimeFormatter fmt_chi){
        System.out.println(header + " - Default: " + fmt.format(pit));
        System.out.println(header + " - NYC: " + fmt_nyc.format(pit));
        System.out.println(header + " - CHI: " + fmt_chi.format(pit));
    }
}

产生:

ZonedDateTime Constructed :
Year - Default: 2021
Year - NYC: 2021
Year - CHI: 2021
YearMonth - Default: 2021-01
YearMonth - NYC: 2021-01
YearMonth - CHI: 2021-12
YearMonthDay - Default: 2021-01-01
YearMonthDay - NYC: 2021-01-01
YearMonthDay - CHI: 2021-12-31

ZonedDateTime Parsed :
Year - Default: 2021
Year - NYC: 2021
Year - CHI: 2021
YearMonth - Default: 2021-01
YearMonth - NYC: 2021-01
YearMonth - CHI: 2021-12
YearMonthDay - Default: 2021-01-01
YearMonthDay - NYC: 2021-01-01
YearMonthDay - CHI: 2021-12-31

OffsetDateTime Parsed :
Year - Default: 2021
Year - NYC: 2021
Year - CHI: 2021
YearMonth - Default: 2021-01
YearMonth - NYC: 2021-01
YearMonth - CHI: 2021-12
YearMonthDay - Default: 2021-01-01
YearMonthDay - NYC: 2021-01-01
YearMonthDay - CHI: 2021-12-31

我认为芝加哥应该在 2020 年代表我的理解/期望是否有误?

运行 JVM 11.0.3+12-LTS

【问题讨论】:

    标签: java


    【解决方案1】:

    YYYY 是基于周的年份。如果你不知道这意味着什么,我会总结一下:“你永远不想要的东西”。

    你想要uuuu。也许是yyyy,但也许是uuuu。见javadoc of DTF。

    【讨论】:

    • 感谢@rzwitserloot。这让我质疑过去 20 年我在 Java 中的工作经历。修复了我的区域问题。
    猜你喜欢
    • 2018-07-18
    • 1970-01-01
    • 2015-06-20
    • 1970-01-01
    • 1970-01-01
    • 2023-03-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多