一切都取决于你所使用的周数定义。
欧洲(ISO 8601)
这个ISO 8601标准在世界范围内广泛使用:欧盟和大多数其他欧洲国家、大多数亚洲和大洋洲国家。
ISO 8601标准规定如下:
- 一周有7天
- 一周的第一天是星期一
- 第一周是包含星期四的年份中的第一周。这意味着它是1月份拥有4天或更多天的第一周。
按照这个定义,可以有第53周。这种情况发生在1月1日是星期五时(例如2016-01-01、2010-01-01)。或者,如果前一年是闰年,也会出现第53周。(例如2005-01-01)
December 2015 January 2016
Mo Tu We Th Fr Sa Su CW Mo Tu We Th Fr Sa Su CW
1 2 3 4 5 6 49 1 2 3 53
7 8 9 10 11 12 13 50 4 5 6 7 8 9 10 01
14 15 16 17 18 19 20 51 11 12 13 14 15 16 17 02
21 22 23 24 25 26 27 52 18 19 20 21 22 23 24 03
28 29 30 31 53 25 26 27 28 29 30 31 04
function week_range() {
local _u _F _V
_u="$(date -d "$1-01-01" "+%u")"
_F="$(date -d "$1-01-01 + $(( (8 - _u) % 7)) days" "+%F")"
_V="$(date -d "$_F" "+%V")"
printf -- "%s-%s\n" "$(date -d "$_F + $(( 7*($2 - _V) )) days" "+%F")" \
"$(date -d "$_F + $(( 7*($2 - _V) + 6 )) days" "+%F")"
}
$ week_range 2016 1; done
2016-01-04 - 2016-01-10
$ week_range 2020 1; done
2019-12-30 - 2020-01-05 << week one starts in the previous year
$ week_range 2020 20
2020-05-11 - 2020-05-17
美国或伊斯兰教(非ISO 8601)
并非所有国家都使用ISO 8601系统。他们采用了一种更为绝对的方法。
美国系统在加拿大、美国、新西兰、印度、日本等地使用,
伊斯兰教系统通常在中东使用。
两个系统非常相似。
美国:
- 一周有7天
- 一周的第一天是星期日
- 第一周从1月1日开始
根据这个定义,一年的开始和结束可能会出现部分周。因此,一年的第一周和最后一周可能不包含所有工作日。
December 2015 January 2016
Su Mo Tu We Th Fr Sa CW Su Mo Tu We Th Fr Sa CW
1 2 3 4 5 49 1 2 01
6 7 8 9 10 11 12 50 3 4 5 6 7 8 9 02
13 14 15 16 17 18 19 51 10 11 12 13 14 15 16 03
20 21 22 23 24 25 26 52 17 18 19 20 21 22 23 04
27 28 29 30 31 53 24 25 26 27 28 29 30 05
31 06
function week_range() {
local _w _F _V _d1 _d2
_w="$(date -d "$1-01-01" "+%w")"
(( _w = _w + 1 ))
_F="$(date -d "$1-01-01 + $(( (8 - _w) % 7)) days" "+%F")"
[[ "$_F" == "$1-01-01" ]] && _V=1 || _V=2
_d1="$(date -d "$_F + $(( 7*($2 - _V) )) days" "+%F")"
_d2="$(date -d "$_F + $(( 7*($2 - _V) + 6 )) days" "+%F")"
[[ "$_d1" < "$1-01-01" ]] && _d1="$1-01-01"
[[ "$_d2" > "$1-12-31" ]] && _d2="$1-12-31"
[[ "$_d1" > "$1-12-31" ]] && echo "invalid week number" > /dev/stderr && return
printf -- "%s - %s\n" \
"$(date -d "$_d1" "+%m/%d/%Y")" \
"$(date -d "$_d2" "+%m/%d/%Y")"
}
$ week_range 2015 53
12/27/2015 - 12/31/2015
$ week_range 2016 1
01/01/2016 - 01/02/2016
$ week_range 2020 20
05/10/2020 - 05/16/2020
伊斯兰教:
- 一周有7天
- 一周的第一天是星期六
- 第一周从1月1日开始
根据此定义,年初和年末可能存在不完整的一周。因此,一年中的第一周和最后一周可能不包含所有工作日。
December 2015 January 2016
Sa Su Mo Tu We Th Fr CW Sa Su Mo Tu We Th Fr CW
1 2 3 4 49 1 01
5 6 7 8 9 10 11 50 2 3 4 5 6 7 8 02
12 13 14 15 16 17 18 51 9 10 11 12 13 14 15 03
19 20 21 22 23 24 25 52 16 17 18 19 20 21 22 04
26 27 28 29 30 31 53 23 24 25 26 27 28 29 05
30 31 06
function week_range() {
local _w _F _V _d1 _d2
_w="$(date -d "$1-01-01" "+%w")"
(( _w = (_w + 8) % 7 + 1 ))
_F="$(date -d "$1-01-01 + $(( (8 - _w) % 7)) days" "+%F")"
[[ "$_F" == "$1-01-01" ]] && _V=1 || _V=2
_d1="$(date -d "$_F + $(( 7*($2 - _V) )) days" "+%F")"
_d2="$(date -d "$_F + $(( 7*($2 - _V) + 6 )) days" "+%F")"
[[ "$_d1" < "$1-01-01" ]] && _d1="$1-01-01"
[[ "$_d2" > "$1-12-31" ]] && _d2="$1-12-31"
[[ "$_d1" > "$1-12-31" ]] && echo "invalid week number" > /dev/stderr && return
printf -- "%s - %s\n" "${_d1//-//}" "${_d2//-//}"
}
$ week_range 2015 53
2015/12/26 - 2015/12/31
$ week_range 2016 1
2016/01/01 - 2016/01/01
$ week_range 2020 20
2020/05/09 - 2020/05/15
注意:还有其他定义周数的方法,不过方法原理是一样的。
weekof 1 2019
得到了错误的周数。这个算法没有考虑到 ISO 格式中的第一周是指包含星期四的第一周。这意味着一年的第一周的星期一可能在前一年的十二月份。 - kvantourdate +%W
。你可以尝试:date --date="2020-05-17 01:00:00" +%W
输出19
,而date --date="2020-05-18 01:00:00" +%W
则输出20
。 - pynexj%W - 一年中的周数,以星期一作为一周的第一天(00..53)
。也就是说,每周都会从星期一开始,就像我的函数输出一样。 - pynexj