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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/20691852/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-18 09:02:44  来源:igfitidea点击:

linux bash - Parse date in custom format

linuxbashparsingdate

提问by BrainStone

I have a date in a the %cformat (could be any other)and I need to use it in the date command. %cis NOT the American format. It is the German one because it's a German server. This also did not work properly on an American server. (Locales set to German or American)

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

This does not work (error included):

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

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“

(date: ungültiges Datum ?Do 19 Dez 2013 22:33:28 CET“ = date: invalid date ?Do 19 Dez 2013 22:33:28 CET“)

(日期:ungültiges Datum?Do 19 Dez 2013 22:33:28 CET“= date: invalid date ?Do 19 Dez 2013 22:33:28 CET“

The difficulty is that I don't know which locale or even whci dateformat will be used later since the user can set their own format. So a simple specific parsing solution ist not really going to work!

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

But how do I do it?

但是我该怎么做呢?

To gerneralize the issue:

为了概括这个问题:

If I have a date format format1(which could be any or at least one that can be reversed)I can use date to get a formatted date. But if I want to format it to another date (format2) how do I do it?
Any solution using anything else than the coreutils is pointless since I am trying to develop a bash script for as many unix machines as possible.

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

DATE=$(date "+$format1")

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

This is needed because I have a command which the user can give a date format. This date string is going to be displayed. But in a later step I need to convert this date string into another fixed one. I can manipulate the whcih format the command will get and I can maniplulate the output (or what the user will see).
I cannot run the command twice because it is very time consuming.

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



Update:

更新:

I have found something like a solution:

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

# 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")

This is working and might be helpful to others. So I will share this with you.

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

采纳答案by claj

Why don't you store the time as unixtime (ie milliseconds since 1st of january 1970) Like 1388198714?

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

The requested exercise in trying to parse all date formats from all around the world as a one shot bash script without reasonable dependecies is slightly ridiculous.

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

回答by Gavin Smith

Not possible with --dateas of GNU coreutils 8.22. From the date manual:

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

‘-d datestr'

‘--date=datestr'

Display the date and time specified in datestr instead of the current date and time. datestr can be in almost any common format. It can contain month names, time zones, ‘am' and ‘pm', ‘yesterday', etc. For example, --date="2004-02-27 14:19:13.489392193 +0530" specifies the instant of time that is 489,392,193 nanoseconds after February 27, 2004 at 2:19:13 PM in a time zone that is 5 hours and 30 minutes east of UTC.

Note: input currently must be in locale independent format. E.g., the LC_TIME=C below is needed to print back the correct date in many locales:

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

'-d 日期字符串'

'--date=datestr'

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

注意:当前输入必须是独立于语言环境的格式。例如,需要下面的 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

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

Note it says that the input format cannot be in a locale-specific format.

请注意,它表示输入格式不能是特定于语言环境的格式。

There may be other libraries or programs that would recognize more date formats, but for a given date format it would not be difficult to write a short program to convert it to something date recognizes (for example, with Perl or awk).

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

回答by Dmitry Alexandrov

You may use libdatetime-format-flexible-perl.

您可以使用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

Default output will be 2013-12-22T07:29:35, but since $dateis not a regular string but object, you can do something like this:

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

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

Also datebehavior probably should be considered as a bug. I think so, because date in the same format but in russian is parsed correctly.

此外date行为也许应该被看作是一个错误。我认为是这样,因为格式相同但俄语的日期被正确解析。

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

回答by Donovan

If you meant the formatting is wrong, I thinkwhat you want is:

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

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

note the lowercase %dand %m.

注意小写%d%m

Locally, this is what I get:

在本地,这就是我得到的:

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