linux bash - 以自定义格式解析日期

时间:2013-12-19 21:16:52

标签: linux bash parsing date

我有一个%c格式的日期(可能是任何其他格式),我需要在date命令中使用它。 %c不是美国格式。它是德国人,因为它是德国服务器。这在美国服务器上也无法正常工作。 (区域设置为德语或美国语)

这不起作用(包括错误):

user@server:~$ NOW=$(date +%c); echo $NOW
Do 19 Dez 2013 22:33:28 CET
user@server:~$ date --date="$NOW" +%d/%m/%Y
date: ungültiges Datum „Do 19 Dez 2013 22:33:28 CET“

(日期:ungültigesGeatum“Do 19 Dez 2013 22:33:28 CET”= date: invalid date „Do 19 Dez 2013 22:33:28 CET“

困难在于我不知道以后会使用哪种语言环境甚至whci dateformat,因为用户可以设置自己的格式。因此,一个简单的特定解析解决方案并不能真正起作用!

但我该怎么做?

将问题推向一致:

如果我有一个日期格式format1 (可以是任何或至少可以反转的那个)我可以使用日期来获取格式化日期。但是,如果我想将其格式化为另一个日期(format2),我该怎么做? 使用除coreutils以外的任何其他解决方案是没有意义的,因为我正在尝试为尽可能多的unix机器开发一个bash脚本。

DATE=$(date "+$format1")

date --date="$DATE" "+$format2" # Error in most cases!

这是必需的,因为我有一个用户可以给出日期格式的命令。将显示此日期字符串。但在后面的步骤中,我需要将此日期字符串转换为另一个固定字符串。我可以操作命令将获得的whcih格式,我可以操作输出(或用户将看到的内容)
我无法运行该命令两次,因为它非常耗时。


更新

我找到了类似解决方案的东西:

# Modify $user_format so it can be parsed later
user_format="$user_format %s"

# Time consuming command which will print a date in the given format
output=$(time_consuming_command params "$user_format" more params)

# This will only display what $user_format used to be
echo ${output% *}

# A simple unix timestamp parsing ("${output##* }" will only return the timestamp)
new_formated_date=$(date -d "1970-01-01 ${output##* } sec UTC" "+$new_format")

这是有效的,可能对其他人有帮助。所以我会和你分享。

4 个答案:

答案 0 :(得分:8)

从GNU coreutils 8.22开始,--date不可能。从日期手册:

  

' - d datestr'

     

“ - 日期= datestr”

     

显示在datestr中指定的日期和时间,而不是当前   日期和时间。 datestr几乎可以是任何常见格式。它可以   包含月份名称,时区,“上午”和“下午”,“昨天”等   例如, - date =“2004-02-27 14:19:13.489392193 +0530”指定   2月27日之后的时间是489,392,193纳秒,   2004年2:19:13 PM在东部5小时30分钟的时区   UTC。

     

注意:输入当前必须采用与语言环境无关的格式。例如,   需要LC_TIME = C以打印许多正确的日期   区域设置:

date -d "$(LC_TIME=C date)"

http://www.gnu.org/software/coreutils/manual/html_node/Options-for-date.html#Options-for-date

请注意,输入格式不能采用特定于语言环境的格式。

可能有其他库或程序可以识别更多的日期格式,但对于给定的日期格式,编写一个简短的程序将其转换为日期识别的东西并不困难(例如,使用Perl或awk)。

答案 1 :(得分:5)

为什么不将时间存储为unixtime(即1970年1月1日以来的毫秒数),如1388198714

尝试解析来自世界各地的所有日期格式作为一次性bash脚本而没有合理依赖的请求练习有点荒谬。

答案 2 :(得分:1)

您可以使用libdatetime-format-flexible-perl

#!/usr/bin/perl
use DateTime::Format::Flexible;
my $date_str = "So 22 Dez 2013 07:29:35 CET";
$parser = DateTime::Format::Flexible->new;
my $date = $parser->parse_datetime($date_str);
print $date

默认输出为2013-12-22T07:29:35,但由于$date不是常规字符串而是对象,您可以执行以下操作:

printf '%02d.%02d.%d', $date->day, $date->month, $date->year;

date行为也可能被认为是一个错误。我是这么认为的,因为日期格式相同,但是俄语正确解析。

$ export LC_TIME=ru_RU.UTF-8
$ NOW="$(date "+%c")"
$ date --date="$NOW" '+%d.%m.%Y'
22.12.2013

答案 3 :(得分:0)

如果您认为格式错误,我认为您想要的是:

NOW=$(date +%c)
date --date="$NOW" +%d/%m/%Y

请注意小写%d%m

在本地,这是我得到的:

root@server2:~# NOW=$(date +%c)
root@server2:~# date --date="$NOW" +%d/%m/%Y
19/12/2013