文档章节

玩转 SHELL 脚本之:linux date 知多少?

大数据之路
 大数据之路
发布于 2013/12/21 02:57
字数 1902
阅读 3411
收藏 67

最近好久没 update 了,一来是近期有点烦人的私事需要处理,二来是工作有点忙,业余时间还要整个 PPT,搜集素材啥的,非常耗时间。。。好吧,这都是借口,其实是人变懒了。。。⊙﹏⊙ 不过我发现最近 1 个月以来,我关注的一些 Blog,一半以上也都没更新了,看来对大家来说年底都是多事之秋呀~

好了,言归正传,之前有介绍过《linux 系统监控、诊断工具之 top 详解》、《linux 系统监控、诊断工具之 lsof 用法简介》,今天再来介绍一个使用频率很高的 linux 命令:date

对日期进行操作,相信每一个 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

Jun@VAIO 192.168.31.171 23:43:29 ~ >
date +%:z   # 获取时区与UTC的差
+08:00
Jun@VAIO 192.168.31.171 23:44:15 ~ >

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 ~ >

注意:

  • date 自然语言指令在天、小时、分钟多单位混合的时候注意每个单位都要加限定条件 ago/-,否则默认是 after:

Jun@VAIO 192.168.1.216 15:48:36 ~ >
date -d'-1 hours -30 minutes'
2015年08月 9日 14:18:54
Jun@VAIO 192.168.1.216 15:48:54 ~ >
date -d'1 hours ago 30 mins ago'
2015年08月 9日 14:18:59
Jun@VAIO 192.168.1.216 15:49:00 ~ >
date -d'1 hours 30 mins ago'
2015年08月 9日 16:19:06
Jun@VAIO 192.168.1.216 15:49:06 ~ >

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 -u -d@3613 +%H"h"%M"min"%S"s"
01h00min13s

#日期转时间戳

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 进制来解析了,所以抛异常了。

这里的规则是:

以 0 开头默认 8 进制,以 0x 开头 16 进制,或者你用 n# 的方式手动指定:

