我需要的是一个脚本(最好是shell),它计算自固定日期以来经过的天数 - 比如2014年8月16日。
我认为可以使用 date +%j
命令,自8月16日起减去229是今年的229天。 然而,1月1日这个剧本将变得毫无用处......
我完全迷失了,因为我不知道脚本编写的第一件事,但我认为有人可能会帮忙。
答案 0 :(得分:1)
如果你有GNU date
且你的固定日期是2014-08-16,你可以使用:
$ old=$(date +'%s' -d '2014-08-16')
$ new=$(date +'%s')
$ echo $(( ($new - $old) / 86400 ))
9
$
Qualcuno在comment中指出并非所有日子都有86400秒。
这是正确的;大多数日子有86400秒,但有些有90000秒,有些有82800秒(当你因为夏令时和标准时间之间的切换而获得或减少一小时)。漫长的日子不会引起问题;短的那些。我更喜欢提供日期(以天为单位)'计算而不是时间(以秒为单位)'计算这些,但我不知道这样做的标准Unix实用程序。
但是,我们可以强制date
来处理它,方法是确保较早的日期与午夜一起作为(隐含)时间,而较晚的日期在午夜之后至少一小时使用明确的时间。除了极少数例外情况(例如几年前一个国家跨越国际日期变更线 - 而且我不会尝试处理它!),最多只有一个小时的净时区切换两个约会。假设两个日期相隔三年。中间两年,从标准时间切换到切换,净结果为零;最重要的是一个开关。这会导致命令看起来像这样:
#!/bin/bash
#
# Calculate days between two dates using GNU date command
# Allow for time zone switches
arg0=$(basename "$0" .sh)
DATE=/usr/gnu/bin/date
case $# in
1) old="$1"; new=$($DATE +"%Y-%m-%d");;
2) old="$1"; new="$2";;
*) echo "Usage: $arg0 old [new]" >&2; exit 1;;
esac
case "$old" in
[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]) : OK;;
*) echo "$arg0: $old does not match YYYY-mm-dd" >&2; exit 1;;
esac
case "$new" in
[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]) : OK;;
*) echo "$arg0: $new does not match YYYY-mm-dd" >&2; exit 1;;
esac
if [[ "$old" > "$new" ]]
then t="$old"; old="$new"; new="$t"
fi
# Faulty
old_secs=$($DATE +'%s' -d "$old")
new_secs=$($DATE +'%s' -d "$new")
echo $(( ($new_secs - $old_secs) / 86400 ))
# Safe
old_secs=$($DATE +'%s' -d "$old")
new_secs=$($DATE +'%s' -d "$new 12:00:00")
echo $(( ($new_secs - $old_secs) / 86400 ))
示例输出(显示差异):
$ bash delta-days.sh 2014-03-01 2014-03-31
29
30
$ bash delta-days.sh 2000-03-01 2014-03-31
5142
5143
$ bash delta-days.sh 2014-03-01 2000-03-31
5083
5083
$
答案 1 :(得分:0)
在bash shell中:
then=$(date -j -f "%Y-%m-%d" "2014-8-16" +%s)
now=$(date +%s)
echo $(($now/86400-$then/86400))
在date
命令中,选项j表示您要显示指定的日期(而不是尝试将系统日期设置为它);选项f是输入日期的格式,“+”选项是输出日期的格式。格式%s
是当前纪元的秒数,即自1970/1/1 00:00 UTC以来。
答案 2 :(得分:0)
如果您只使用年份和年份数字,则可以使用此公式计算日序列号:
number = (year-1)/4*(4*365+1) + (year-1)%4*365 + day # integer arithmetic
在像这样的shell脚本中使用(与去年相比):
$ year=$(date +%Y)
$ day=$(date +%j)
$ now=$((($year-1)/4*1461+($year-1)%4*365+day))
$ then=$(((2013-1)/4*1461+(2013-1)%4*365+230))
$ echo $then $now
735113 735485
$ echo $(($now-$then))
372
这个公式只知道常见的闰年(每四年一次),而不是像1900年,2100年,2200年这样没有飞跃的年份。也就是说,它可能是2100年开始的休假日。
答案 3 :(得分:0)
对于perl(从CPAN安装),有一个非常完整的DateTime模块,可以满足您的目的:
perl -MDateTime -E '
$base = DateTime->new(year=>2014, month=>8, day=>16);
$now = DateTime->today;
$next_year = DateTime->new(year=>2015, month=>8, day=>16);
say $base->delta_days($now)->in_units("days");
say $base->delta_days($next_year)->in_units("days");
'
10
365