Конвертируйте Между форматами даты и времени С помощью Perl

StackOverflow https://stackoverflow.com/questions/2253004

Вопрос

В настоящее время мы используем сторонний API, который предоставляет datetime в следующем формате:

Sat Mar 06 09:00:00 ICST 2010
Fri Feb 19 19:30:00 JDT 2010
Fri Feb 19 19:30:00 PST 2010

Однако мы хотим сохранить эти объекты datetime в 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 в надлежащий формат и время на нашем сервере для вставки в поле datetime 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

Чтобы поддержать запрос, который вы хотите выполнить, сохраните время в формате GMT плюс смещение (т. е., с GMT по местному времени из 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.Таким образом, вы можете извлекать их из базы данных и преобразовывать в соответствующий часовой пояс по мере необходимости для отображения пользователю.

Для правильной обработки datetimes в Perl я от всей души рекомендую Дата - время suite, в котором есть анализаторы и форматеры для всех видов различных форматов ввода и вывода.

Я не уверен, что даты, перечисленные в вашем 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, соответствующее вашему синтаксису (их существует огромное количество), но в остальном нетрудно просто использовать регулярное выражение для извлечения полей даты и времени и передачи их конструктору DateTime.

Как только вы обработаете свои строки в объекты DateTime с правильно установленным временем, совсем не составит труда преобразовать их обратно в метки времени MySQL:просто используй Дата-время::Формат::MySQL:

my $string = DateTime::Format::MySQL->format_datetime($dt);

Попробуйте использовать Дата - время модуль.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top