我使用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总是指小时数)
答案 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