“不知今夕是何年”的周基年解法 | 得物技术

极客远征
• 阅读 250

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标准的周定义:

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

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

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

这一周算上一年还是下一年,取决于这一周的大多数日期(4天以上)在哪一年。算在前一年,就是前一年的最后一周;算在后一年就是后一年的第一周。
“不知今夕是何年”的周基年解法 | 得物技术

周基年的定义

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

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

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

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

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

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

在Java中,java.time.LocalDate类和java.time.temporal.WeekFields类提供了方便的方法来处理ISO-8601标准的周基年。通过使用这些类,可以轻松地获取指定日期所在的周基年和周数,并进行相关的日期和时间计算。
“不知今夕是何年”的周基年解法 | 得物技术
所以当需要用到某年某周的场景,必须用周基年+周,否则迟早都是雷。最后贴一个jdk8的源代码实现,细细品读。
“不知今夕是何年”的周基年解法 | 得物技术

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

*文/摇浪

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

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

点赞
收藏
评论区
推荐文章
blmius blmius
4年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
美凌格栋栋酱 美凌格栋栋酱
7个月前
Oracle 分组与拼接字符串同时使用
SELECTT.,ROWNUMIDFROM(SELECTT.EMPLID,T.NAME,T.BU,T.REALDEPART,T.FORMATDATE,SUM(T.S0)S0,MAX(UPDATETIME)CREATETIME,LISTAGG(TOCHAR(
Wesley13 Wesley13
3年前
MySQL部分从库上面因为大量的临时表tmp_table造成慢查询
背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为
Peter20 Peter20
4年前
mysql中like用法
like的通配符有两种%(百分号):代表零个、一个或者多个字符。\(下划线):代表一个数字或者字符。1\.name以"李"开头wherenamelike'李%'2\.name中包含"云",“云”可以在任何位置wherenamelike'%云%'3\.第二个和第三个字符是0的值wheresalarylike'\00%'4\
Wesley13 Wesley13
3年前
FLV文件格式
1.        FLV文件对齐方式FLV文件以大端对齐方式存放多字节整型。如存放数字无符号16位的数字300(0x012C),那么在FLV文件中存放的顺序是:|0x01|0x2C|。如果是无符号32位数字300(0x0000012C),那么在FLV文件中的存放顺序是:|0x00|0x00|0x00|0x01|0x2C。2.  
Wesley13 Wesley13
3年前
mysql中时间比较的实现
MySql中时间比较的实现unix\_timestamp()unix\_timestamp函数可以接受一个参数,也可以不使用参数。它的返回值是一个无符号的整数。不使用参数,它返回自1970年1月1日0时0分0秒到现在所经过的秒数,如果使用参数,参数的类型为时间类型或者时间类型的字符串表示,则是从1970010100:00:0
Wesley13 Wesley13
3年前
mysql设置时区
mysql设置时区mysql\_query("SETtime\_zone'8:00'")ordie('时区设置失败,请联系管理员!');中国在东8区所以加8方法二:selectcount(user\_id)asdevice,CONVERT\_TZ(FROM\_UNIXTIME(reg\_time),'08:00','0
Wesley13 Wesley13
3年前
PHP创建多级树型结构
<!lang:php<?php$areaarray(array('id'1,'pid'0,'name''中国'),array('id'5,'pid'0,'name''美国'),array('id'2,'pid'1,'name''吉林'),array('id'4,'pid'2,'n
Easter79 Easter79
3年前
SpringBoot整合Redis乱码原因及解决方案
问题描述:springboot使用springdataredis存储数据时乱码rediskey/value出现\\xAC\\xED\\x00\\x05t\\x00\\x05问题分析:查看RedisTemplate类!(https://oscimg.oschina.net/oscnet/0a85565fa
Wesley13 Wesley13
3年前
Java日期时间API系列36
  十二时辰,古代劳动人民把一昼夜划分成十二个时段,每一个时段叫一个时辰。二十四小时和十二时辰对照表:时辰时间24时制子时深夜11:00凌晨01:0023:0001:00丑时上午01:00上午03:0001:0003:00寅时上午03:00上午0