从给定日期获取下周六的日期

从给定日期获取下周六的日期

我想要给定日期之后下一个星期六的日期。例如,对于$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.以消除其中一些命令与不相关包中具有相同名称的命令的歧义(因此,替换daterounddateutils.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"

替换%cstrftime您想要的规格:

$ 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。

相关内容