Crane
Table_bottom

Search
Loading
Table_bottom

分类
Table_bottom

随机文章
Table_bottom

标签云
Table_bottom

最新评论
Table_bottom

链接
Table_bottom

功能
Table_bottom

计算两个日期的差值

Crane posted @ 2011年4月08日 05:58 in Linux with tags linux program shell 程序员 , 15213 阅读

记得今年早些时候看到百度员工出的那个视频,中间有一幕女主角在计算自己自出生以来已经生活了多少天,只见她熟练的打开excel,在A1中输入生日,在B1中输入当天日期,在C1中输入=B1-A1,立刻得到自己来到这个世上的时间,眼看过去了这么多天,自己当初的梦想实现了多少呢,……,剧情自此展开,不再追踪。

我看到这个的时候,想着cli控们有没有什么方法能实现同样的功能呢,无所不能的shell(我记得有人说过shell是完备的)啊,需要你的力量。

想了一下,使用了coreutils中的date命令,写成了如下shell脚本:

 

#/bin/sh
#
# this scrit is used to calculate the distance between two date.
# e.g. My birthday is 1988-12-29,today is 2011-04-01,I want to how
# many days I have been alive in this world.
# so use
#  daydis.sh 19881229 20110401

function error_msg(){
    echo -n This is a shell script to count days between date.
    echo '  usage: $0 date1 date2'
    echo -e '\tfor example, to calculate how many days between two date,'
    echo -e '\te.g. from 19881229 to 20110401'
    echo -e '\ttry: $0 19881229 20110401'
    exit
}
from=$1
to=$2
if [ ${#from} -ne 8 ] || [ ${#to} -ne 8 ];then
    error_msg
fi
if [ $(($1-$2)) -gt 0 ] ;then
    error_msg
fi
if [ ${from:0:4} -lt 1902 ] || [ ${to:0:4} -gt 2037 ];then
    echo "the year of date should range from 1902 to 2037."
    exit
fi
from=`eval date -d "$1" +%s`
#echo $from
to=`eval date -d "$2" +%s`
#echo $to
secdis=`echo $(($to-$from))`
#echo $secdis
daydis=`echo $(($secdis/3600/24))`

echo "from $1 to $2,there are $daydis day(s)."

原理是用到了日历时间,在UNIX系统中的时间定义是这样的,系统用一个time_t类型的变量来表示系统时间,它的值是从1970年1月1日00:00:00以来所经过的秒数的累计,程序中就是通过计算两个日期的这个秒数累计的差,然后把这个秒数差值转换成天数,即得到了我们要的答案。

得到一个日期的秒数累计(日历时间)可以用date命令来搞定,比如2011年4月1日,可以这样

$ date -d "20110401" +%s

1301587200

得到的那个1301587200就是一个秒数的累计,再做一些简单的算术运算就可以得到所要的结果。

PS:上面可以看到这个秒数已经累计到13亿了,而如果用一个32位整数来存放这个的话,有符号的最大也就是21亿多,貌似已经很靠近了,如果到了那一天会有什么问题呢?这就是著名的Year 2038 problem,不过不用担心,到那个时间还早着呢,这期间硬件变化,把32位的换成64位,或者干脆用一个浮点数来存这个,都不会出现这个问题。


登录 *


loading captcha image...
(输入验证码)
or Ctrl+Enter