将日期/时间作为(年,月,日,小时,分钟,秒)的数组,如何将其转换为纪元时间,即1970-01-01 00:00以来的秒数:00 GMT?
奖金问题:如果将日期/时间作为字符串给出,您将如何首先将其解析为(y,m,d,h,m,s)数组?
答案 0 :(得分:34)
如果您正在使用DateTime模块,则可以在DateTime对象上调用epoch()方法,因为这就是您认为的unix时间。
使用DateTimes可以轻松地从纪元转换为日期对象。
另外,localtime和gmtime会将一个纪元转换为一个包含日月和年的数组,来自Time::Local module的timelocal和timegm会反过来,转换一个时间元素数组(秒,分钟,......,日,月等)进入一个时代。
答案 1 :(得分:19)
这是获得unix时间的最简单方法:
use Time::Local;
timelocal($second,$minute,$hour,$day,$month-1,$year);
注意参数的相反顺序,1月是0月。 有关更多选项,请参阅CPAN中的DateTime模块。
关于解析,请参阅CPAN中的Date::Parse模块。如果你真的需要对日期解析感兴趣,那么Date::Manip可能会有所帮助,尽管它自己的文档警告你远离它,因为它带有很多包袱(它知道像常见的商业假期等)和其他解决方案要快得多。
如果你碰巧知道你将要解析的日期/时间的格式,那么一个简单的正则表达式就足够了,但你可能最好使用合适的CPAN模块。例如,如果您知道日期将始终采用YMDHMS顺序,请使用CPAN模块DateTime::Format::ISO8601。
为了我自己的参考,如果没有别的,下面是我用于应用程序的函数,我知道日期将始终按YMDHMS顺序,全部或部分“HMS”部分是可选的。它接受任何分隔符(例如,“2009-02-15”或“2009.02.15”)。它返回相应的unix时间(自1970-01-01 00:00:00 GMT以来的秒数)或-1如果它无法解析它(这意味着你最好确定你永远不会合法地需要解析日期1969- 12-31 23:59:59)它还假设两位数年份XX到“69”表示“20XX”,否则“19XX”(例如,“50-02-15”表示2050-02-15但“75-02-15”表示1975- 02-15)。
use Time::Local;
sub parsedate {
my($s) = @_;
my($year, $month, $day, $hour, $minute, $second);
if($s =~ m{^\s*(\d{1,4})\W*0*(\d{1,2})\W*0*(\d{1,2})\W*0*
(\d{0,2})\W*0*(\d{0,2})\W*0*(\d{0,2})}x) {
$year = $1; $month = $2; $day = $3;
$hour = $4; $minute = $5; $second = $6;
$hour |= 0; $minute |= 0; $second |= 0; # defaults.
$year = ($year<100 ? ($year<70 ? 2000+$year : 1900+$year) : $year);
return timelocal($second,$minute,$hour,$day,$month-1,$year);
}
return -1;
}
答案 2 :(得分:17)
要解析日期,请在CPAN中查看Date::Parse。
答案 3 :(得分:7)
$ENV{TZ}="GMT";
POSIX::tzset();
$time = POSIX::mktime($s,$m,$h,$d,$mo-1,$y-1900);
答案 4 :(得分:7)
我知道这是一个老问题,但我想我会提供另一个答案。
Time::Piece
是Perl 5.9.5的核心
这允许通过strptime
方法以任意格式解析时间。
e.g:
my $t = Time::Piece->strptime("Sunday 3rd Nov, 1943",
"%A %drd %b, %Y");
有用的部分是 - 因为它是一个重载的对象,你可以用它进行数值比较。
e.g。
if ( $t < time() ) { #do something }
或者如果您在字符串上下文中访问它:
print $t,"\n";
你得到:
Wed Nov 3 00:00:00 1943
有一堆访问器方法允许一些其他有用的基于时间的变换。 https://metacpan.org/pod/Time::Piece
答案 5 :(得分:6)
use Date::Manip;
$string = '18-Sep-2008 20:09'; # or a wide range of other date formats
$unix_time = UnixDate( ParseDate($string), "%s" );
编辑:
Date :: Manip很大很慢,但解析非常灵活,而且它是纯粹的perl。如果您在编写代码时匆忙,请使用它,并且您知道在运行代码时不会匆忙。
e.g。在启动时使用它来解析命令行选项,但不要使用它在繁忙的Web服务器上解析大量数据。
(感谢下面第一条评论的作者)
答案 6 :(得分:2)
我最喜欢的日期时间解析器是DateTime::Format::ISO8601一旦你有了这个工作,你将拥有一个DateTime对象,可以使用epoch()
轻松转换为纪元秒答案 7 :(得分:2)
可能是“有多种方式去做”的更好例子之一,无论是否有CPAN的帮助。
如果您可以控制作为'日期/时间'传递的内容,我建议使用特定的Date :: Time :: Format子类或使用DateTime来DateTime路由:: Format :: Strptime如果没有人支持您古怪的日期格式(有关详细信息,请参阅datetime FAQ)。一般来说,如果你想对结果做任何严肃的事情,Date :: Time就是要走的路:CPAN上的几个课程都非常具有肛门保持性和准确性。
如果你期待奇怪的自由形式的东西,把它扔到Date::Parse的str2time()方法,这将获得一个秒 - 自 - 纪元的价值,然后你可以有你的邪恶的方式,没有Date::Manip的开销。
答案 8 :(得分:2)
CPAN上有许多日期操作模块。我特别喜欢的是DateTime,您可以使用strptime modules以任意格式解析日期。 CPAN上还有许多DateTime :: Format模块用于处理专门的日期格式,但strptime是最通用的。
答案 9 :(得分:2)
有待进一步参考,可以应用于例如!#/bin/sh
脚本的单行内容。
EPOCH="`perl -e 'use Time::Local; print timelocal('${SEC}','${MIN}','${HOUR}','${DAY}','${MONTH}','${YEAR}'),\"\n\";'`"
请记住避免八进制值!
答案 10 :(得分:0)
我使用的是一个非常老的操作系统,我不敢在其上安装库,所以这就是我所使用的;
%MonthMatrix=("Jan",0,"Feb",31,"Mar",59,"Apr",90,"May",120,"Jun",151,"Jul",181,"Aug",212,"Sep",243,"Oct",273,"Nov",304,"Dec",334);
$LeapYearCount=int($YearFourDigits/4);
$EpochDayNumber=$MonthMatrix{$MonthThreeLetters};
if ($LeapYearCount==($YearFourDigits/4)) { if ($EpochDayNumber<32) { $EpochDayNumber--; }}
$EpochDayNumber=($YearFourDigits-1970)*365+$LeapYearCount+$EpochDayNumber+$DayAsNumber-493;
$TimeOfDaySeconds=($HourAsNumber*3600)+($MinutesAsNumber*60)+$SecondsAsNumber;
$ActualEpochTime=($EpochDayNumber*86400)+$TimeOfDaySeconds;
输入变量是;
$MonthThreeLetters
$DayAsNumber
$YearFourDigits
$HourAsNumber
$MinutesAsNumber
$SecondsAsNumber
...这应该是不言自明的。
输入变量当然采用GMT(UTC)。输出变量为“ $ ActualEpochTime”。 (通常,我只需要$ EpochDayNumber,这就是为什么那个多余的变量独立存在的原因。)
我使用这个公式多年,没有错误。
答案 11 :(得分:-3)
过滤器在标准输入上转换为标准输出的秒数以来,以各种ISO相关格式转换任何日期(以及在阅读Mighty Kuhn的the writings之后还有谁使用?)可能有助于说明这两个部分:
martind@whitewater:~$ cat `which isoToEpoch`
#!/usr/bin/perl -w
use strict;
use Time::Piece;
# sudo apt-get install libtime-piece-perl
while (<>) {
# date --iso=s:
# 2007-02-15T18:25:42-0800
# Other matched formats:
# 2007-02-15 13:50:29 (UTC-0800)
# 2007-02-15 13:50:29 (UTC-08:00)
s/(\d{4}-\d{2}-\d{2}([T ])\d{2}:\d{2}:\d{2})(?:\.\d+)? ?(?:\(UTC)?([+\-]\d{2})?:?00\)?/Time::Piece->strptime ($1, "%Y-%m-%d$2%H:%M:%S")->epoch - (defined ($3) ? $3 * 3600 : 0)/eg;
print;
}
martind@whitewater:~$
答案 12 :(得分:-4)
如果您只是在寻找命令行实用程序(即,不会从其他函数调用的东西),请尝试使用此脚本。它假定存在GNU日期(存在于几乎任何Linux系统上):
#! /usr/bin/perl -w
use strict;
$_ = (join ' ', @ARGV);
$_ ||= <STDIN>;
chomp;
if (/^[\d.]+$/) {
print scalar localtime $_;
print "\n";
}
else {
exec "date -d '$_' +%s";
}
以下是它的工作原理:
$ Time now
1221763842
$ Time yesterday
1221677444
$ Time 1221677444
Wed Sep 17 11:50:44 2008
$ Time '12:30pm jan 4 1987'
536790600
$ Time '9am 8 weeks ago'
1216915200