精确计算指定日期是当年的第几周

1,307 阅读2分钟

如何不借助第三方库(dayjs/momentjs),获取指定日期是当年的第几周?

在网上找了很多,发现大部分都是错的。一个重要的原因就是,他们连“每年的第一周”的定义不没有弄清楚。

根据中华人民共和国国家标准GB/T 7408-2005《数据元和交换格式信息交换日期和时间表示法》中4.3.3.2部分:

即一年中的第一个 日历星期包括该年的第一个星期四,并且日历年的最后一个日历星期就是在下一个日历年的第一个日历星期之前的那个星期,日历星期数是其在该年中的顺序。

这句话的意思就是,每年的第一个星期,应该是包含第一个星期四的那个星期。按照这样的定义,2022年的第一个星期是2022年1月2日-2022年1月8日。

image.png

所以,网上很多都将1月1日作为起止日期开始算,是不准确的。

那么按照这个定义,我的思路是这样的:将每年的第一个星期四作为起始日期,指定日期所在周的星期四作为终止日期,再将两者的差值除以7,即为所求周数。还有一个细节就是跨年问题,指定日期有可能是在上一年的最后一个星期。比如2022年的1月1日,其实属于2021年的最后一周。

  const ONE_DAY_MILSEC = 24 * 3600 * 1000

  const getWeekOfYear = (dateStr) => {
    const dateObj = new Date(dateStr)
    const startOfYear = new Date(dateStr)

    startOfYear.setMonth(0)//1月
    startOfYear.setDate(1)//1日

    let dayOfFirstDate = startOfYear.getDay() //1号是星期几
    let dateOfFirstThursday //所在年份的第一个星期四的日期
    //计算所在年份的第一个星期四
    if(dayOfFirstDate < 5) { //1月1日在星期五之前,则再过(4 - dayOfFirstDate)天是星期四
      dateOfFirstThursday =  startOfYear.getTime() + ONE_DAY_MILSEC  * (4 - dayOfFirstDate)
    }else{//否则顺延一周,再过( 4 - dayOfFirstDate + 7) 天 才是当年的第一个星期四
      dateOfFirstThursday = startOfYear.getTime() + ONE_DAY_MILSEC *  ( 4 - dayOfFirstDate + 7)
    }
    let curThursday = dateObj.getTime() + ONE_DAY_MILSEC * (4 -  dateObj.getDay())  //给定日期所在周的星期四

    let ans = ''
    if(curThursday >= dateOfFirstThursday) {
      const year = startOfYear.getFullYear()
      ans = year + '年 第' + ((curThursday - dateOfFirstThursday) / ONE_DAY_MILSEC / 7 + 1) + '周'
    }else{//指定日期是在上一年的最后一个星期
      let lastDayOfLastYear = startOfYear.getTime() - ONE_DAY_MILSEC
      const year = new Date(lastDayOfLastYear).getFullYear()
      ans = getWeekOfYear(lastDayOfLastYear) 
    }
    return ans
  }

  console.log(getWeekOfYear('2023-01-01'))

以上就是本文的全部内容,水平有限,欢迎指教。