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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-09 20:10:42  来源:igfitidea点击:

How to find the difference in days between two dates?

bashshelldate

提问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 (-doption). 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?

怎么了?

  1. Provide valid time string in Aand B
  2. Use date -dto handle time strings
  3. Use date %sto convert time strings to seconds since 1970 (unix epoche)
  4. Use bash parameter expansionto subtract seconds
  5. divide by seconds per day (86400=60*60*24) to get difference as days
  6. ! DSTis not taken into account ! See this answer at unix.stackexchange!
  1. AB 中提供有效的时间字符串
  2. 使用date -d处理时间字符串
  3. 使用date %s时间转换字符串秒自1970年以来(UNIX悬搁)
  4. 使用bash参数扩展减去秒
  5. 除以每天的秒数 (86400=60*60*24) 得到天数的差异
  6. !不考虑夏令时!在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