我想要给定日期之后下一个星期六的日期。例如,对于$date1="30-AUG-2015"
,我想要结果 05-SEP-2015。
我已尝试以下所有命令但没有成功:
samba@samba:~$ date1="30-AUG-2015"
samba@samba:~$ date2=$(date --date='"$date1" +next Saturday')
date: invalid date ‘"$date1" +next Saturday’
samba@samba:~$ date1="30-AUG-2015"
samba@samba:~$ date2=$(date --date1='next Saturday')
date: unrecognized option '--date1=next Saturday'
Try 'date --help' for more information.
samba@samba:~$ date1="30-AUG-2015"
samba@samba:~$ date -d "$date1 next saturday"
Sun Aug 30 00:00:00 IST 2015
samba@samba:~$ $date1 -d "next saturday"
30-AUG-2015: command not found
答案1
我强烈推荐日期工具对于这样的事情。
在带有 EPEL 的 Fedora Linux 21+ 或 CentOS/RHEL 上:
dnf install dateutils
(yum
而不是旧版 RHEL 上的 DNF。)
在基于 Debian 的系统上,也可以调用该包,dateutils
但命令以 为前缀,dateutils.
以消除其中一些命令与不相关包中具有相同名称的命令的歧义(因此,替换dateround
为dateutils.dround
下面的命令)。
然后,只需执行以下操作:
dateround today sunday
您可以使用“今天”或替换为实际日期:
$ dateround 2015-08-30 saturday
2015-09-05
如果您需要输入特定格式的日期,例如 2015 年 8 月 30 日,您可以使用-i
或--input-format
选项,例如:
$ dateround -i '%d-%b-%Y' 30-AUG-2015 saturday
2015-09-05
从名称“dateround”中并不能立即清楚地看出,但是这个命令四舍五入— 也就是说,周一不会回溯至上周日。如果匹配,它还默认返回当前日期 - 例如,如果今天是星期日,dateround today sunday
则会给出今天的日期。如果您希望它始终是未来的日期,请添加该--next
标志。
答案2
和ksh93
:
$ LC_ALL=C ksh93 -c 'printf "%(%c)T\n" "30-Aug-2015 Saturday"'
Sat Sep 5 00:00:00 2015
请注意,如果日期是星期六,那么它将在同一天返回,如果您想要下一个星期六,请执行以下操作:
LC_ALL=C printf "%(%c)T\n" "30-Aug-2015 tomorrow Saturday"
替换%c
为strftime
您想要的规格:
$ LC_ALL=C printf "%(%d-%b-%Y)T\n" "03-Jan-2015 tomorrow saturday"
10-Jan-2015
为此10-JAN-2015
,请将其分配给使用以下命令声明的变量typeset -u
:
typeset -u date=${
LC_ALL=C printf "%(%d-%b-%Y)T\n" "03-Jan-2015 tomorrow saturday"
}
通过 GNU 实现date
:
$ d=03-JAN-2015
$ LC_ALL=C date -d "$d +1 week -$(date -d "$d +1 day" +%w) day" '+%d-%^b-%Y'
10-JAN-2015
答案3
适用于任何一天、一周的单行解决方案,无需循环
MON=1
TUE=2
WED=3
THU=4
FRI=5
SAT=6
SUN=7
echo "Today " && date
echo "Next Monday " && date -d "+ $(( ( (6 + $MON - $(date +%u)) % 7) + 1 )) days"
echo "Next Tuesday " && date -d "+ $(( ( (6 + $TUE - $(date +%u)) % 7) + 1 )) days"
echo "Next Wednesday " && date -d "+ $(( ( (6 + $WED - $(date +%u)) % 7) + 1 )) days"
echo "Next Thursday " && date -d "+ $(( ( (6 + $THU - $(date +%u)) % 7) + 1 )) days"
echo "Next Friday " && date -d "+ $(( ( (6 + $FRI - $(date +%u)) % 7) + 1 )) days"
echo "Next Saturday " && date -d "+ $(( ( (6 + $SAT - $(date +%u)) % 7) + 1 )) days"
echo "Next Sunday " && date -d "+ $(( ( (6 + $SUN - $(date +%u)) % 7) + 1 )) days"
输出
Today
Thu, Nov 12, 2020 10:24:38 PM
Next Monday
Mon, Nov 16, 2020 10:24:39 PM
Next Tuesday
Tue, Nov 17, 2020 10:24:40 PM
Next Wednesday
Wed, Nov 18, 2020 10:24:40 PM
Next Thursday
Thu, Nov 19, 2020 10:24:41 PM
Next Friday
Fri, Nov 13, 2020 10:24:42 PM
Next Saturday
Sat, Nov 14, 2020 10:24:42 PM
Next Sunday
Sun, Nov 15, 2020 10:24:43 PM
解释
想法是计算直到一周的第二天的天数并将这些数字添加到当前日期。我们以星期六为例。
- 周一加 5 天
- ...
- 周五加 1 天
- 周六加 7 天
- 周日加 6 天
因此,算法的第一次迭代看起来像是取当前星期几date +%u
,取mod 7
并相加,1
因为模是从零开始的:
( $(date +%u) % 7) + 1
但是,它没有考虑到我们添加的天数顺序是降序的(5,4,3,2,1,7,6)。为了适应这一点,我们必须从 中减去当前星期几7
,然后取模并添加1
:
( (7 - $(date +%u)) % 7) + 1
这样我们就得到了周一 ( 7 == 6 + $MON
) 的工作示例。为了让它搜索任意一周的一天,我们应该像这样重写它
( (6 + <DAY> - $(date +%u)) % 7) + 1
其中<DAY>
应该是上面的任何变量 ( $MON
... $SUN
)
针对 Alpine Linux 的修改
Alpine Linux 不支持-d "+ 3 days"
,因此您要么安装coreutils
( apk add coreutils
) 使其工作,要么自己进行天算术。
date -d "@$(($(date +%s) + 86400 * $(( ( (6 + $SAT - $(date +%u)) % 7) + 1 )) ))"
解释
$(date +%s)
输出自...以来的秒数!你知道!86400
是每天的秒数,date -d "@<number_of_seconds>"
从修改的秒数恢复日期。
针对 Mac 操作系统的修改
它的工作方式类似于“Alpine Linux 的修改”,除了在 MacOS 上,而不是date -d "@<number_of_seconds>"
你写date -r "<number_of_seconds>"
,所以
date -r "$(($(date +%s) + 86400 * $(( ( (6 + $SAT - $(date +%u)) % 7) + 1 )) ))"
更多详情请参阅上面的“Alpine Linux 的修改/说明”。
答案4
一个更简单的解决方案是:
$ adate1="30-AUG-2015"
$ faketime "$adate1" date -d 'saturday' +'%d-%b-%Y'
05-Sep-2015
当然,你需要安装faketime。