英文:
Convert UTC to Location specific time in Perl
问题
我已经编写了一个脚本,它以UTC时间作为输入,并应该打印特定位置(站点ID)的时间。站点ID目前已硬编码,根据站点而变化。
以下是我的脚本:
#!/usr/bin/env perl5.34.0
use strict; use warnings;
use Date::Parse;
use DateTime;
use Time::Piece qw( localtime );
use POSIX 'strftime';
use Date::Format qw(!strftime);
my $site_id = 1;
my %time_zone_hash = (
1 => 'Europe/London', #伦敦 (GMT+0)
2 => 'Asia/Kolkata', #班加罗尔 (GMT+05:30)
);
my $utc_now = strftime('%Y-%m-%d %H:%M:%S', gmtime());
print "UTC:$utc_now\n";
my $site_time = convertSiteTime($site_id, $utc_now);
print "site_time=$site_time\n";
print time2str('%Y-%m-%d %H:%M:%S', $site_time)."\n";
sub convertSiteTime {
my $id = shift;
my $time_str = shift;
my $epoch_time = str2time($time_str);
if (!$epoch_time) {
print "$time_str is not a valid date. Please provide a valid date.\n";
exit(1);
}
my $dt = DateTime->from_epoch(epoch => $epoch_time);
$dt->set_time_zone($time_zone_hash{$id});
return $dt->epoch();
}
输出:
UTC:2023-07-20 09:19:16
site_time=1689824956
2023-07-20 09:19:16
它为UTC和站点时间提供相同的结果。在这种情况下,站点时间应该是 2023-07-20 10:19:16
。
请问有人能告诉我脚本有什么问题。另外,我的系统(环境)设置为UTC时间。
英文:
I have written a script, which takes UTC time as an input and should print location specific (site id) time. The site id is been hard-coded as of now, which will vary according to the site.
Below is my script:
#!/usr/bin/env perl5.34.0
use strict; use warnings;
use Date::Parse;
use DateTime;
use Time::Piece qw( localtime );
use POSIX 'strftime';
use Date::Format qw(!strftime);
my $site_id = 1;
my %time_zone_hash = (
1 => 'Europe/London', #london (GMT+0)
2 => 'Asia/Kolkata', #bang (GMT+05:30)
);
my $utc_now = strftime('%Y-%m-%d %H:%M:%S', gmtime());
print "UTC:$utc_now\n";
my $site_time = convertSiteTime($site_id, $utc_now);
print "site_time=$site_time\n";
print time2str('%Y-%m-%d %H:%M:%S', $site_time)."\n";
sub convertSiteTime {
my $id = shift;
my $time_str = shift;
my $epoch_time = str2time($time_str);
if (!$epoch_time) {
print "$time_str is not a valid date. Please provide a valid date.\n";
exit(1);
}
my $dt = DateTime->from_epoch(epoch => $epoch_time);
$dt->set_time_zone($time_zone_hash{$id});
return $dt->epoch();
}
Output:
UTC:2023-07-20 09:19:16
site_time=1689824956
2023-07-20 09:19:16
It gives same result for UTC and site time. The site time suppose to be 2023-07-20 10:19:16
in this scenario.
Could someone please let me know whats wrong in the script.
Also my system (environment) is set to UTC time.
答案1
得分: 1
你正在询问如何将日期字符串从UTC转换为另一个时区(Asia/Kolkata)。
您的流程如下:
字符串 -> 时间戳 -> 日期时间对象 -> 更改时区 -> 时间戳 -> 字符串
将日期时间从一个时区转换为另一个时区对时间戳没有影响。无论您在地球上的哪个地方,自1970-01-01T00:00:00Z以来的时间都是相同的。[1]
这意味着
my $dt = DateTime->from_epoch(epoch => $epoch_time);
$dt->set_time_zone($time_zone_hash{$id});
return $dt->epoch;
与
return $epoch_time;
是相同的。由于中间部分是无用的,因此您的流程实际上是以下内容:
字符串 -> 时间戳 -> 字符串
这实际上是正确的。还有正确的:
字符串 -> 对象 -> 字符串
问题在于您正在不正确地执行这些转换。
我将首先重复我之前在您早期问题的回答中提供的DateTime和Time::Piece解决方案,然后提供一个Date::Parse + Date::Format解决方案。
使用DateTime将日期字符串从UTC转换为另一个时区
use DateTime::Format::Strptime qw( );
my $format = DateTime::Format::Strptime->new(
pattern => "%F %T",
strict => 1,
time_zone => "UTC",
on_error => "croak",
);
my $dt = $format->parse_datetime( "2023-07-20 09:19:16" );
$dt->set_time_zone( "Asia/Kolkata" );
say $dt->strftime( "%F %T %z" );
2023-07-20 14:49:16 +0530
- 不依赖于
%ENV
。 - 不依赖于系统定义的时区。
- 不包含在
perl
中。 - 相对较慢。
- 具有良好的接口。
使用Time::Piece将日期字符串从UTC转换为另一个时区
use Time::Piece qw( localtime );
my $dt;
{
local $ENV{ TZ } = "UTC";
$dt = localtime->strptime( "2023-07-20 09:19:16", "%F %T" );
}
{
local $ENV{ TZ } = "Asia/Kolkata";
say $dt->strftime( "%F %T %z" );
}
2023-07-20 14:49:16 +0530
- 即使对
%ENV
进行临时更改可能在多线程应用中也会有问题。 - 依赖于系统定义的时区,因此可能不太可移植。
- 包含在Perl中。
- 快速。
- Time::Piece可能很难正确使用。
使用Date::Parse + Date::Format将日期字符串从UTC转换为另一个时区
我刚刚发现这些模块处理时区的方式非常糟糕。
由于我们知道输入的偏移量,我们可以使用Date::Parse的str2time
。但我们不能使用Date::Format的time2str
来获得所需的输出。
除相对论效应外。
英文:
You are asking how to convert a date-string from UTC to another time zone (Asia/Kolkata).
Your flow:
string -> epoch -> DT object -> change time zone -> epoch -> string
Converting a date-time from one time zone to another has no effect on epoch. It doesn't matter where you are on Earth, the same amount of time has passed since 1970-01-01T00:00:00Z.<sup>[1]</sup>
That means that
my $dt = DateTime->from_epoch(epoch => $epoch_time);
$dt->set_time_zone($time_zone_hash{$id});
return $dt->epoch;
is the same as
return $epoch_time;
Since that whole middle bit is useless, your flow is effectively the following:
string -> epoch -> string
This is actually correct. Also correct:
string -> object -> string
The problem is that you are doing those conversions incorrectly.
I'll start with repeating the DateTime and Time::Piece solutions I already provided in my answer to your earlier question, then I'll provide a Date::Parse + Date::Format solution.
Converting a date-string from UTC to another time zone using DateTime
use DateTime::Format::Strptime qw( );
my $format = DateTime::Format::Strptime->new(
pattern => "%F %T",
strict => 1,
time_zone => "UTC",
on_error => "croak",
);
my $dt = $format->parse_datetime( "2023-07-20 09:19:16" );
$dt->set_time_zone( "Asia/Kolkata" );
say $dt->strftime( "%F %T %z" );
2023-07-20 14:49:16 +0530
- Doesn't rely on
%ENV
. - Doesn't rely on the system for its definitions of time zones.
- Not included with
perl
. - Relatively slow.
- Decent interface.
Converting a date-string from UTC to another time zone using Time::Piece
use Time::Piece qw( localtime );
my $dt;
{
local $ENV{ TZ } = "UTC";
$dt = localtime->strptime( "2023-07-20 09:19:16", "%F %T" );
}
{
local $ENV{ TZ } = "Asia/Kolkata";
say $dt->strftime( "%F %T %z" );
}
2023-07-20 14:49:16 +0530
- Even temporary changes to
%ENV
might be problematic in a threaded application. - Relies on the system for its definitions of time zones, so it might be less portable.
- Included with Perl.
- Fast.
- Time::Piece can be very tricky to use correctly.
Converting a date-string from UTC to another time zone using Date::Parse + Date::Format
I've just discovered the handling of time zones by those modules is complete garbage.
Since we know the offset of the input, we can Date::Parse's str2time
. But we can't use Date::Format's time2str
to get the desired output.
- Aside from relativistic effects.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论