我们目前正在使用第三方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 模块。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top