【问题标题】:Check if timestamp falls in current week in perl检查时间戳是否在 perl 中的当前周
【发布时间】:2018-02-05 22:36:39
【问题描述】:

我有一个包含键和时间戳的哈希值,如下所示。有没有办法找出哪些键具有当前星期的时间戳。

my %hash = (
      'key1'  => '2018-01-17',
      'key2'  => '2018-02-05,2018-01-08',
      'key3'  => '2018-01-26' ,
      'key4'  => '2018-01-04',
      'key5'  => '2018-01-27,2018-02-06,2018-01-28'
    );

预期结果是:'key2' 和 'key5' 值 2018-02-05 和 2018-02-06 在本周下降。

【问题讨论】:

  • 您更喜欢“使用模块 X”解决方案还是“使用原始 perl”解决方案?
  • 模块解决方案很好。谢谢!
  • 您是指日历周,您从哪一天开始一周?还是您的意思是“过去 7 天内”?
  • 你试过什么?您是否在循环键/日期或测试日期时遇到问题?

标签: perl


【解决方案1】:

就我个人而言,我喜欢 DateTime 来满足我所有的日期/时间需求,因为它是一个非常完整的解决方案。在下文中,我假设您的哈希值的格式一致(YYYY-MM-DD 用逗号分隔,没有空格)。另请注意,这使用星期一作为一周的第一天,有关详细信息,请参阅DateTime truncate method。

use warnings;
use strict;
use DateTime;
use DateTime::Format::Strptime;

my %hash = (
    'key1' => '2018-01-17',
    'key2' => '2018-02-05,2018-01-08',
    'key3' => '2018-01-26',
    'key4' => '2018-01-04',
    'key5' => '2018-01-27,2018-02-06,2018-01-28'
);

my $strp = DateTime::Format::Strptime->new( on_error=>'croak',
    pattern => '%Y-%m-%d', time_zone=>'floating' );

my $week_start = DateTime->now(time_zone=>'local')
    ->set_time_zone('floating')->truncate(to=>'week');
my $week_end   = $week_start->clone->add( days => 7 );

for my $key (sort keys %hash) {
    for my $date (split /,/, $hash{$key}) {
        my $dt = $strp->parse_datetime($date);
        # DateTime objects overload comparison operators
        if ( $week_start <= $dt && $dt < $week_end ) {
            print "$key\n";
        }
    }
}

【讨论】:

  • 不要截断除非你切换到浮动,否则它可以fail。固定。
  • @ikegami - 谢谢,虽然它是 floating 而不是 float,但已修复。更新:啊,看来我们几乎是在同一时间发现的 :-)
  • @ikegami - 嗯,是的,使用local 时间可能更好,已编辑,谢谢。
【解决方案2】:

有很多方法可以做你想做的事。使用Time::Piece,我认为它是 Perl 5.9.5 的核心,您可以这样做:

use Time::Piece;

my %hash = (
  'key1' => '2018-01-17',
  'key2' => '2018-02-05,2018-01-08',
  'key3' => '2018-01-26' ,
  'key4' => '2018-01-04',
  'key5' => '2018-01-27,2018-02-06,2018-01-28'
);

my $current = localtime->strftime('%Y-%V');

foreach my $i (sort keys %hash) {
  foreach my $j (split /\s*,\s*/, $hash{$i}) {
    if( localtime->strptime($j, '%Y-%m-%d')->strftime('%Y-%V') eq $current ) {
      print 'Key: ', $i, ', date: ', $j, "\n";
    }
  }
}

它使用 %V 是 ISO 8601 周数这一事实,它与年份连接起来可以比较。

函数strptime 将字符串转换为日期对象,然后strftime 将日期对象转换为字符串。

输出:

Key: key2, date: 2018-02-05
Key: key5, date: 2018-02-06

strftime 函数还有其他周定义可供您使用:%U、%V 和 %W;例如见here。

【讨论】:

  • 您将本地日期的星期与 UTC 日期的星期进行比较。这可能会导致奇怪(即不正确)的结果。固定。
  • @ikegami,你已经编辑了代码,所以只剩下感谢你了!
  • 感谢 ikegami、Javier 和 haukex 的解释和代码示例。工作很棒!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-11-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多