如何找到两个日期之间的天数差异?

时间:2011-02-09 15:17:35

标签: bash shell date

A = “2002-20-10”
B =“2003-22-11”

如何找到两个日期之间的天数差异?

23 个答案:

答案 0 :(得分:57)

bash方式 - 将日期转换为%y%m%d格式,然后您可以直接从命令行执行此操作:

echo $(( ($(date --date="031122" +%s) - $(date --date="021020" +%s) )/(60*60*24) ))

答案 1 :(得分:25)

如果你有GNU date,它允许打印任意日期(-d选项)的表示。 在这种情况下,将日期转换为自EPOCH以来的秒数,减去并除以24 * 3600。

或者您需要一种便携式方式?

答案 2 :(得分:16)

在python中

$python -c "from datetime import date; print (date(2003,11,22)-date(2002,10,20)).days"
398

答案 3 :(得分:16)

小心!这里的许多bash解决方案都被打破了日期范围,这些日期范围跨越了夏令时开始的日期(如果适用)。这是因为$((math))构造对结果值执行'floor'/ truncation操作,仅返回整数。让我来说明一下:

DST于今年3月8日在美国开始,所以让我们使用一个跨越的日期范围:

start_ts=$(date -d "2015-03-05" '+%s')
end_ts=$(date -d "2015-03-11" '+%s')

让我们看看我们用双括号得到的东西:

echo $(( ( end_ts - start_ts )/(60*60*24) ))

返回'5'。

使用'bc'更准确地执行此操作会给我们带来不同的结果:

echo "scale=2; ( $end_ts - $start_ts )/(60*60*24)" | bc

返回'5.95' - 缺少的0.05是DST切换时的丢失小时数。

那么应该如何正确地完成呢? 我建议改用:

printf "%.0f" $(echo "scale=2; ( $end_ts - $start_ts )/(60*60*24)" | bc)

这里,'printf'舍入'bc'计算的更准确的结果,给我们正确的日期范围'6'。

编辑:在@ hank-schultz的评论中突出显示答案,我最近一直在使用

date_diff=$(( ($(date -d "2015-03-11 UTC" +%s) - $(date -d "2015-03-05 UTC" +%s) )/(60*60*24) ))

只要您总是从后一个日期中减去较早的日期,这也应该是闰秒安全,因为闰秒只会增加差异 - 截断有效地向下舍入到正确的结果。

答案 4 :(得分:7)

以下是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!

答案 5 :(得分:4)

