Perl基于文本匹配转换时间

时间:2016-01-06 13:41:33

标签: json perl

我使用Perl读取json文件中的变量并相应地处理它们。我需要帮助的地方是当我从文件中读取一段时间,如下所示:

"StartTime":"2015-07-08T03:38:08Z",
"EndTime":"2015-07-10T03:38:08Z"

这很容易处理,但这里有一个棘手的部分:

"StartTime":"now-10",
"EndTime":"now+10"

我有一个函数从json文件中获取这些变量,并检查字符串是否包含单词" now"。但在那之后,我不知道该怎么做。我试图转换"现在"当地时间(时间),但它快速变得丑陋。这是我的代码:

    my $_StartTime = getFromJson("StartTime");
    my $_EndTime = getFromJson("EndTime");

    if($_StartTime =~ /now/) {
        (my $sec, my $min, my $hour, my $mday, my $mon, my $year, my $wday, my $yday, my $isdst) = localtime(time);
        my $now = sprintf("%04d-%02d-%02dT%02d:%02d:%02dZ", $year+1900, $mon+1, $mday, $hour, $min, $sec);
    }
    # end time is handled the same way

我是否在正确的轨道上?如果是这样,我怎样才能添加" +/- 10"在"现在"之后在文件中? (注意:假设+/- 10总是指小时数)

4 个答案:

答案 0 :(得分:3)

在这种情况下,CPAN上有很多很好的模块可以提供帮助。你不需要使用它们,但它仍然值得了解它们。

首先,JSON可能会在解析JSON文件时让您的生活更轻松,因为它有简单的方法将JSON转换为本机Perl结构。

其次,DateTime模块系列可以使解析和操作日期变得更容易。具体而言,您可以使用DateTime::Format::ISO8601来解析日期,而不是使用sprintf

my $dt = DateTime::Format::ISO8601->parse_datetime( $_StartTime );

DateTime具有访问日,年,月等的方法。这些内容记录在主模块页面上。

然后,您可以保留now输入的特殊情况,并执行以下操作:

    # work out if it's addition or subtraction and grab the amount
    # then use the appropriate DateTime function:

    my $dt = DateTime->now()->add( seconds => 10 );
    # or 
    my $dt = DateTime->now()->subtract( seconds => 10 );

答案 1 :(得分:2)

使用POSIX::strftime会让您的生活更轻松。

use POSIX 'strftime';

my @test_times = qw[now+10 now now-10];

foreach my $start_time (@test_times) {
  if (my ($adjust) = $start_time =~ /^now([-+]\d+)?/) {
    $adjust //= 0;
    $adjust *= 60 * 60; # Convert hours to seconds
    my $time = strftime '%Y-%m-%dT%H:%M:%SZ', gmtime(time + $adjust);
    say $time;
  }
}

进一步思考,我想我更愿意使用Time::Piece。原则几乎相同。

use Time::Piece;

my @test_times = qw[now+10 now now-10];

foreach my $start_time (@test_times) {
  if (my ($adjust) = $start_time =~ /^now([-+]\d+)?/) {
    $adjust //= 0;
    $adjust *= 60 * 60; # Convert hours to seconds
    my $time = gmtime(time + $adjust);
    say $time->strftime('%Y-%m-%dT%H:%M:%SZ');
  }
}

答案 2 :(得分:1)

我会将其更改为:

my $_StartTime = getFromJson("StartTime");
my $_EndTime = getFromJson("EndTime");

if($_StartTime =~ s/now//) {
    my $time = time;
    if ($_StartTime =~ /^([-+]?)([0-9]+)/) {
        my ($sign, $number) = ($1, $2);
        $time += ($sign eq '-' ? -1 : 1) * $number * 3_600;
    }

    (my $sec, my $min, my $hour, my $mday, my $mon, my $year, my $wday, my $yday, my $isdst) = localtime($rime);
    $_StartTime = sprintf("%04d-%02d-%02dT%02d:%02d:%02dZ", $year+1900, $mon+1, $mday, $hour, $min, $sec);
}

答案 3 :(得分:1)

您几乎没有提供有关原始数据格式的信息,以及您希望从中获得的结果。我假设你展示的代码是将用now格式化的时间转换为你认可的时间,以便你可以从那里继续。但最好在一个地方处理这两种格式,以生成相同的最终结果,而不管输入

该程序使用虚构的JSON数据结构并处理其中的所有元素。核心是使用Time::Piece模块,它将为您解析和格式化时间并进行日期/时间算术

我已经封装了在子例程convert_time中处理两种时间值的代码,该子例程返回Time::Piece个对象。代码只使用模块自己的stringify方法使值可读,但您可以使用对象的方法生成任何形式的字符串

use strict;
use warnings 'all';
use feature 'say';

use JSON 'from_json';
use Time::Piece;
use Time::Seconds 'ONE_HOUR';


my $json = <<END;
[
    {
        "StartTime": "2015-07-08T03:38:08Z",
        "EndTime":   "2015-07-10T03:38:08Z"
    },
    {
        "StartTime": "now-10",
        "EndTime":   "now+10"
    }
]
END

my $data = from_json($json);

for my $item ( @$data ) {

    for my $key ( keys %$item ) {

        my $time = $item->{$key};

        say "$key $time";
        my $ans = convert_time($time);

        print $ans, "\n\n";
    }
}


sub convert_time {

    my ($time) = @_;

    if ( $time =~ /now([+-]\d+)/ ) {
        return localtime() + $1 * ONE_HOUR;
    }
    else {
        return Time::Piece->strptime($time, '%Y-%m-%dT%H:%M:%SZ');
    }

}

输出

StartTime 2015-07-08T03:38:08Z
Wed Jul  8 03:38:08 2015

EndTime 2015-07-10T03:38:08Z
Fri Jul 10 03:38:08 2015

StartTime now-10
Wed Jan  6 05:57:04 2016

EndTime now+10
Thu Jan  7 01:57:04 2016