[[ 0010 -eq 8 ]] && echo 111 
111
[[ 8#10 -eq 8 ]] && echo 111
111
[[ 0x10 -eq 16 ]] && echo 111 
111

解决办法有如下 4 种,可以选择你认为最爽的一种修复:

  • (1.1)换成 [ 0 -eq 0950 ] && echo 1 即可

  • (1.2)或者手动指定进制也行 [[ 10#`date +%H%M` -eq 10#0950 ]] && echo 1

  • (1.3)两边当做字符串来对待 [[ "`date +'%H%M'`" == "0950" ]] && echo 1

  • (1.4)加 - 格式化占位符,让 '%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 ~ >

(3)如何获取任意日期的月末/月初(第一天/最后一天)?

判断今天是不是月末:
	[ `date --date='next day' +'%B'` != `date +'%B'` ] && echo 'end of month' || echo 'not end of month' 
	[[ `date +%d` -eq `echo $(cal)|grep -Po '\d+$'` ]] && echo 月末 || echo 非月末
得到当月/上月的第1天/最后一天:
	# First Day, current month: ## %d = day of month.
	date -d "-0 month -$(($(date +%d)-1)) days"	 
	# First Day, last month:
	date -d "-1 month -$(($(date +%d)-1)) days"
	# Last Day, last month:
	date -d "-$(date +%d) days -0 month"
	# Last Day, current month:
	date -d "-$(date +%d) days +1 month"
	# Last Day, month before last month:
	date -d "-$(date +%d) days -1 month"
得到指定日期当月的最后一天:
Jun@VAIO 192.168.1.216 23:57:02 ~ >
getlastDay_func1(){ echo `echo $(cal $(echo $1|awk -vFIELDWIDTHS="4 2 2" '{print $2,$1}'))|grep -Po '\d+$'`; }
Jun@VAIO 192.168.1.216 23:57:45 ~ >
getlastDay_func1 20150214
28
Jun@VAIO 192.168.1.216 23:56:44 ~ >
getlastDay_func2(){ echo `date -d"-1 days +1 month $(echo $1|sed -r 's/(....)(..).*/\1-\2-01/')" +%Y%m%d`; }
Jun@VAIO 192.168.1.216 23:56:52 ~ >
getlastDay_func2 20150214
20150228
Jun@VAIO 192.168.1.216 23:57:02 ~ >

好吧,今天的主题就到此为止了,希望本文能对你有所帮助。

简单、高效一直是每个 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

© 著作权归作者所有

大数据之路
粉丝 1593
博文 516
码字总数 336681
作品 0
武汉
架构师
私信 提问
加载中

评论(5)

仪山湖
仪山湖
总结的好全,收藏的
大数据之路
大数据之路 博主

引用来自“买合苏提”的评论

引用来自“xrzs”的评论

引用来自“买合苏提”的评论

不知什么原因,代码在客户端里显示都是连成一片的

显示有问题可以直接@红薯 大哥,看看是不是某个 android 客户端版本和 js 高亮框架不兼容所致。

恩,有可能是,我在看看别的博客有没有类似的问题

配了几张图,如果不方便 PC 看,又有流量的话,可以先看图。
买合苏提
买合苏提

引用来自“xrzs”的评论

引用来自“买合苏提”的评论

不知什么原因,代码在客户端里显示都是连成一片的

显示有问题可以直接@红薯 大哥,看看是不是某个 android 客户端版本和 js 高亮框架不兼容所致。

恩,有可能是,我在看看别的博客有没有类似的问题
大数据之路
大数据之路 博主

引用来自“买合苏提”的评论

不知什么原因,代码在客户端里显示都是连成一片的

显示有问题可以直接@红薯 大哥,看看是不是某个 android 客户端版本和 js 高亮框架不兼容所致。
买合苏提
买合苏提
不知什么原因,代码在客户端里显示都是连成一片的
20.1 Shell脚本介绍;20.2 Shell脚本结构和执行;20.3date命令用法;20.4

20.1 Shell脚本介绍 1. shell是一种脚本语言 aming_linux blog.lishiming.net 2. 可以使用逻辑判断、循环等语法 3. 可以自定义函数 4. shell是系统命令的集合 5. shell脚本可以实现自动化运维...

主内安详
2018/04/18
0
0
如何在 Linux 中安装 2048 游戏

流行的移动益智游戏 2048 也可以在 Ubuntu 和 Linux 发行版上玩。啊!你甚至可以在 Linux 终端上玩 2048。如果你的生产率因为这个让人上瘾的游戏下降,请不要怪我。 早在 2014 年,2048 就是...

17%
2018/09/08
0
0
69:shell脚本介绍 | shell脚本结构 | 执行data命令用法 | shell脚本中变量

1、shell脚本介绍: shell是一种脚本语言和传统的开发语言相比,会比较简单: shell有自己语法,可以支持逻辑判断、循环等语法: 可以自定义函数,目的是减少重复的代码: shell是系统命令的集合...

芬野de博客
2018/09/21
0
0
20.1 Shell脚本介绍;20.2 Shell脚本结构和执行;20.3 date命令用法;20.

20.1 Shell脚本介绍 1. shell是一种脚本语言 aming_linux blog.lishiming.net 2. 可以使用逻辑判断、循环等语法 3. 可以自定义函数 4. shell是系统命令的集合 5. shell脚本可以实现自动化运维...

主内安详
2018/04/19
0
0
Shell编程(shell脚本介绍、shell脚本结构和执行、date命令用法、shell脚本变量)

shell脚本介绍 Shell Script,Shell脚本与Windows/Dos下的批处理相似,也就是用各类命令预先放入到一个文件中,方便一次性执行的一个程序文件,主要是方便管理员进行设置或者管理用的。但是它...

蛋黄_Yolks
2018/09/14
0
0

没有更多内容

加载失败,请刷新页面

加载更多

巨杉Tech | 微服务趋势下的数据库设计与应用简析

上周五(7月12日)巨杉数据库参与了由得到App主办八里庄技术沙龙活动,分享主题是关于分布式数据库架构与实战。 以下就是根据巨杉数据库现场分享的内容进行的分享实录整理。 巨杉数据库简介 ...

巨杉数据库
22分钟前
40
0
借助URLOS快速安装AliSQL

环境需求 最低硬件配置:1核CPU,1G内存(1+1)提示:如果你的应用较多,而主机节点的硬件配置较低,建议在部署节点时开通虚拟虚拟内存; 生产环境建议使用2G或以上内存; 推荐安装系统:Ubu...

躲猫猫_007
24分钟前
0
0
DM 源码阅读系列文章(九)shard DDL 与 checkpoint 机制的实现

作者:张学程 本文为 DM 源码阅读系列文章的第九篇,在 上篇文章 中我们详细介绍了 DM 对 online schema change 方案的同步支持,对 online schema change 同步方案以及实现细节等逻辑进行了...

TiDB
26分钟前
0
0
mysql指令

mysql指令 连接数据库 mysql -h 127.0.0.1 -u root -p -h : 数据库地址 -u : 用户名 -p : 密码 显示所有数据库 show databases; //显示所有数据库use XXX; //使用指定数据库show t...

xiaobai1315
29分钟前
0
0
C++STL常见面试题

1.C++ STL 之所以得到广泛的赞誉,也被很多人使用,不只是提供了像vector, string, list等方便的容器,更重要的是STL封装了许多复杂的数据结构算法和大量常用数据结构操作。vector封装数组,...

shzwork
40分钟前
0
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部