日期时间格式之间进行转换使用Perl
-
20-09-2019 - |
题
我们目前正在使用第三方API,在下面的格式提供的日期时间:
Sat Mar 06 09:00:00 ICST 2010
Fri Feb 19 19:30:00 JDT 2010
Fri Feb 19 19:30:00 PST 2010
然而,我们希望在MySQL这些datetime对象存储在一个标准日期时间字段,需要下面的格式:
YYYY-MM-DD HH:MM:SS
现在,让我们用下面的代码被报告错误某些时区,如KDT,JDT和ICST:
use Date::Manip;
use DateTime;
use DateTime::Format::DateManip;
my $date = ParseDate($time);
$date = DateTime::Format::DateManip->parse_datetime($date);
eval{ $time = $date->strftime("%Y-%m-%d %H:%M:%S"); };
你能不能推荐一个更好的实施Perl代码上面的datetime对象从API转换到我们的服务器上正确的格式和时间被插入到一个MySQL的时间字段?
在此先感谢您的帮助和建议!
解决方案
在GMT内部存储的时间。做GMT所有操作。然后,在最后时刻,就像你要显示的结果给用户,然后的转换到用户的本地时间。
我建议使用日期::解析,但你“将不得不增加其时区偏移,因为它目前还没有印度支那夏令时和日本夏令时间,例如。
#! /usr/bin/perl
use warnings;
use strict;
use Date::Format;
use Date::Parse;
# add timezone offsets
$Time::Zone::Zone{icst} = +7*3600;
$Time::Zone::Zone{jdt} = +9*3600;
while (<DATA>) {
chomp;
warn("$0: failed conversion for $_\n"), next
unless defined(my $time_t = str2time $_);
my @t = gmtime($time_t);
print $_, " => ", strftime("%Y-%m-%d %H:%M:%S", @t), "\n";
}
__DATA__
Sat Mar 06 09:00:00 ICST 2010
Fri Feb 19 19:30:00 JDT 2010
Fri Feb 19 19:30:00 PST 2010
输出:
Sat Mar 06 09:00:00 ICST 2010 => 2010-03-06 02:00:00 Fri Feb 19 19:30:00 JDT 2010 => 2010-02-19 10:30:00 Fri Feb 19 19:30:00 PST 2010 => 2010-02-20 03:30:00
要支持您想查询,存储在格林尼治标准时间加上时间偏移量(即的,从格林尼治标准时间从API的本地时间)。请注意,下面的代码假定如果str2time
可以分析给定的时间,strptime
也可以。循环改变到
my @dates;
while (<DATA>) {
chomp;
warn("$0: failed conversion for $_\n"), next
unless defined(my $time_t = str2time $_);
my $zone = (strptime $_)[-1];
my @t = gmtime($time_t);
push @dates => [ strftime("%Y-%m-%d %H:%M:%S", @t)
, sprintf("%+03d:%02d",
int($zone / 3600),
int($zone % 3600) / 60)
, $_
];
}
使用所收集的时间,呈现为SQL:
print "DROP TABLE IF EXISTS dates;\n",
"CREATE TABLE dates (date DATETIME, offset CHAR(6));\n",
"INSERT INTO dates (date,offset) VALUES\n",
join(",\n\n" =>
map(" -- $_->[2]\n" .
" ('$_->[0]','$_->[1]')", @dates)),
";\n",
"SELECT CONVERT_TZ(date,'+00:00',offset) FROM dates;\n"
的输出是
DROP TABLE IF EXISTS dates;
CREATE TABLE dates (date DATETIME, offset CHAR(6));
INSERT INTO dates (date,offset) VALUES
-- Sat Mar 06 09:00:00 ICST 2010
('2010-03-06 02:00:00','+07:00'),
-- Fri Feb 19 19:30:00 JDT 2010
('2010-02-19 10:30:00','+09:00'),
-- Fri Feb 19 19:30:00 PST 2010
('2010-02-20 03:30:00','-08:00');
SELECT CONVERT_TZ(date,'+00:00',offset) FROM dates;
和我们可以管它mysql
:
$ ./prog.pl | mysql -u username -D dbname CONVERT_TZ(date,'+00:00',offset) 2010-03-06 09:00:00 2010-02-19 19:30:00 2010-02-19 19:30:00
其他提示
在存储日期,你应该总是将它们存储在UTC。这样一来,就可以从数据库中提取它们,并将它们转换为适当的时区所必需的显示给用户。
有关在Perl妥善处理日期时间,我尽情地推荐日期时间套件,它具有解析器并为各种不同的输入和输出格式格式化。
我不知道,如果在你的OP所列日期的标准格式,但如果没有,那将是很容易从他们构建一个DateTime格式:
my $str = 'Sat Mar 06 09:00:00 ICST 2010';
my ( $month, $day, $hour, $min, $sec, $tz, $year ) = ( $str =~ m{\w{3}\s(\w{3})\s(\d{2})\s(\d{2}):(\d{2}):(\d{2})\s(\w+)\s(\d{4})} );
my $dt = DateTime->new( year => $year, month => $month, day => $day,
hour => $hour, minute => $min, second => $sec,
time_zone => $tz );
您可以再使用日期时间::格式:: MySQL的将日期转换到MySQL兼容日期时间。
您可能不得不明确地告诉该时区()你正在处理DateTime构造,由于三,四字母代码不是唯一的不规范。
我建议开始日期时间::时区和可能构造新类型为你的时区,如果你不能找到你所寻找的列表。您还可以找到符合你的语法(有他们的一个巨大的数字)日期时间格式化,否则它不是很难简单地使用正则表达式来提取日期和时间字段,并传递给一个DateTime构造函数。
一旦你得到了你的字符串解析成datetime对象与时间设置正确,这是一点问题都没有将它们转换回来了到MySQL时间戳:只要使用的日期时间::格式:: MySQL的:
my $string = DateTime::Format::MySQL->format_datetime($dt);
尝试使用的DateTime 模块。