ISO WEEK NUM 实现
项目要求实现 ISOWEEKNUM
函数, 网上查找资料了解到是一种周数计算方式, 称为 ISO标准周
. Excel里面就有直接提供此函数.
在一些博客和GitHub上面找到的几个实现, 经过测试似乎都并不正确. 跟Excel计算出来的结果并不一样.
无奈之下只好放弃了复制粘贴大法, 自己去了解了一下ISOWEEKNUM的定义, 并做出了以下实现:
/**
* 计算某日期在全年中的周数, 结果要符合ISO标准周的定义
*
* @param {Date} date 要计算的日期
* @returns {number} 周数
*/
var ISOWEEKNUM = function (date) {
var currentDate = new Date(date);
var firstOfCurrentYear = setMonthAndDate(date, 0, 1);
var isoWeekNumber = 0;
// 判断当前年的第一天与date对象所指的日期的关系
if ((firstOfCurrentYear.getDay() > 4)
// 这里是两个 `与` 符号, 不知道为什么被转成了这样
&& (currentDate.getMonth() === 0)
&& (currentDate.getDate() - firstOfCurrentYear.getDate()) < 3) {
firstOfCurrentYear = new Date(firstOfCurrentYear
.setFullYear(firstOfCurrentYear.getFullYear() - 1));
}
// 循环叠加, 计算周数
while (firstOfCurrentYear.getTime() <= currentDate.getTime()) {
firstOfCurrentYear = addDate(firstOfCurrentYear, 7);
++isoWeekNumber;
}
return isoWeekNumber;
};
/**
* 设置月份&日期
*
* @functional
* @param {Date} originDate 原日期
* @param {number} monthNumber 设置的月份
* @param {number} dateNumber 设置的日期(月中的日期)
* @returns {Date} 新的日期
*/
var setMonthAndDate = function (originDate, monthNumber, dateNumber) {
var _ = new Date(new Date(originDate).setMonth(monthNumber));
return new Date(_.setDate(dateNumber));
};
/**
* 基于 originDate 添加天数并返回新的 Date
*
* @functional
* @param {Date} originDate 原日期
* @param {number} incNumber 添加的日期数
* @returns {Date} 新的日期
*/
var addDate = function (originDate, incNumber) {
return new Date(new Date(originDate).setDate(originDate.getDate() + incNumber));
};
你可以直接粘贴这段代码到浏览器的控制台执行(注意第15和16行的那两个&&
实体符号), 下面是一些日期的测试结果:
// 2016年1月1日
ISOWEEKNUM(new Date(2016, 0, 1))
// <· 53
// 2016年1月3日
ISOWEEKNUM(new Date(2016, 0, 3))
// <· 53
// 2016年1月4日
ISOWEEKNUM(new Date(2016, 0, 4))
// <· 1
// 2016年6月1日
ISOWEEKNUM(new Date(2016, 5, 1))
// <· 22
// 2018年1月1日
ISOWEEKNUM(new Date(2018, 0, 1))
// <· 1
// 2018年3月7日
ISOWEEKNUM(new Date(2016, 2, 7))
// <· 10