A =“ 2002-20-10”
B =“ 2003-22-11”
如何找到两个日期之间的天数差异?
Answers:
如果您有GNU date
,它允许打印任意日期的表示形式(-d
选项)。在这种情况下,将日期转换为自EPOCH以来的秒数,然后减去并除以24 * 3600。
还是您需要一种便携式方式?
echo "( `date -d $B +%s` - `date -d $A +%s`) / (24*3600)" | bc -l
bash方式-将日期转换为%y%m%d格式,然后可以直接从命令行执行此操作:
echo $(( ($(date --date="031122" +%s) - $(date --date="021020" +%s) )/(60*60*24) ))
%y%m%d
格式。例如,gnu date将接受所%Y-%m-%d
用OP的格式。通常,ISO-8601是一个不错的选择(OP的格式就是这样一种格式)。最好避免使用两位数年份的格式。
days_diff=$(( (`date -d $B +%s` - `date -d "00:00" +%s`) / (24*3600) ))
。请注意,这$days_diff
将是一个整数(即无小数)
date
安装的变体。它适用于GNU date
。它不适用于POSIX date
。对于大多数读者来说,这可能不是问题,但是值得注意。
tl; dr
date_diff=$(( ($(date -d "2015-03-11 UTC" +%s) - $(date -d "2015-03-05 UTC" +%s)) / (60*60*24) ))
小心!这里的许多bash解决方案都打破了日期范围,该范围跨越了夏令时开始的日期(如果适用)。这是因为$((math))构造对结果值执行了“ floor” /截断运算,仅返回整数。让我说明一下:
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) ))
只要您总是从较晚的日期中减去较早的日期,这也应该是leap秒安全的,因为leap秒只会增加差异-截断有效地舍入为正确的结果。
echo $(( ($(date --date="2015-03-11 UTC" +%s) - $(date --date="2015-03-05 UTC" +%s) )/(60*60*24) ))
,返回6,而不是5
并在python中
$python -c "from datetime import date; print (date(2003,11,22)-date(2002,10,20)).days"
398
bash
和shell
,所以我认为我们可以假设我们正在谈论* nix系统。在这样的系统中,echo
并且date
确实存在,但是python没有。
这对我有用:
A="2002-10-20"
B="2003-11-22"
echo $(( ($(date -d $B +%s) - $(date -d $A +%s)) / 86400 )) days
版画
398 days
怎么了?
date -d
处理时间字符串date %s
时间转换字符串秒自1970年以来(UNIX悬搁)如果选项-d在您的系统中可用,则这是另一种方法。需要注意的是,自从我考虑过每年365天以来,这并不能说明leap年。
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`
为方便起见,这是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))
欢乐!
A="2002-20-10"; B="2003-22-11"
echo $(((`date -jf "%Y-%d-%m" "$B" +%s` - `date -jf "%Y-%d-%m" "$A" +%s`)/86400))
,即将格式和变量都包装在双引号中,否则可能在不同的日期格式(例如%b %d, %Y
/ Jul 5, 2017
)上失败
即使您没有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天零一个小时。
这个问题再次出现在我的提要上。这是使用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
这是我使用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
)功能将日期字符串转换回时间戳,然后进行计算。
我将在Ruby中提交另一个可能的解决方案。看起来到目前为止,它是最小,最干净的一种:
A=2003-12-11
B=2002-10-10
DIFF=$(ruby -rdate -e "puts Date.parse('$A') - Date.parse('$B')")
echo $DIFF
date
或某些脚本语言),老实说,Ruby是进入此处的好方法。该解决方案非常简短,并且不使用任何非标准库或其他依赖项。实际上,我认为安装Ruby的可能性比安装GNU日期的可能性高。
使用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上的文档
使用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
试试看:
perl -e 'use Date::Calc qw(Delta_Days); printf "%d\n", Delta_Days(2002,10,20,2003,11,22);'
假设我们手动将Oracle DB备份同步到第三磁盘。然后,我们要删除该磁盘上的旧备份。因此,这是一个小的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
修改Dirs和保留期限(“ 30天”)以适合您的需求。
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