sedationh / blog

Blog space for a user who doesn't want to mess with blogs anymore:)
0 stars 0 forks source link

关于 yyyy 和 YYYY #67

Open sedationh opened 9 months ago

sedationh commented 9 months ago

最近有个图广为流传

image

这个问题本质上是两种对年的定义的差异导致的

yyyy 是比较符合直觉的,在公历上这天在哪一年就是哪一年,如 2023-01-01 -> 2023

但 YYYY 的比较容易混乱,原因在于这天在哪一年是由这天所在周的所在年决定的

  1. week 可能跨年
  2. 不同国家对于 week 的起始天判断不一样

The ISO-8601 definition, where a week starts on Monday and the first week has a minimum of 4 days. The ISO-8601 standard defines a calendar system based on weeks.

image

看代码

    // https://medium.com/@ps.stepniewski/difference-between-yyyy-and-yyyy-java-date-pattern-what-is-week-based-year-aebc14911bc5
    @Test
    public void localePlUsesWeekFieldsIso() {
        // 不同 Locale 可能有不同的一周的开始日,默认情况下,美国 Locale 的一周开始于星期日,而大多数欧洲国家(包括波兰)的一周则是从星期一开始。
        DateTimeFormatter formatterPl = DateTimeFormatter.ofPattern("YYYY-MM-dd ww", Locale.forLanguageTag("pl-PL"));
        assertEquals(LocalDate.of(2021, 12, 30).format(formatterPl), "2021-12-30 52");
        assertEquals(LocalDate.of(2021, 12, 31).format(formatterPl), "2021-12-31 52");
        assertEquals(LocalDate.of(2022, 1, 1).format(formatterPl), "2021-01-01 52");
        assertEquals(LocalDate.of(2022, 1, 2).format(formatterPl), "2021-01-02 52");

        assertEquals(LocalDate.of(2023, 1, 1).format(formatterPl), "2022-01-01 52");
        assertEquals(LocalDate.of(2023, 1, 2).format(formatterPl), "2023-01-02 01");
    }

image

在前端的场景里,JavaScirpt 自身没处理 week-based-year,需要加点操作,如使用 dayjs

https://day.js.org/docs/en/plugin/advanced-format Format Output Description
GGGG 2017 ISO Week Year ( dependent IsoWeek plugin )
const time = "2023-01-01"
const yyyy = dayjs(time).format("DD/MM/yyyy")
const GGGG = dayjs(time).format("DD/MM/GGGG")
const YYYY = dayjs(time).format("DD/MM/YYYY")

console.log({
   yyyy, GGGG, YYYY
})
{
  "yyyy": "01/01/yyyy",
  "YYYY": "01/01/2023",
  "GGGG": "01/01/2022"
}