我有从大日志文件中提取的周数列表,它们是使用语法提取的:
$ date --date="Wed Mar 20 10:19:56 2012" +%W;
12
我想创建一个简单的bash函数,可以将这些周数转换为日期范围。我认为函数应该接受2个参数:$ number和$ year,例如:
$ week() { ......... }
$ number=12; year=2012
$ week $number $year
"Mon Mar 19 2012" - "Sun Mar 25 2012"
答案 0 :(得分:10)
使用GNU date
:
$ cat weekof.sh
function weekof()
{
local week=$1 year=$2
local week_num_of_Jan_1 week_day_of_Jan_1
local first_Mon
local date_fmt="+%a %b %d %Y"
local mon sun
week_num_of_Jan_1=$(date -d $year-01-01 +%W)
week_day_of_Jan_1=$(date -d $year-01-01 +%u)
if ((week_num_of_Jan_1)); then
first_Mon=$year-01-01
else
first_Mon=$year-01-$((01 + (7 - week_day_of_Jan_1 + 1) ))
fi
mon=$(date -d "$first_Mon +$((week - 1)) week" "$date_fmt")
sun=$(date -d "$first_Mon +$((week - 1)) week + 6 day" "$date_fmt")
echo "\"$mon\" - \"$sun\""
}
weekof $1 $2
$ bash weekof.sh 12 2012
"Mon Mar 19 2012" - "Sun Mar 25 2012"
$ bash weekof.sh 1 2018
"Mon Jan 01 2018" - "Sun Jan 07 2018"
$
答案 1 :(得分:3)
星期一是一周的第一天,ISO week numbers:
function week2date () {
local year=$1
local week=$2
local dayofweek=$3
date -d "$year-01-01 +$(( $week * 7 + 1 - $(date -d "$year-01-04" +%w ) - 3 )) days -2 days + $dayofweek days" +"%Y-%m-%d"
}
week2date 2017 35 1
week2date 2017 35 7
输出:
2017-08-28
2017-09-03
答案 2 :(得分:1)
如果一周的开始是星期日,您可以使用这个版本的weekof:
function weekof()
{
local week=$1 year=$2
local week_num_of_Jan_1 week_day_of_Jan_1
local first_Sun
local date_fmt="+%Y-%m-%d"
local sun sat
week_num_of_Jan_1=$(date -d $year-01-01 +%U)
week_day_of_Jan_1=$(date -d $year-01-01 +%u)
if ((week_num_of_Jan_1)); then
first_Sun=$year-01-01
else
first_Sun=$year-01-$((01 + (7 - week_day_of_Jan_1) ))
fi
sun=$(date -d "$first_Sun +$((week - 1)) week" "$date_fmt")
sat=$(date -d "$first_Sun +$((week - 1)) week + 6 day" "$date_fmt")
echo "$sun $sat"
}
答案 3 :(得分:1)
一切取决于您所定义的周数 也用过。
此ISO 8601 standard在世界范围内得到广泛使用:欧盟和其他大多数国家 欧洲国家,亚洲大部分地区和大洋洲
ISO 8601标准规定以下内容:
使用此定义,可能有第53周。这些发生在1月1日是 星期五(例如2016年1月1日,2010年1月1日)。或者,如果前一年是 年,也是星期六。 (例如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
# dow Jan 01 (Mon 01 ... Sun 07)
_u="$(date -d "$1-01-01" "+%u")"
# First Monday
_F="$(date -d "$1-01-01 + $(( (8 - _u) % 7)) days" "+%F")"
# Week number of first Monday
_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系统。他们使用更绝对的方法。 美国系统用于加拿大,美国,新西兰,印度,日本,... 伊斯兰系统通常在中东使用。 两种系统非常相似。
使用此定义,可以在 一年的开始和结束。因此,第一周和最后一周 年份不能包含所有工作日。
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
# dow Jan 01 (Sun 01 ... Sat 07)
_w="$(date -d "$1-01-01" "+%w")"
(( _w = _w + 1 ))
# First Saturday
_F="$(date -d "$1-01-01 + $(( (8 - _w) % 7)) days" "+%F")"
# Week number of first Sunday
[[ "$_F" == "$1-01-01" ]] && _V=1 || _V=2
# Start and end
_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
使用此定义,可以在 一年的开始和结束。因此,第一周和最后一周 年份不能包含所有工作日。
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
# dow Jan 01 (Sat 01 ... Fri 07)
_w="$(date -d "$1-01-01" "+%w")"
(( _w = (_w + 8) % 7 + 1 ))
# First Saturday
_F="$(date -d "$1-01-01 + $(( (8 - _w) % 7)) days" "+%F")"
# Week number of first Saturday
[[ "$_F" == "$1-01-01" ]] && _V=1 || _V=2
# Start and end
_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
注意:还有其他定义周数的方法。但是,方法保持不变。
答案 4 :(得分:0)
如果有人需要它:我发现了更短的方式(不确定是否更容易):
function weekof() {
local year=$2
local week=`echo $1 | sed 's/^0*//'` # Fixes random bug
local dateFormat="+%a %b %d %Y"
# Offset is the day of week, so we can calculate back to monday
local offset="`date -d "$year/01/01 +$((week - 1)) week" "+%u"`"
echo -n "`date -d "$year/01/01 +$((week - 1)) week +$((1 - $offset)) day" "$dateFormat"`" # Monday
echo -n " - "
echo "`date -d "$year/01/01 +$((week - 1)) week +$((7 - $offset)) day" "$dateFormat"`" # Sunday }
我参加了一年中的第一天并且前进了n周,以便在正确的一周内到达某个地方。 然后我把我的工作日带回去/转发到星期一和星期天。