##
# 本文为《shell脚本专家指南》一书的学习笔记。
##
3.1. 用天数来计算日期
unix和linux以1970年1月1日0时0分开始计算时间,也就是所谓的时间戳,单位是
秒。在系统中,可以使用 date +'%s' 来查看。
严格来讲,系统的起止时间是以零时区开始计算的。比如,一般我们系统的时区为
东八区(+8),故使用 date -d '1970-1-1 0:0' +'%s'得到是-28800,即当
东八区为1970-1-1 0:0时,零时区的时间实际为1969-12-31 16:00。
linux中/etc/shadow文件中,第三个字段,保留了用户上次修改密码的时间,距
1970-1-1经过的天数。
计算公式
(Year*365)+(Year/4)-(Year/100)+(Year/400)+(Month*306001/10000)+(Day)
公式适用于1582-10-15到9999-12-31时间段的天数计算,数值为指定日期到
元年的天数。
公式套用中,1月2月中,年份要减1,月份要加13,对于非1月2月,直接月份
加1就可以套用。据网上的说法,可能跟月份乘以的306001这个值有关系。
据说是月的平均天数。
关于这个公式。。。建议不要瞎想,我瞎想了两天,都没想出个头绪,最后
看仔细作者对公式的描述,才恍然大悟。这个公式只是为了便于计算
1582-10-15到9999-12-31范围内不同日期间的天数差值。如果单独给公式套入
一个日期,得到的天数并没有任何意义。
unix的纪元日期为公元纪元的1970-1-1,可以记一个固定值719591,用于快速
计算各日期据unix纪元日期的天数。
3.1.1. 自从纪元以来的天数
示例:该脚本计算的描述,为当前时区的时间,至纪元时间的秒数。
系统的 date +%s 命令,显示的为零时区至纪元时间的描述。
比如,在东八区,该脚本执行的秒数为 1544809090 ,而date +%s输出为 1544780309 。
两者相差 28781 ,刚好是7.99(两条命令分开执行,时间上差了几秒)。
#!/bin/bash
epoch_days=719591
declare -a DATE=(`date +"%S %M %H %d %m %Y"`)
year="${DATE[5]}"
month="${DATE[4]}"
day="${DATE[3]}"
hour="${DATE[2]}"
minute="${DATE[1]}"
second="${DATE[0]}"
if [ $month -gt 2 ];
then
month=$(($month+1))
else
month=$(($month+13))
year=$($year-1)
fi
today_days=$(( $year*365 + $year/4 -$year/100 + $year/400 + $month*306001/10000 + $day ))
echo $today_days
days_since_epoch=$(( $today_days - $epoch_days ))
echo $days_since_epoch
seconds_since_epoch=`echo "$days_since_epoch*86400 + $hour*3600 + $minute*60 + $second" | bc`
echo $seconds_since_epoch
3.1.2. 以秒计算日期的其他方法
在gnu版本中,date 命令可以直接加参 +%s 来获取秒数,为零时区对应时间
至纪元时间的秒数。
3.2. 评估当前日期和时间
书中给出了一个示例,通过判断当前星期和小时,决定是否调度一个作业。
#!/bin/bash
test $# -ne 4 && {
echo "Usage: $0 <day begin> <day end> <hour begin> <hour end>"
echo " Days are 0-6 where 0 is Sunday."
echo " Hours are 0-23"
exit 9
}
DAY_BEGIN=$1
DAY_END=$2
HOUR_BEGIN=$3
HOUR_END=$4
DAY=`date +%w`
HOUR=`date +%H`
if [ $DAY -ge $DAY_BEGIN -a $DAY -le $DAY_END ] && [ $HOUR -ge $HOUR_BEGIN -a $HOUR -le $HOUR_END ];
then
echo "It is time to notify."
# 原文为return 0。
exit 0
else
echo "It is not time to notify."
# 原文为return 1。
exit 1
fi