新年遇到的日期 Bug

新的一年到来了,遇到一个日期相关bug,这个 bug 在我的代码里只会在新年的第一周才会被触发,也算是比较有趣。

在我的代码里面,我有一个下面这样的函数来计算并储存一个日期所属的「年份」以及「第几周」:

func getYearAndWeek(at date: Date) -> (Int, Int) {
	let monday = date.currentWeekMonday
	let year = monday.component(.year)!
	let weekOfYear = Calendar.iso8601.component(.weekOfYear, from: monday)
}

问题出在第二行,计算年份的时候我使用的是自然年,但是计算 .weekOfYear 时候使用的年份是不一样的。

譬如,输入日期是 2019年12月30日,使用上面的代码,我们会得到 year = 2019,week = 1,因为使用的是自然年。

下面的代码才是正确的做法,这时候我们会得到 year = 2020,week = 1,这才是正确的。

func getYearAndWeek(at date: Date) -> (Int, Int) {
	let monday = date.currentWeekMonday
        let components = Calendar.iso8601.dateComponents([.weekOfYear, .yearForWeekOfYear], from: monday)
        let yearForWeekOfYear = components.yearForWeekOfYear!
        let weekOfYear = components.weekOfYear!
}

关于这一点,其实 ISO 8601 日期系统有明确的定义(wikipedia):

The ISO 8601 definition for week 01 is the week with the Gregorian year’s first Thursday in it

如下图所示,由于2020年1月1日是星期三,属于一个星期前半部分,所以从12月30号到1月5号这一周都属于 week 01。

image

所以,新的一年这个bug再次提醒了我,如果一个需求涉及日期相关的改动,那就把实现时间乘以三吧 :)

Posted 2020-01-02