聊聊 Shell 腳本中的日期運(yùn)算
本文轉(zhuǎn)載自微信公眾號(hào)「Linux開發(fā)那些事兒」,作者 LinuxThings 。轉(zhuǎn)載本文請(qǐng)聯(lián)系Linux開發(fā)那些事兒公眾號(hào)。
平常寫shell腳本的過(guò)程中,經(jīng)常要用到日期的運(yùn)算,比如:日期的加減、與UTC時(shí)間換算,比較大小等等,下面就來(lái)聊一聊這些常用的日期運(yùn)算
日期加減
- 秒增減
- [root@ecs-centos-7 ~]# date +'%Y-%m-%d %H:%M:%S' -d "70 second 2020-10-20 12:00:00"
- 2020-10-20 12:01:10
- [root@ecs-centos-7 ~]# date +'%Y-%m-%d %H:%M:%S' -d "-70 second 2020-10-20 12:00:00"
- 2020-10-20 11:58:50
- 分鐘增減
- [root@ecs-centos-7 ~]# date +'%Y-%m-%d %H:%M:%S' -d "10 minute 2020-10-20 12:00:00"
- 2020-10-20 12:10:00
- [root@ecs-centos-7 ~]# date +'%Y-%m-%d %H:%M:%S' -d "-10 minute 2020-10-20 12:00:00"
- 2020-10-20 11:50:00
- 小時(shí)增減
- [root@ecs-centos-7 ~]# date +'%Y-%m-%d %H:%M:%S' -d "1 hour 2020-10-20 12:00:00"
- 2020-10-20 13:00:00
- [root@ecs-centos-7 ~]# date +'%Y-%m-%d %H:%M:%S' -d "-1 hour 2020-10-20 12:00:00"
- 2020-10-20 11:00:00
- 天增減
- [root@ecs-centos-7 ~]# date +'%Y-%m-%d %H:%M:%S' -d "3 day 2020-10-20 12:00:00"
- 2020-10-23 12:00:00
- [root@ecs-centos-7 ~]# date +'%Y-%m-%d %H:%M:%S' -d "-3 day 2020-10-20 12:00:00"
- 2020-10-17 12:00:00
- 周增減
- [root@ecs-centos-7 ~]# date +'%Y-%m-%d %H:%M:%S' -d "1 week 2020-10-20 12:00:00"
- 2020-10-27 12:00:00
- [root@ecs-centos-7 ~]# date +'%Y-%m-%d %H:%M:%S' -d "-1 week 2020-10-20 12:00:00"
- 2020-10-13 12:00:00
- 月增減
- [root@ecs-centos-7 ~]# date +'%Y-%m-%d %H:%M:%S' -d "2 month 2020-10-20 12:00:00"
- 2020-12-20 12:00:00
- [root@ecs-centos-7 ~]# date +'%Y-%m-%d %H:%M:%S' -d "-2 month 2020-10-20 12:00:00"
- 2020-08-20 12:00:00
- 年增減
- [root@ecs-centos-7 ~]# date +'%Y-%m-%d %H:%M:%S' -d "1 year 2020-10-20 12:00:00"
- 2021-10-20 12:00:00
- [root@ecs-centos-7 ~]# date +'%Y-%m-%d %H:%M:%S' -d "-1 year 2020-10-20 12:00:00"
- 2019-10-20 12:00:00
- 年月日時(shí)分秒增減
年月日時(shí)分秒除了每一個(gè)單獨(dú)進(jìn)行日期增減之外,還可以一起使用
- [root@ecs-centos-7 ~]# date +'%Y-%m-%d %H:%M:%S' -d "1 year 2 month 1 week 3 hour -10 minute 40 second 2020-10-20 12:00:00"
- 2021-12-27 14:50:40
- 一個(gè)月中第幾天
- [root@ecs-centos-7 ~]# date +%Y%m%d
- 20201023
- [root@ecs-centos-7 ~]# date +%d
- 23
- [root@ecs-centos-7 ~]# date +%d -d "20201013"
- 13
date +%d 命令是計(jì)算當(dāng)前日期( 2020年10月23日 ) 是一個(gè)月中的第幾天
date +%d -d "20201013" 命令是計(jì)算 2020年10月13日 是一個(gè)月中第幾天
- 一年中第幾周
- [root@ecs-centos-7 ~]# date +%Y%m%d
- 20201023
- [root@ecs-centos-7 ~]# date +%V
- 43
- [root@ecs-centos-7 ~]# date +%V -d "20201005"
- 41
上面例子中, date +%V 命令是計(jì)算當(dāng)前日期是一年中第幾周,星期一是一周的第一天,取值范圍是 01-53,date +%V -d "20201005" 命令是計(jì)算指定日期 ( 20201005 ) 是一年中第幾周
- 一周中第幾天
- [root@ecs-centos-7 ~]# date +%Y%m%d
- 20201023
- [root@ecs-centos-7 ~]# date +%u
- 5
- [root@ecs-centos-7 ~]# date +%u -d "20201004"
- 7
上面的例子中,date +%u 命令是計(jì)算當(dāng)前日期是一周中第幾天,取值范圍是 1 - 7,分別表示周一至周日,結(jié)果是 5,表示當(dāng)前這一天是周五, date +%u -d "20201004" 命令是計(jì)算指定日期 ( 20201004 ) 是一周中第幾天,結(jié)果是 7 ,表示 2020年10月4日是周日
- [root@ecs-centos-7 ~]# date +%Y%m%d
- 20201023
- [root@ecs-centos-7 ~]# date +%w
- 5
- [root@ecs-centos-7 ~]# date +%w -d "20201004"
- 0
上面例子中,date +%w 命令是也是計(jì)算當(dāng)前日期是一周中第幾天,取值范圍是 0 - 6 , 0 代表周日,1 - 6 分別代表周一至周六
命令 date +%w -d "20201004" 是計(jì)算指定日期 ( 20201004 ) 是一周中第幾天,結(jié)果是 0,表示2020年10月4日是周日
月第一天和月最后一天
- [root@ecs-centos-7 ~]# date +"%Y-%m-%d" -d "-$(($(date +%d -d '2020-10-20') -1 )) days 2020-10-20"
- 2020-10-01
- [root@ecs-centos-7 ~]# date +"%Y-%m-%d" -d "-$(($(date +%d -d '2020-10-20') )) days +1 month 2020-10-20"
- 2020-10-31
上面例子中,date +"%Y-%m-%d" -d "-$(($(date +%d -d '2020-10-20') -1 )) days 2020-10-20" 命令是計(jì)算日期 2020-10-20 中月份的第一天, 結(jié)果是 2020-10-01
命令 date +"%Y-%m-%d" -d "-$(($(date +%d -d '2020-10-20') )) days +1 month 2020-10-20" 是計(jì)算日期 2020-10-20 中月份的最后一天, 結(jié)果是 2020-10-31
日期和UTC時(shí)間互相轉(zhuǎn)換
- 日期轉(zhuǎn) UTC 時(shí)間
UTC時(shí)間是整數(shù),把日期轉(zhuǎn)成UTC時(shí)間,更方便各種計(jì)算
- [root@ecs-centos-7 ~]# date +%s
- 1603443806
- [root@ecs-centos-7 ~]# date +%s -d "2020-10-20 12:00:00"
- 1603166400
- [root@ecs-centos-7 ~]# date +%s -d "2020-10-20 00:00:00"
- 1603123200
- [root@ecs-centos-7 ~]# date +%s -d "2020-10-20"
- 1603123200
- [root@ecs-centos-7 ~]# date +%s -d "2020-10-01"
- 1601481600
上面例子中,date +%s 命令是把當(dāng)前時(shí)間轉(zhuǎn)成 UTC 時(shí)間,date +%s -d "2020-10-20 12:00:00" 命令是把 2020-10-20 12:00:00 轉(zhuǎn)成UTC時(shí)間
- UTC時(shí)間轉(zhuǎn)日期
- [root@ecs-centos-7 ~]# date +%s -d "2020-10-20 12:00:00"
- 1603166400
- [root@ecs-centos-7 ~]# date -d "@1603166400"
- 2020年 10月 20日 星期二 12:00:00 CST
命令 date +%s -d "2020-10-20 12:00:00" 是計(jì)算 2020-10-20 12:00:00 的UTC時(shí)間,這里主要是為了和后面UTC時(shí)間轉(zhuǎn)日期做對(duì)比用的
命令 date -d "@1603166400" 是計(jì)算UTC時(shí)間( 1603166400 ) 對(duì)應(yīng)的日期,計(jì)算結(jié)果是 2020年 10月 20日 星期二 12:00:00 CST 前一條命令的日期參數(shù)是一致的
日期比較大小
shell中直接比較日期相當(dāng)于字符串比較,可以先把日期轉(zhuǎn)成UTC時(shí)間再進(jìn)行比較,下面是一個(gè)日期比較的測(cè)試腳本 ( t.sh ),執(zhí)行時(shí)需要傳入兩個(gè)待比較的日期
- #!/bin/bash
- date1=$(date +%s -d "$1")
- date2=$(date +%s -d "$2")
- if [[ ${date1} -lt ${date2} ]]; then
- echo " $1 < $2 "
- elif [[ ${date1} -eq ${date2} ]]; then
- echo " $1 = $2 "
- else
- echo " $1 > $2 "
- fi
執(zhí)行測(cè)試腳本,具體結(jié)果如下:
- [root@localhost shell_test]# ./t.sh "20201020" "20201020"
- 20201020 = 20201020
- [root@localhost shell_test]# ./t.sh "20201020" "20201021"
- 20201020 < 20201021
- [root@localhost shell_test]# ./t.sh "20201020" "20201019"
- 20201020 > 20201019
- [root@localhost shell_test]#
- [root@localhost shell_test]# ./t.sh "2020-10-20 00:00:01" "2020-10-20 00:00:00"
- 2020-10-20 00:00:01 > 2020-10-20 00:00:00
- [root@localhost shell_test]# ./t.sh "2020-10-20 00:00:01" "2020-10-20 00:00:01"
- 2020-10-20 00:00:01 = 2020-10-20 00:00:01
- [root@localhost shell_test]# ./t.sh "2020-10-20 00:00:01" "2020-10-20 00:00:10"
- 2020-10-20 00:00:01 < 2020-10-20 00:00:10
- [root@localhost shell_test]#
從結(jié)果可以看出, t.sh 腳本傳入日期參數(shù)既可以只有年月日又可以年月日時(shí)分秒都有,而且日期的格式既可以是 20201020 格式,又可以是 2020-10-20 00:00:00 格式的
日期循環(huán)遍歷
在工作中,經(jīng)常要處理一段時(shí)間內(nèi)的日志,需要遍歷日期,然后對(duì)每天的日志做處理,下面的測(cè)試腳本 ( t.sh ) 是測(cè)試日期遍歷的, 腳本內(nèi)容如下:
- #!/bin/bash
- #開始日期
- begindate=$1
- #結(jié)束日期
- enddate=$2
- #后一天日期,用于循環(huán)
- nextdate=${begindate}
- #后一天日期的utc時(shí)間,用于比較日期
- nextutc=$(date +%s -d "${nextdate}")
- #結(jié)束日期的UTC時(shí)間
- endutc=$(date +%s -d "${enddate}")
- while [ ${nextutc} -le ${endutc} ]
- do
- echo "process ${nextdate} log..."
- #計(jì)算后一天的日期
- nextdate=$(date -d "${nextdate} 1 day" +%Y%m%d)
- #計(jì)算后一天日期的utc時(shí)間
- nextutc=$(date +%s -d "${nextdate}")
- done
執(zhí)行測(cè)試腳本,具體結(jié)果如下:
- [root@localhost shell_test]# ./t.sh "20201020" "20201023"
- process 20201020 log...
- process 20201021 log...
- process 20201022 log...
- process 20201023 log...