InfoQ 推荐 ( ) • 2024-04-09 13:17

2024年1月5日,周五,本来是个美好的日子,期待着马上到来的周末。可是下午1点多,接到产品一个问题反馈,经过一番排查,23年7月份上线的功能,对于跨年场景的处理有问题,其核心在于“周的年”获取方式不正确。

举个🌰

(1)前端:页面按照周来选择,例如 2024-12-30,返回给后端的是 Year:2025 -Week:1。

2)后端:根据前端传递的 Year-Week 去DB中查询 数据开发回流的历史离线数据,神奇的事儿就发生了。如下图,数据中 Year字段,就不太正常,2024-12-30,应该是2025年的第一周。

同样的问题,也会出现在1月的开始几天,year字段不太正常。

这是出了什么问题呢?

因为不知今夕是何年啊!!!

ISO-8601标准

ISO-8601是国际标准化组织(ISO)发布的日期和时间表示法的标准,它定义了一种统一的日期和时间格式。ISO-8601标准的目的是提供一种易于理解、易于比较和易于存储的日期和时间表示方法,以便在不同的计算机系统和地区之间进行交互和共享。

周的定义

ISO-8601标准还定义了一种标准的周定义,用于表示周数。该定义基于一年中的周数,以及每周的起始日和结束日。

根据ISO-8601标准的周定义:

一年中的第一个周:一年中的第一个周是包含该年的第一个星期四的周。这意味着该年的第一个周可能会跨越前一年和当前年。每周的起始日:ISO-8601将周的起始日定义为星期一。每周的结束日:ISO-8601将周的结束日定义为星期日。

根据这个定义,一年中的周数从1开始,持续到52或53。如果一年的第一个周跨越前一年和当前年,则第一个周的周数是前一年的最后一周,而不是当前年的第一周。

使用ISO-8601的周定义,可以准确地表示和计算一年中的周数。这种定义方式确保了在不同的计算机系统和地区之间,对于特定的日期,可以一致地确定所在的周数。

这一周算上一年还是下一年,取决于这一周的大多数日期(4天以上)在哪一年。算在前一年,就是前一年的最后一周;算在后一年就是后一年的第一周。

周基年的定义

在ISO-8601标准中,对周的年定义是一种与常规年份定义略有不同的方式。它被称为周基年(Week-based Year)。

根据ISO-8601标准的周基年定义:

一年中的第一个周:一年中的第一个周是包含该年的第一个星期四的周。这意味着该年的第一个周可能会跨越前一年和当前年。每周的起始日:ISO-8601将周的起始日定义为星期一。每周的结束日:ISO-8601将周的结束日定义为星期日。

根据这个定义,一年中的周数从1开始,持续到52或53。如果一年的第一个周跨越前一年和当前年,则第一个周的周数是前一年的最后一周,而不是当前年的第一周。

周基年的定义方式使得在计算和表示特定日期所在的周数时更加准确和统一。它确保了在不同的计算机系统和地区之间,对于特定日期所在的周数能够一致地确定。

简单说,当计算一个日期x是某年的某周,不能直接用常见的getYear,也就是不能用自然年,要用周基年。

在Java中,java.time.LocalDate类和java.time.temporal.WeekFields类提供了方便的方法来处理ISO-8601标准的周基年。通过使用这些类,可以轻松地获取指定日期所在的周基年和周数,并进行相关的日期和时间计算。

所以当需要用到某年某周的场景,必须用周基年+周,否则迟早都是雷。最后贴一个jdk8的源代码实现,细细品读。

从“周基年”这个小场景,可以发现编程基础的扎实与否多么重要,很多同学认为八股文没有价值,恰恰就是这种坚实的基础保证下,才能够让我们的业务系统运行顺畅无问题。

 *文/摇浪 

本文属得物技术原创,更多精彩文章请看:得物技术官网"

未经得物技术许可严禁转载,否则依法追究法律责任!