在Bash中解析日期

时间:2009-12-03 20:19:56

标签: bash date parsing

如何用bash解析日期,将不同的字段(年,月,日,小时,分钟,秒)分成不同的变量?

日期格式为:YYYY-MM-DD hh:mm:ss

10 个答案:

答案 0 :(得分:63)

它必须是bash吗?您可以使用GNU coreutils /bin/date二进制文件进行多次转换:

 $ date --date="2009-01-02 03:04:05" "+%d %B of %Y at %H:%M and %S seconds"
 02 January of 2009 at 03:04 and 05 seconds

解析给定日期并以所选格式显示。您可以随意根据自己的需要进行调整。

答案 1 :(得分:28)

这很简单,只需将你的破折号和冒号转换为空格(无需更改IFS)并在一行中使用'read':

read Y M D h m s <<< ${date//[-:]/ }

例如:

$ date=$(date +'%Y-%m-%d %H:%M:%S')
$ read Y M D h m s <<< ${date//[-: ]/ }
$ echo "Y=$Y, m=$m"
Y=2009, m=57

答案 2 :(得分:14)

我有不同的输入时间格式,因此这里有一个更灵活的解决方案。

在BSD / macOS

中转换日期
date -jf in_format [+out_format] in_date

格式使用strftime(参见man strftime)。

对于给定的输入格式YYYY-MM-DD hh:mm:ss

$ date -jf '%Y-%m-%d %H:%M:%S' '2017-05-10 13:40:01'
Wed May 10 13:40:01 PDT 2017

要将它们读入单独的变量,我采用NVRAM的想法,但允许您使用任何strftime格式:

$ date_in='2017-05-10 13:40:01'

$ format='%Y-%m-%d %H:%M:%S'

$ read -r y m d H M S <<< "$(date -jf "$format" '+%Y %m %d %H %M %S' "$date_in")"

$ for var in y m d H M S; do echo "$var=${!var}"; done
y=2017
m=05
d=10
H=13
M=40
S=01

(在脚本中,always使用read -r。)

在我的情况下,我想在时区之间进行转换(请参阅/usr/share/zoneinfo目录以获取区域名称):

$ format=%Y-%m-%dT%H:%M:%S%z

$ TZ=UTC date -jf $format +$format 2017-05-10T02:40:01+0200
2017-05-10T00:40:01+0000

$ TZ=America/Los_Angeles date -jf $format +$format 2017-05-10T02:40:01+0200
2017-05-09T17:40:01-0700

在GNU / Linux

中转换日期
  

在Mac上,您可以使用dategdate的GNU版本安装为brew install coreutils

date [+out_format] -d in_date

out_format使用strftime(参见man strftime)。

在GNU coreutils&#39; date命令,没有办法显式设置输入格式,因为它试图自己找出输入格式,而东西通常只是起作用。 (有关详细信息,请阅读coreutils: Date input formats上的手册。)

例如:

$ date '+%Y %m %d %H %M %S' -d '2017-05-10 13:40:01'
2017 05 10 13 40 01

要将它们读入单独的变量,请通过将括号中的命令替换为GNU版本来修改Mac部分中的命令。

要在时区之间进行转换(请参阅/usr/share/zoneinfo目录中的区域名称),您可以在输入字符串中指定TZ="America/Los_Angeles"。注意区域名称周围的文字"字符和in_date之前的空格字符:

TZ=out_tz date [+out_format] 'TZ="in_tz" 'in_date

例如:

$ format='%Y-%m-%d %H:%M:%S%z'

$ TZ=America/Los_Angeles date +"$format" -d 'TZ="UTC" 2017-05-10 02:40:01'
2017-05-09 19:40:01-0700

$ TZ=UTC date +"$format" -d 'TZ="America/Los_Angeles" 2017-05-09 19:40:01'
2017-05-10 02:40:01+0000

GNU日期还了解时区的小时偏移量:

$ TZ=UTC date +"$format" -d '2017-05-09 19:40:01-0700'
2017-05-10 02:40:01+0000

答案 3 :(得分:7)

$ t='2009-12-03 12:38:15'
$ a=(`echo $t | sed -e 's/[:-]/ /g'`)
$ echo ${a[*]}
2009 12 03 12 38 15
$ echo ${a[3]}
12

答案 4 :(得分:5)

数组方法可能更好,但这是你特别要求的:

IFS=" :-"
read year month day hour minute second < <(echo "YYYY-MM-DD hh:mm:ss")

答案 5 :(得分:3)

Pure Bash:

date="2009-12-03 15:35:11"
saveIFS="$IFS"
IFS="- :"
date=($date)
IFS="$saveIFS"
for field in "${date[@]}"
do
    echo $field
done

2009
12
03
15
35
11

答案 6 :(得分:2)

而不是使用shell脚本,无论你需要什么,都可以在脚本本身中加入:

a=date +%Y 
b=date +%S
c=date +%H

将是一年 b将是秒 c将是几个小时。等等。

答案 7 :(得分:2)

OP问题的另一个解决方案:

IFS=' -:' read y m d h m s<<<'2014-03-26 16:36:41'

使用BSD date和GNU date将日期转换为另一种格式:

$ LC_ALL=C date -jf '%a %b %e %H:%M:%S %Z %Y' 'Wed Mar 26 16:36:41 EET 2014' +%F\ %T
2014-03-26 16:36:41
$ gdate -d 'Wed Mar 26 16:36:41 EET 2014' +%F\ %T
2014-03-26 16:36:41

即使在非英语语言环境中,GNU date也会识别WedMar,但BSD date则不会。

将自纪元以来的秒数转换为GNU日期和BSD日期的日期和时间:

$ gdate -d @1234567890 '+%F %T'
2009-02-14 01:31:30
$ date -r 1234567890 '+%F %T'
2009-02-14 01:31:30

使用POSIX shell,POSIX awk,GNU date和BSD date将秒转换为小时,分钟和秒:

$ s=12345;printf '%02d:%02d:%02d\n' $((s/3600)) $((s%3600/60)) $((s%60))
05:25:45
$ echo 12345|awk '{printf "%02d:%02d:%02d\n",$0/3600,$0%3600/60,$0%60}'
05:25:45
$ gdate -d @12345 +%T
05:25:45
$ date -r 12345 +%T
05:25:45

将秒数转换为天,小时,分钟和秒:

$ t=12345678
$ printf '%d:%02d:%02d:%02d\n' $((t/86400)) $((t/3600%24)) $((t/60%60)) $((t%60))
142:21:21:18

答案 8 :(得分:1)

另一个纯粹的bash

$ d="2009-12-03 15:35:11"
$ d=${d//[- :]/|}
$ IFS="|"
$ set -- $d
$ echo $1
2009
$ echo $2
12
$ echo $@
2009 12 03 15 35 11

答案 9 :(得分:0)

你尝试过使用剪切吗? 这样的事情: DAYOFWEEK = date|cut -d" " -f1