在我之前的一篇文章中提到了在C程序中如何自由的将当前或者指定的时间按照格式自由输出。如果我们要在shell中做差不多的事情呢?这篇文章就是说这个的。
本文地址:https://segmentfault.com/a/1190000006038638
date 命令输出
如果是要输出当前时间的格式的话,那么使用类似于以下格式即可
# date "+%Y-%m-%d"
上面这个命令的输出结果是:2016-07-22
。简而言之,以这个格式调用date(记得在双引号最前面加上“+
”),可以让date按照你所自定义的格式来输出当前的日期。以百分号开头的就是日期格式,剩下的字符就是你自定义的,date会将你自定义的字符原原本本的输出来。比如:
# date "+Today is %b %e, %Y. It is %l:%M:%S on %A."
Today is Jul 22, 2016. It is 8:01:57 on Friday.
#
date 格式符
date命令的格式符,参照手册页man date
,如下:
符号 | 含义 | 符号 | 含义 | 符号 | 含义 |
---|---|---|---|---|---|
年 | |||||
%C |
年份的前两位 (e.g., 20) | %y |
年份的后两位 (00..99) | %Y |
完整年份 |
月 | |||||
%b , %h
|
月份的简称 (e.g., Jan) | %B |
月份的全称 (e.g., January) | %m |
月份的数字 (01..12) |
日 | |||||
%d |
本月的几号 (e.g, 01) | %j |
每年的第几天 (001..366) | ||
星期数 | |||||
%U |
今年的第几个星期,以周日为星期初,从00开始 | ||||
%W |
今年的第几个星期,以周一为星期初,从01开始 (01..53) | ||||
星期几 | |||||
%a |
星期几的三字母简称 (e.g., Sun) | %A |
星期几的全称 (e.g., Sunday) | ||
%w |
星期几的数字,0~6,0表示周日 | %u |
星期几的数字,1~7,1表示星期一 | ||
小时 | |||||
%H |
24小时制的小时 (00..23) | %I |
12小时制的小时 (01..12) | ||
%k |
24小时制的小时 ( 0..23) | %l |
12小时制的小时 ( 1..12) | ||
分钟 | |||||
%M |
分钟 (00..59) | ||||
上下午 | |||||
%p |
AM / PM | %P |
am / pm | ||
秒数 | |||||
%S |
秒数 (00..60) | %N |
纳秒 (000000000..999999999) | ||
普通字符 | |||||
%t |
tab | %% |
%符号 | %n |
换行 |
完整/组合时间 | |||||
%c |
使用当地语言表示的日期/时间 (e.g., Thu Mar 3 23:05:25 2005) | ||||
%s |
从 1970-01-01 00:00:00 UTC 以来的秒数 | ||||
%D |
同%m/%d/%y
|
%F |
同 %Y-%m-%d
|
%T |
24小时制,同%H:%M:%S
|
%R |
24小时制的时:分,同%H:%M
|
%r |
12小时制的时间 (e.g., 11:11:04 PM) | ||
时区 | |||||
%z |
+hhmm 格式的时区 (e.g., +0800, 表示东八区) | ||||
%:z |
+hh:mm 格式的时区 | %::z |
+hh:mm:ss 格式的时区 | %Z |
时区的名称 (e.g., HKT) |
date 日期变量操作
%s 格式和 -d 参数
我们可以留意到,date命令里有一个格式符是“%s
”(注意小写),以及date的一个命令参数
-d, --date=STRING display time described by STRING, not `now'
%s seconds since 1970-01-01 00:00:00 UTC
其中%s
很好理解,这不就是和time(NULL)
一样的嘛 ~~
至于-d
,我感觉是很强大的。这里仅仅说明本文需要涉及的知识:
- 首先,
date -d ...
的输出,是带上当地时区偏移的时间(local time),这点要记住 - 其次,
date -d ...
中的参数,可以传入一个1970年1月1日以来的UTC秒数值,方法是加上@
符号。要记住,是UTC
秒数,不是本地时间
比如:
# date -d @60
Thu Jan 1 08:01:00 HKT 1970
相信这个例子已经挺清楚了,我传入time值为60(格林威治时间1970年1月1日0:01:00),然后date
返回给我一个在当时的北京时间。
时间值操作
有了1970年以来的秒数,剩下的事情就好说了。这里再给一个例子吧。我们有一个需求:
编译时,获得编译时7天后的日期,并且以那一天的0:00:00这个时间值进行操作
很简单,在Makefile里面这么写就好了:
CURR_TIMESTAMP=$(shell date "+%s") # 获取当前的时间秒数,注意是UTC时间
OFFSET_TIMESTAMP=604800 # 这是7天的秒数,我要在上面的秒数基础上做偏移
INSTALL_TIMESTAMP=$(shell echo `expr $(CURR_TIMESTAMP) + $(OFFSET_TIMESTAMP)`) # 转换成七天后的日子
...
.PHONY:install
install:
...
# 找到日期字符串进行操作
date -d "@$(INSTALL_TIMESTAMP)" "+%Y-%m-%d 0:0:0" | xargs ...
# 找到转换后的日期秒数进行操作
date -d "@$(INSTALL_TIMESTAMP)" "+%Y-%m-%d 0:0:0" | xargs -I [] date -d "[]" "+%s" | xargs ...
...
看起来比较混乱的是“找到转换后的日期秒数进行操作”,这里总共分三步:
1、date -d "@$(INSTALL_TIMESTAMP)" "+%Y-%m-%d 0:0:0"
:因为我们不需要精确的秒数,只需要0:0:0,因此首先把当前的timestamp转换成一个字符串,只是字符串我们只动态生成了“date”的部分,“time”部分被我们定死为零时。
2、xargs -I [] date -d "[]" "+%s"
:原来的那个带着“0:0:0”时间的字符串,date
是有能力识别的,这里再使用"+%s"
让date
帮我们转换成数字值
3、xargs ...
:拿到了数字值,随便你操作。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。