对日期进行操作,相信每一个 RD 都不会陌生,在我所主要接触、工作的 3 种语言里,感觉 shell 下的 date 设计的最简洁实用,其次是 python,最复杂难用的当属 java 中的 date 了。
下面要介绍的 date 是指 linux 下的 GNU date, unix 用户或者非 gnu date 用户只能 YY 下了,因为下文的绝大多数特性你那都不支持的。
1、获取当前时间 并格式化
june@Win7 192.168.1.101 01:46:27 ~ > date Sat, Dec 21, 2013 1:49:15 AM june@Win7 192.168.1.101 01:49:15 ~ > date -I 2013-12-21 june@Win7 192.168.1.101 02:16:52 ~ > date -d tomorrow +%Y-%m-%d 2013-12-22 june@Win7 192.168.1.101 02:17:49 ~ > date -d yesterday +%Y-%m-%d 2013-12-20 june@Win7 192.168.1.101 02:18:05 ~ > date -d last-day +%Y-%m-%d 2013-12-20 june@Win7 192.168.1.101 02:18:15 ~ > date +'%F %T' 2013-12-21 01:49:26 june@Win7 192.168.1.101 01:49:26 ~ > date +"%Y-%m-%d %H:%M:%S" 2013-12-21 01:49:52 june@Win7 192.168.1.101 01:49:52 ~ >
2、日期的二 则运算
GNU date 的日期加减运算是支持自然语言的,主要有三种指令:
last/next指令
ago指令
负数指令
june@Win7 192.168.1.101 02:10:00 ~ > date -I && date -I -d'last sunday -7 days' 2013-12-21 2013-12-08 june@Win7 192.168.1.101 02:10:03 ~ > # 注意:语法对年月日、时分秒都适用 june@Win7 192.168.1.101 01:59:47 ~ > date -d '20110614 next-day' +%Y-%m-%d 2011-06-15 june@Win7 192.168.1.101 02:01:17 ~ > date -d '20110614 1 days' +%Y-%m-%d 2011-06-15 june@Win7 192.168.1.101 02:01:39 ~ > date -d '20110614 1 days ago' +%Y-%m-%d 2011-06-13 # 注意最好用自然语言,别用 +1 -1 操作,某些早期版本(如RedHat 4U7)不支持可能造成错误结果,而且这种写法会和时区语法冲突,容易出问题。 june@Win7 192.168.1.101 02:01:44 ~ > date -d '20110614 -1 days' +%Y-%m-%d 2011-06-13 june@Win7 192.168.1.101 02:01:57 ~ > date -d '20110614 +1 days' +%Y-%m-%d 2011-06-15 june@Win7 192.168.1.101 02:02:01 ~ >
3、字符串转换为日期、指定时间格式
#美国式时间格式 june@Win7 10.59.9.38 18:02:30 ~ > date -d'31/Oct/2013:00:00:10 +0800' +'%F %T' date: invalid date `31/Oct/2013:00:00:10 +0800' june@Win7 10.59.9.38 18:02:34 ~ > date -d'31 Oct 2013 00:00:10 +0800' +'%F %T' 2013-10-31 00:00:10 june@Win7 10.59.9.38 18:07:34 ~ > #秒转为分 date -d @103 +%m"min"%S"s" #日期转时间戳 june@Win7 192.168.1.101 02:02:01 ~ > date -d "2010-12-11" +%s 1291996800 #时间戳转日期 june@Win7 192.168.1.101 02:04:22 ~ > date -d@1291996800 -I 2010-12-11 # 下面的是非常规方法,拓展思路而已 june@Win7 192.168.1.101 02:10:03 ~ > echo 1307980800 | awk '{T=strftime("%F %T",$1);print T}' 2011-06-14 00:00:00 june@Win7 192.168.1.101 02:16:15 ~ > echo '1307980800' |sed -r -e "s/(.*)/date -d @\1 '+%Y-%m-%d %H:%M:%S'/e" 2011-06-14 00:00:00 june@Win7 192.168.1.101 02:16:52 ~ > #此方法在大于2038年的时候会有问题,即使是 64bit 也是有问题的。32473710849 date -d "UTC 1970-01-01 1234567890 secs"
4、注 意时区问题
date 里面时间的 + - 注意格式会影响结果/时区(最安全的写法是不要带符号,用自然语言即可):
date -d'2013-07-01 09:52:33 +1 minutes' # 这个+1被当成时区了 Mon, Jul 01, 2013 4:53:33 PM date -d'2013-07-01 09:52:33 1 minutes' # 同样 -1 也会有问题 Mon, Jul 01, 2013 9:53:33 AM date -u --date='+2 minutes 13-07-01 09:52:33' # 把 + - 时间放在最前面也行 Mon Jul 1 09:54:33 UTC 2013 date -u --date='13-07-01 09:52:33 +0 +2 minutes' # 注意前面的 -u UTC时间,少了也会有问题 Mon Jul 1 09:54:33 UTC 2013 date -u --date='13-07-01 09:52:33 GMT +2 minutes' # 指定时区 Mon Jul 1 09:54:33 UTC 2013
5、最后的技能: (1)当 %H%M 遇上 [[ ]]
请看下面这段代码,很多人估计会犯的错误:
[[ `date +'%H%M'` -eq 0 ]]
恭喜你,你每天早上的 8、9 点执行脚本的话都会遇到:
value too great for base (error token is "0950") 这样的错误,
这是因为 [[]] 把 0950 当成 8 进制来解析了,所以抛异常了。
解决办法有如下 3 种,可以选择你认为最爽的一种修复:
(1.1)换成 [ 0 -eq 0950 ] && echo 1 即可
(1.2)或者手动指定进制也行 [[ 950 -eq 10#0950 ]] && echo 1
(1.3)让 '%H%M' 这种格式不带前导符 0:
june@Win7 192.168.1.101 02:30:03 ~ > date +'[%H%M]' [0230] june@Win7 192.168.1.101 02:30:19 ~ > date +'[%_H%_M]' [ 230] june@Win7 192.168.1.101 02:30:26 ~ > date +'[%-H%-M]' [230] june@Win7 192.168.1.101 02:30:35 ~ >
(2)如何快速获取一个日期列表
june@Win7 192.168.1.101 02:30:35 ~ ># seq -w,seq -f%.8g, echo {..} date -f <(seq -f%.0f 20130227 20130301) +%Y%m%d 2>/dev/null 20130227 20130228 20130301 june@Win7 192.168.1.101 02:33:50 ~ >
好吧,今天的主题就到此为止了,希望本文能对你有所帮助。
简单、高效一直是每个 Linuxer 追求的目标,如果你也有这方面的技巧/问题需要交流,欢迎通过下面的评论来与我保持联系。
6、Ref
(1)一个关于date -d '1 month ago' 的 “bug”
http://hi.baidu.com/leejun_2005/item/8cb255757225835b0d0a078a
(2)date非常规用法总结
http://scmbob.org/special_usage_of_date.html
(3)shell 转换时间戳获取两个时间段的所有日期,返回list
http://hi.baidu.com/leejun_2005/item/92854594db7ca831326eeb69
(4)python datetime 时间日期处理小结
http://hi.baidu.com/leejun_2005/item/abaf4d0e3aac8a153b53ee69
(5)自定义 java 日期、时间 处理函数集
http://my.oschina.net/leejun2005/blog/92665