如果选项-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`

答案 6 :(得分:4)

即使您没有GNU日期,也可能安装了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";

由于夏令时,这将返回398.041666666667 - 398天和1小时。


我的Feed反馈了这个问题。这是使用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

答案 7 :(得分:3)

这对我有用:

A="2002-10-20"
B="2003-11-22"
echo $(( ($(date -d $B +%s) - $(date -d $A +%s)) / 86400 )) days

打印

398 days

发生了什么事?

  1. A B
  2. 中提供有效的时间字符串
  3. 使用date -d处理时间字符串
  4. 使用date %s将时间字符串转换为自1970年以来的秒数(unix epoche)
  5. 使用bash parameter expansion减去秒数
  6. 除以每天的秒数(86400 = 60 * 60 * 24)以获得天数差异
  7. DST未被考虑在内!请在unix.stackexchange
  8. 上查看此答案

答案 8 :(得分:2)

这是我使用zsh的工作方法。在OSX上测试过:

# Calculation dates
## A random old date
START_DATE="2015-11-15"
## Today's date
TODAY=$(date +%Y-%m-%d)

# Import zsh date mod
zmodload zsh/datetime

# Calculate number of days
DIFF=$(( ( $(strftime -r %Y-%m-%d $TODAY) - $(strftime -r %Y-%m-%d $START_DATE) ) / 86400 ))
echo "Your value: " $DIFF

结果:

Your value:  1577

基本上,我们使用strftime反向(-r)功能将日期字符串转换回时间戳,然后进行计算。

答案 9 :(得分:1)

我会在Ruby中提交另一个可能的解决方案。看起来它是迄今为止最小,最干净的一个:

A=2003-12-11
B=2002-10-10
DIFF=$(ruby -rdate -e "puts Date.parse('$A') - Date.parse('$B')")
echo $DIFF

答案 10 :(得分:1)

在unix上

你应该安装GNU日期。你不需要偏离bash。考虑到几天,这里是解决方案,只是为了显示步骤。它可以简化并扩展到完整日期。

DATE=$(echo `date`)
DATENOW=$(echo `date -d "$DATE" +%j`)
DATECOMING=$(echo `date -d "20131220" +%j`)
THEDAY=$(echo `expr $DATECOMING - $DATENOW`)

echo $THEDAY 

答案 11 :(得分:0)

命令行bash解决方案

echo $((($(date +%s -d 20210131)-$(date +%s -d 20210101))/86400)) days

将打印

30 days

答案 12 :(得分:0)

对于 zsh(仅适用于同一年的日期)

echo $(($(date -d "today" +%j) - $(date -d "08 Jan 2021" +%j) )) days

答案 13 :(得分:0)

我不想在生成自签名证书时将过期时间硬编码为设定的天数,而是想让它们在 Y2k38 problem 开始之前(2028 年 1 月 19 日)过期。但是,OpenSSL 只允许使用 -days 设置到期时间,即从当前日期算起的天数。 我最终使用了这个:

openssl req -newkey rsa -new -x509 \
  -days $((( $((2**31)) - $(date +%s))/86400-1)) \
  -nodes -out new.crt -keyout new.key -subj '/CN=SAML_SP/'

答案 14 :(得分:0)

echo $(date +%d/%h/%y) date_today
echo " The other date is 1970/01/01"
TODAY_DATE="1970-01-01"
BEFORE_DATE=$(date +%d%h%y)
echo "THE DIFFERNS IS " $(( ($(date -d $BEFORE_DATE +%s) - $(date -d $TODAY_DATE +%s)) )) SECOUND

使用它来获取您今天的日期以及您想要的日期之后的秒数。如果需要,只需将其除以86400

echo $(date +%d/%h/%y) date_today
echo " The other date is 1970/01/01"
TODAY_DATE="1970-01-01"
BEFORE_DATE=$(date +%d%h%y)
echo "THE DIFFERNS IS " $(( ($(date -d $BEFORE_DATE +%s) - $(date -d $TODAY_DATE +%s))/ 86400)) SECOUND

答案 15 :(得分:0)

这是我设法在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

答案 16 :(得分:0)

对于MacOS sierra(可能来自Mac OS X yosemate),

要从文件中获取纪元时间(1970年的秒数),并将其保存到var: old_dt=`date -j -r YOUR_FILE "+%s"`

获取当前时间的纪元时间 new_dt=`date -j "+%s"`

计算上述两个纪元时间的差异 (( diff = new_dt - old_dt ))

检查差异是否超过23天 (( new_dt - old_dt > (23*86400) )) && echo Is more than 23 days

答案 17 :(得分:0)

这假设一个月是一年的1/12:

#!/usr/bin/awk -f
function mktm(datespec) {
  split(datespec, q, "-")
  return q[1] * 365.25 + q[3] * 365.25 / 12 + q[2]
}
BEGIN {
  printf "%d\n", mktm(ARGV[2]) - mktm(ARGV[1])
}

答案 18 :(得分:0)

使用mysql命令

$ echo "select datediff('2013-06-20 18:12:54+08:00', '2013-05-30 18:12:54+08:00');"  | mysql -N

结果:21

注意:在计算中仅使用值的日期部分

参考:http://dev.mysql.com/doc/refman/5.6/en/date-and-time-functions.html#function_datediff

答案 19 :(得分:0)

假设我们手动将Oracle DB备份rsync到第三层磁盘。然后我们要删除该磁盘上的旧备份。所以这是一个小的bash脚本:

#!/bin/sh

for backup_dir in {'/backup/cmsprd/local/backupset','/backup/cmsprd/local/autobackup','/backup/cfprd/backupset','/backup/cfprd/autobackup'}
do

    for f in `find $backup_dir -type d -regex '.*_.*_.*' -printf "%f\n"`
    do

        f2=`echo $f | sed -e 's/_//g'`
        days=$(((`date "+%s"` - `date -d "${f2}" "+%s"`)/86400))

        if [ $days -gt 30 ]; then
            rm -rf $backup_dir/$f
        fi

    done

done

修改目录和保留期(“30天”)以满足您的需求。

答案 20 :(得分:0)

使用http://cfajohnson.com/shell/ssr/ssr-scripts.tar.gz中的shell函数;它们适用于任何标准的Unix shell。

date1=2012-09-22
date2=2013-01-31
. date-funcs-sh
_date2julian "$date1"
jd1=$_DATE2JULIAN
_date2julian "$date2"
echo $(( _DATE2JULIAN - jd1 ))

请参阅http://cfajohnson.com/shell/ssr/08-The-Dating-Game.shtml

上的文档

答案 21 :(得分:0)

另一个Python版本:

python -c "from datetime import date; print date(2003, 11, 22).toordinal() - date(2002, 10, 20).toordinal()"

答案 22 :(得分:0)

尝试一下:

perl -e 'use Date::Calc qw(Delta_Days); printf "%d\n", Delta_Days(2002,10,20,2003,11,22);'
相关问题