回到:


awk时间类内置函数

awk常用于处理日志,它支持简单的时间类操作。有下面3个内置的时间函数:

  • mktime("YYYY MM DD HH mm SS [DST]"):构建一个时间,返回这个时间点的秒级epoch,构建失败则返回-1
  • systime():返回当前系统时间点,返回的是秒级epoch值
  • strftime([format [, timestamp [, utc-flag] ] ]):将时间按指定格式转换为字符串并返回转的结果字符串

注意,awk构建时间时都是返回秒级的epoch值,表示从1970-01-01 00:00:00开始到指定时间已经过的秒数。

1
2
3
awk 'BEGIN{print systime();print mktime("2019 2 29 12 32 59")}'
1572364974
1551414779

awk mktime()

mktime在构建时间时,如果传递的DD给定的值超出了月份MM允许的天数,则自动延申到下个月。例如,指定”2019 2 29 12 30 59”中2月只有28号,所以构建出来的时间是2019-03-01 12:30:59

此外,其它部分也不限定必须在范围内。例如,2019 2 23 12 32 65的秒超出了59,那么多出来的秒数将进位到分钟。

1
2
3
4
awk 'BEGIN{
print mktime("2019 2 23 12 32 65") | "xargs -i date -d@{} +\"%F %T\""
}'
2019-02-23 12:33:05

如果某部位的数值为负数,则表示在此时间点基础上减几。例如:

1
2
3
4
5
6
7
# 2019-02-23 12:00:59基础上减1分钟
$ awk 'BEGIN{print mktime("2019 2 23 12 -1 59") | "xargs -i date -d@{} +\"%F %T\""}'
2019-02-23 11:59:59

# 2019-02-23 00:32:59基础上减1小时
$ awk 'BEGIN{print mktime("2019 2 23 -1 32 59") | "xargs -i date -d@{} +\"%F %T\""}'
2019-02-22 23:32:59

awk strftime()

1
strftime([format [, timestamp [, utc-flag] ] ])

将指定的时间戳tiemstamp按照给定格式format转换为字符串并返回这个字符串。

如果省略timestamp,则对当前系统时间进行格式化。

如果省略format,则采用PROCINFO[“strftime”]的格式,其默认格式为%a %b %e %H:%M%:S %Z %Y。该格式对应于Shell命令date的默认输出结果。

1
2
3
4
5
6
7
8
$ awk 'BEGIN{print strftime()}'
Wed Oct 30 00:20:01 CST 2014

$ date
Wed Oct 30 00:20:04 CST 2014

$ awk 'BEGIN{print strftime(PROCINFO["strftime"], systime())}'
Wed Oct 30 00:24:00 CST 2014

支持的格式包括:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
%a 星期几的缩写,如Mon、Sun Wed Fri
%A 星期几的英文全名,如Monday
%b 月份的英文缩写,如Oct、Sep
%B 月份的英文全名,如February、October
%C 2位数的世纪,例如1970对应的世纪是19
%y 2位数的年份(00–99),通过年份模以100取得,例如2019/100的余数位19
%Y 四位数年份(如2015)
%m 月份(01–12)
%j 年中天(001–366)
%d 月中天(01–31)
%e 空格填充的月中天
%H 24小时制的小时(00–23)
%I 12小时制的小时(01–12)
%p 12小时制时的AM/PM
%M 分钟数(00–59)
%S 秒数(00–60)
%u 数值的星期几(1–7),1表示星期一
%w 数值的星期几(0–6),0表示星期日
%W 年中第几周(00–53)
%z 时区偏移,格式为"+HHMM",如"+0800"
%Z 时区偏移的英文缩写,如CST

%k 24小时制的时间(0-23),1位数的小时使用空格填充
%l 12小时制的时间(1-12),1位数的小时使用空格填充
%s 秒级epoch

##### 特殊符号
%n 换行符
%t 制表符
%% 百分号%

##### 等价写法:
%x 等价于"%A %B %d %Y"
%F 等价于"%Y-%m-%d",用于表示ISO 8601日期格式
%T 等价于"%H:%M:%S"
%X 等价于"%T"
%r 12小时制的时间部分格式,等价于"%I:%M:%S %p"
%R 等价于"%H:%M"
%c 等价于"%A %B %d %T %Y",如Wed 30 Oct 2015 12:34:48 AM CST
%D 等价于"%m/%d/%y"
%h 等价于"%b"

例如:

1
2
3
4
5
6
7
8
$ awk 'BEGIN{print strftime("%s", mktime("2077 11 12 10 23 32"))}'
3403909412

$ awk 'BEGIN{print strftime("%F %T %Z", mktime("2077 11 12 10 23 32"))}'
2077-11-12 10:23:32 CST

$ awk 'BEGIN{print strftime("%F %T %z", mktime("2077 11 12 10 23 32"))}'
2077-11-12 10:23:32 +0800

awk将日期时间字符串转换为时间:strptime1()

例如:

1
2019-11-11T03:42:42+08:00

1.将日期时间字符串中的年月日时分秒全都单独保存起来
2.将年月日时分秒构建成mktime()的字符串格式”YYYY MM DD HH mm SS”
3.使用mktime()可以构建出时间点

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
function strptime(str,    time_str,arr,Y,M,D,H,m,S){
time_str = gensub(/[-T:+]/," ","g",str)
split(time_str, arr, " ")
Y = arr[1]
M = arr[2]
D = arr[3]
H = arr[4]
m = arr[5]
S = arr[6]
# mktime失败返回-1
return mktime(sprintf("%d %d %d %d %d %d", Y,M,D,H,m,S))
}

BEGIN{
str = "2019-11-11T03:42:42+08:00"
print strptime(str)
}

awk将日期时间字符串转换为时间:strptime2()

下面是更难一点的,月份使用的是英文或英文缩写,日期时间分隔符也比较特殊。

1
Sat 26. Jan 15:36:24 CET 2013
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
function strptime(str,     time_str,arr,Y,M,D,H,m,S){
time_str = gensub(/[.:]+/, " ", "g", str)
split(time_str, arr, " ")
Y = arr[8]
M = month_map(arr[3])
D = arr[2]
H = arr[4]
m = arr[5]
S = arr[6]
return mktime(sprintf("%d %d %d %d %d %d", Y,M,D,H,m,S))
}

function month_map(str, mon){
# mon = substr(str,1,3)
# return (((index("JanFebMarAprMayJunJelAugSepOctNovDec", mon)-1)/3)+1)
mon["Jan"] = 1
mon["Feb"] = 2
mon["Mar"] = 3
mon["Apr"] = 4
mon["May"] = 5
mon["Jun"] = 6
mon["Jul"] = 7
mon["Aug"] = 8
mon["Sep"] = 9
mon["Oct"] = 10
mon["Nov"] = 11
mon["Dec"] = 12
return mon[str]
}

BEGIN{
str = "Sat 26. Jan 15:36:24 CET 2013"
print strptime(str)
}