召唤小埋
    0%

    一键穿越到2020-12-31

    什么?一键穿越到2020-12-31?什么啊。今天明明才1月2号。刚刚享受过元旦的快乐,你就告诉我又到年底了?

    nonono,实际上是今天我在V站看到了这篇帖子。觉得很有意思。所以拿来分享一下。

    写代码的时候,你常用的时间格式是YYYY-MM-dd,还是yyyy-MM-dd呢?

    可能这些的区别,你曾经在上课的时候听老师提起过。也可能你从来没有注意过他们的区别。但是无论如何,今年已经2020了。你可一定要搞清楚这些的区别!

    我们先来复现一下贴中的BUG:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    @Test
    void TestYearBug() {
    LocalDateTime before2020 = LocalDateTime.of(2019, Month.DECEMBER, 25, 8, 0, 0);
    for (int day = 0; day < 8; day++) {
    String dateFormatToString = before2020.format(DateTimeFormatter.ofPattern("YYYY-MM-dd"));
    System.out.println(dateFormatToString);
    before2020 = before2020.plusDays(1L);
    }
    }

    如果你不认得LocalDateTime和DateTimeFormatter的话,那你真的是Out啦,不要再用Date和SimpleDateFormatter啦。快去了解一下这两个崭新的类吧。

    话归正题,让我们来看看结果是什么:

    😮

    什么鬼啊,为什么2019-12-28下面直接就是2020-12-29了?

    其实这个问题在 Stack OverFlow 上很早就有讨论了。Y returns 2012 while y returns 2011 in SimpleDateFormat.

    我们去Java Doc上翻一翻,很容易就找到答案了:Y是“Week-Based-Year”,而y是“Year”。

    那什么是 “Week-Based-Year”呢,我找到的一篇文章中这样解释:

    Week number according to the ISO-8601 standard, weeks starting on Monday. The first week of the year is the week that contains that year’s first Thursday (=’First 4-day week’). The highest week number in a year is either 52 or 53.

    根据 ISO-8601 标准,一周始于周一,一年的第一周是包含这一年第一个星期四的那一周。因此,2020-01-02,也就是今天,是周四。因此,这周就是2020年第一周。所以作为“Week Year”,YYYY就会把同在本周的2019-….

    写到这里我迷惑了。看看上面的运行结果。如果说因为这周是2020第一周,所以把周一周二的12-30、12-31归于2020年,我理解。但是12-29呢?它是属于上周日啊?

    于是我就去找了其他地方的文章,最后在掘金看到有人说:YYYYweek-based-year,表示:当天所在的周属于的年份,一周从周日开始,周六结束,只要本周跨年,那么这周就算入下一年。所以2019年12月29日那天在这种表述方式下就已经 2020 年了。

    这样说的话就解释了运行结果了。但是我又运行了一下代码:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    @Test
    void TestYearBug() {
    LocalDateTime before2020 = LocalDateTime.of(2019, Month.DECEMBER, 25, 8, 0, 0);
    for (int day = 0; day < 8; day++) {
    String dateFormatToString = before2020.format(DateTimeFormatter.ofPattern("YYYY-MM-dd w e E"));
    System.out.print("dayOfWeek:"+before2020.get(WeekFields.ISO.dayOfWeek())+" ");
    System.out.println(dateFormatToString);
    before2020 = before2020.plusDays(1L);
    }
    }

    运行结果如下:

    🤨

    难道这不是按照ISO-8601来的吗?所以上面我阅读ISO标准的时候才会被迷惑?

    这就留待日后我去找寻答案了。

    附表:All letters ‘A’ to ‘Z’ and ‘a’ to ‘z’ are reserved as pattern letters. The following pattern letters are defined:

      Symbol  Meaning                     Presentation      Examples
      ------  -------                     ------------      -------
       G       era                         text              AD; Anno Domini; A
       u       year                        year              2004; 04
       y       year-of-era                 year              2004; 04
       D       day-of-year                 number            189
       M/L     month-of-year               number/text       7; 07; Jul; July; J
       d       day-of-month                number            10
    
       Q/q     quarter-of-year             number/text       3; 03; Q3; 3rd quarter
       Y       week-based-year             year              1996; 96
       w       week-of-week-based-year     number            27
       W       week-of-month               number            4
       E       day-of-week                 text              Tue; Tuesday; T
       e/c     localized day-of-week       number/text       2; 02; Tue; Tuesday; T
       F       week-of-month               number            3
    
       a       am-pm-of-day                text              PM
       h       clock-hour-of-am-pm (1-12)  number            12
       K       hour-of-am-pm (0-11)        number            0
       k       clock-hour-of-am-pm (1-24)  number            0
    
       H       hour-of-day (0-23)          number            0
       m       minute-of-hour              number            30
       s       second-of-minute            number            55
       S       fraction-of-second          fraction          978
       A       milli-of-day                number            1234
       n       nano-of-second              number            987654321
       N       nano-of-day                 number            1234000000
    
       V       time-zone ID                zone-id           America/Los_Angeles; Z; -08:30
       z       time-zone name              zone-name         Pacific Standard Time; PST
       O       localized zone-offset       offset-O          GMT+8; GMT+08:00; UTC-08:00;
       X       zone-offset 'Z' for zero    offset-X          Z; -08; -0830; -08:30; -083015; -08:30:15;
       x       zone-offset                 offset-x          +0000; -08; -0830; -08:30; -083015; -08:30:15;
       Z       zone-offset                 offset-Z          +0000; -0800; -08:00;
    
       p       pad next                    pad modifier      1
    
       '       escape for text             delimiter
       ''      single quote                literal           '
       [       optional section start
       ]       optional section end
       #       reserved for future use
       {       reserved for future use
       }       reserved for future use
     
    • 创建时间: 2020-01-02 14:12:20
    • 修改时间: 2020-02-13 16:44:11
    • 本文作者: Morty.ROY
    • 本文链接: https://www.royians.cn/2020/01.02.5cb164bd/
    • 版权声明: 本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!