bash 如何找到两个日期之间的天数差异?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/4946785/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to find the difference in days between two dates?
提问by Tree
A="2002-20-10"
B="2003-22-11"
A="2002-20-10"
B="2003-22-11"
How to find the difference in days between two dates?
如何找到两个日期之间的天数差异?
采纳答案by techHymaner
If you have GNU date
, it allows to print the representation of an arbitrary date (-d
option).
In this case convert the dates to seconds since EPOCH, subtract and divide by 24*3600.
如果你有 GNU date
,它允许打印任意日期的表示(-d
选项)。在这种情况下,将日期转换为自 EPOCH 以来的秒数,减去并除以 24*3600。
Or you need a portable way?
或者你需要一个便携的方式?
回答by techHymaner
The bash way - convert the dates into %y%m%d format and then you can do this straight from the command line:
bash 方式 - 将日期转换为 %y%m%d 格式,然后您可以直接从命令行执行此操作:
echo $(( ($(date --date="031122" +%s) - $(date --date="021020" +%s) )/(60*60*24) ))
回答by Fred Laurent
And in python
在蟒蛇中
$python -c "from datetime import date; print (date(2003,11,22)-date(2002,10,20)).days"
398
回答by evan_b
Watch out! Many of the bash solutions here are broken for date ranges which span the date when daylight savings time begins (where applicable). This is because the $(( math )) construct does a 'floor'/truncation operation on the resulting value, returning only the whole number. Let me illustrate:
小心!此处的许多 bash 解决方案的日期范围都跨越了夏令时开始的日期(如果适用)。这是因为 $(( math )) 构造对结果值执行“地板”/截断操作,仅返回整数。让我举例说明:
DST started March 8th this year in the US, so let's use a date range spanning that:
夏令时于今年 3 月 8 日在美国开始,因此让我们使用跨越以下范围的日期范围:
start_ts=$(date -d "2015-03-05" '+%s')
end_ts=$(date -d "2015-03-11" '+%s')
Let's see what we get with the double parentheses:
让我们看看用双括号得到什么:
echo $(( ( end_ts - start_ts )/(60*60*24) ))
Returns '5'.
返回“5”。
Doing this using 'bc' with more accuracy gives us a different result:
使用 'bc' 更准确地执行此操作会给我们一个不同的结果:
echo "scale=2; ( $end_ts - $start_ts )/(60*60*24)" | bc
Returns '5.95' - the missing 0.05 being the lost hour from the DST switchover.
返回 '5.95' - 缺少的 0.05 是 DST 切换丢失的小时数。
So how should this be done correctly?
I would suggest using this instead:
那么应该如何正确地做到这一点呢?
我建议改用这个:
printf "%.0f" $(echo "scale=2; ( $end_ts - $start_ts )/(60*60*24)" | bc)
Here, the 'printf' rounds the more accurate result calculated by 'bc', giving us the correct date range of '6'.
在这里,“printf”四舍五入了“bc”计算出的更准确的结果,为我们提供了正确的日期范围“6”。
Edit: highlighting the answer in a comment from @hank-schultz below, which I have been using lately:
编辑:在下面来自@hank-schultz 的评论中突出显示答案,我最近一直在使用它:
date_diff=$(( ($(date -d "2015-03-11 UTC" +%s) - $(date -d "2015-03-05 UTC" +%s) )/(60*60*24) ))
This should also be leap second safe as long as you always subtract the earlier date from the later one, since leap seconds will only ever add to the difference - truncation effectively rounds down to the correct result.
只要您总是从较晚的日期中减去较早的日期,这也应该是闰秒安全的,因为闰秒只会增加差异 - 截断有效地向下舍入到正确的结果。
回答by jschnasse
This works for me:
这对我有用:
A="2002-10-20"
B="2003-11-22"
echo $(( ($(date -d $B +%s) - $(date -d $A +%s)) / 86400 )) days
Prints
印刷
398 days
What is happening?
怎么了?
- Provide valid time string in Aand B
- Use
date -d
to handle time strings - Use
date %s
to convert time strings to seconds since 1970 (unix epoche) - Use bash parameter expansionto subtract seconds
- divide by seconds per day (86400=60*60*24) to get difference as days
- ! DSTis not taken into account ! See this answer at unix.stackexchange!
- 在A和B 中提供有效的时间字符串
- 使用
date -d
处理时间字符串 - 使用
date %s
时间转换字符串秒自1970年以来(UNIX悬搁) - 使用bash参数扩展减去秒
- 除以每天的秒数 (86400=60*60*24) 得到天数的差异
- !不考虑夏令时!在unix.stackexchange看到这个答案!
回答by nickl-
Here's the MAC OS X version for your convenience.
为方便起见,这里是 MAC OS X 版本。
$ A="2002-20-10"; B="2003-22-11";
$ echo $(((`date -jf %Y-%d-%m $B +%s` - `date -jf %Y-%d-%m $A +%s`)/86400))
nJoy!
快乐!
回答by Ruchi
If the option -d works in your system, here's another way to do it. There is a caveat that it wouldn't account for leap years since I've considered 365 days per year.
如果选项 -d 在您的系统中有效,这是另一种方法。有一个警告,它不会考虑闰年,因为我已经考虑了每年 365 天。
date1yrs=`date -d "20100209" +%Y`
date1days=`date -d "20100209" +%j`
date2yrs=`date +%Y`
date2days=`date +%j`
diffyr=`expr $date2yrs - $date1yrs`
diffyr2days=`expr $diffyr \* 365`
diffdays=`expr $date2days - $date1days`
echo `expr $diffyr2days + $diffdays`
回答by glenn Hymanman
Even if you don't have GNU date, you'll probably have Perl installed:
即使您没有 GNU date,您也可能安装了 Perl:
use Time::Local;
sub to_epoch {
my ($t) = @_;
my ($y, $d, $m) = ($t =~ /(\d{4})-(\d{2})-(\d{2})/);
return timelocal(0, 0, 0, $d+0, $m-1, $y-1900);
}
sub diff_days {
my ($t1, $t2) = @_;
return (abs(to_epoch($t2) - to_epoch($t1))) / 86400;
}
print diff_days("2002-20-10", "2003-22-11"), "\n";
This returns 398.041666666667
-- 398 days and one hour due to daylight savings.
398.041666666667
由于夏令时,这将返回398 天零 1 小时。
The question came back up on my feed. Here's a more concise method using a Perl bundled module
这个问题又出现在我的提要上。这是使用 Perl 捆绑模块的更简洁的方法
days=$(perl -MDateTime -le '
sub parse_date {
@f = split /-/, shift;
return DateTime->new(year=>$f[0], month=>$f[2], day=>$f[1]);
}
print parse_date(shift)->delta_days(parse_date(shift))->in_units("days");
' $A $B)
echo $days # => 398
回答by Gotxi
This is the simplest i managed to get working on centos 7:
这是我设法在 centos 7 上工作的最简单的方法:
OLDDATE="2018-12-31"
TODAY=$(date -d $(date +%Y-%m-%d) '+%s')
LINUXDATE=$(date -d "$OLDDATE" '+%s')
DIFFDAYS=$(( ($TODAY - $LINUXDATE) / (60*60*24) ))
echo $DIFFDAYS
回答by GreyCat
I'd submit another possible solution in Ruby. Looks like it's the be smallest and cleanest looking one so far:
我会在 Ruby 中提交另一个可能的解决方案。看起来它是迄今为止最小和最干净的一个:
A=2003-12-11
B=2002-10-10
DIFF=$(ruby -rdate -e "puts Date.parse('$A') - Date.parse('$B')")
echo $DIFF