我有一个在Linux上运行的shell脚本,并使用此调用以YYYY-MM-DD
格式获取昨天的日期:
date -d "1 day ago" '+%Y-%m-%d'
它大部分时间都可以使用,但是当脚本在昨天上午2013-03-11 0:35 CDT
运行时,它返回"2013-03-09"
而不是"2013-03-10"
。
据推测,夏令时(昨天开始)是罪魁祸首。我猜测实施"1 day ago"
的方式是在2013-03-11 0:35 CDT
2013-03-09 23:35 CST
之前24小时减去24小时,这导致了"2013-03-09"
的结果。
那么在Linux上使用bash获取昨天日期的DST安全方法是什么?
答案 0 :(得分:217)
我认为这应该有效,无论你多久经营一次......
date -d "yesterday 13:00" '+%Y-%m-%d'
答案 1 :(得分:45)
Mac OSX下的Bash略有不同。
昨天
echo `date -v-1d +%F`
上周
echo `date -v-1w +%F`
答案 2 :(得分:11)
这也应该有效,但可能太多了:
date -d @$(( $(date +"%s") - 86400)) +"%Y-%m-%d"
答案 3 :(得分:4)
如果您确定该脚本在一天的头几个小时内运行,您只需执行
即可 date -d "12 hours ago" '+%Y-%m-%d'
顺便说一句,如果脚本每天都在00:35运行(通过crontab?),你应该问问自己如果DST的变化在那个小时内会发生什么变化;脚本无法运行,或在某些情况下运行两次。但是,cron
的现代实施在这方面是quite clever。
答案 4 :(得分:3)
此处的解决方案也适用于Solaris和AIX。
操作时区可以在几个小时内更改时钟。 由于夏令时,24小时前可以是今天或前天。
你确定昨天是20或30小时前。哪一个?好吧,最近的一个不是今天。
echo -e "$(TZ=GMT+30 date +%Y-%m-%d)\n$(TZ=GMT+20 date +%Y-%m-%d)" | grep -v $(date +%Y-%m-%d) | tail -1
bash需要echo命令中使用的-e参数,但不能与ksh一起使用。 在ksh中,您可以使用不带-e标志的相同命令。
当您的脚本将在不同的环境中使用时,您可以使用#!/ bin / ksh或#!/ bin / bash启动脚本。你也可以用换行符替换\ n:
echo "$(TZ=GMT+30 date +%Y-%m-%d)
$(TZ=GMT+20 date +%Y-%m-%d)" | grep -v $(date +%Y-%m-%d) | tail -1
答案 5 :(得分:2)
你可以使用
date -d "30 days ago" +"%d/%m/%Y"
从30天前获取日期,类似地,您可以用x天数替换30
答案 6 :(得分:2)
date -d "yesterday" '+%Y-%m-%d'
要稍后使用:
date=$(date -d "yesterday" '+%Y-%m-%d')
答案 7 :(得分:1)
并使用fork to date
命令隐含延迟,使用内置的 pure bash 有一种简单有效的方法:
printf -v tznow '%(%z %s)T' -1
TZ=${tznow% *} printf -v yesterday '%(%Y-%m-%d)T' $(( ${tznow#* } - 86400 ))
echo $yesterday
与必须 叉 插入date
相比,这对系统更友好得多。
从bash V> = 5.0 开始,有一个新变量$EPOCHSECONDS
printf -v tz '%(%z)T' -1
TZ=$tz printf -v yesterday '%(%Y-%m-%d)T' $(( EPOCHSECONDS - 86400 ))
echo $yesterday
答案 8 :(得分:0)
只需使用date
并信任秒:
正如您正确指出的那样,如果您依赖英语时间算术,则会隐藏很多有关基础计算的详细信息。例如。 -d yesterday
和-d 1 day ago
会有不同的行为。
相反,您可以可靠地依赖于自unix时代UTC以来的(精确记录的)秒数,并且bash算法可以获得您想要的时刻:
date -d @$(( $(date +"%s") - 24*3600)) +"%Y-%m-%d"
另一个answer指出了这一点。这种形式在具有不同date
命令行标志的平台上更具可移植性,与语言无关(例如“昨天”与法语语言环境中的“hier”),坦率地说(从长远来看)将更容易记住,因为,你已经知道了。否则,您可能会不断问自己:“它是-d 2 hours ago
还是-d 2 hour ago
?”或者“我想要-d yesterday
或-d 1 day ago
吗?”)。这里唯一棘手的问题是@
。
使用bash武装而已:
只用bash打击,你也可以通过printf内置获得昨天的时间:
%(datefmt)T
causes printf to output the date-time string resulting from using
datefmt as a format string for strftime(3). The corresponding argu‐
ment is an integer representing the number of seconds since the
epoch. Two special argument values may be used: -1 represents the
current time, and -2 represents the time the shell was invoked.
If no argument is specified, conversion behaves as if -1 had
been given.
This is an exception to the usual printf behavior.
所以,
# inner printf gets you the current unix time in seconds
# outer printf spits it out according to the format
printf "%(%Y-%m-%d)T\n" $(( $(printf "%(%s)T" -1) - 24*3600 ))
或者等同于临时变量(外部子shell可选,但保持环境变量干净)。
(
now=$(printf "%(%s)T" -1);
printf "%(%Y-%m-%d)T\n" $((now - 24*3600));
)
注意:尽管manpage声明%()T
格式化程序没有参数会假设默认-1
,但我似乎得到了0(谢谢你,bash手册版本4.3.48) )
答案 9 :(得分:0)
您可以使用:
date -d "yesterday 13:55" '+%Y-%m-%d'
或者bash会检索您想要检索的任何时间。
一个月:
date -d "30 days ago" '+%Y-%m-%d'