代码之家  ›  专栏  ›  技术社区  ›  ABach

我怎样才能用Perl获取这个星期的日期?

  •  6
  • ABach  · 技术社区  · 15 年前

    我有下面的循环来计算本周的日期并打印出来。它是有效的,但是我在Perl中加入了大量的日期/时间可能性,并希望得到您对是否有更好的方法的意见。这是我写的代码:

    #!/usr/bin/env perl
    use warnings;
    use strict;
    
    use DateTime;
    
    # Calculate numeric value of today and the 
    # target day (Monday = 1, Sunday = 7); the
    # target, in this case, is Monday, since that's
    # when I want the week to start
    my $today_dt = DateTime->now;
    my $today = $today_dt->day_of_week;
    my $target = 1;
    
    # Create DateTime copies to act as the "bookends"
    # for the date range
    my ($start, $end) = ($today_dt->clone(), $today_dt->clone());
    
    if ($today == $target)
    {
      # If today is the target, "start" is already set;
      # we simply need to set the end date
      $end->add( days => 6 );
    }
    else
    {
      # Otherwise, we calculate the Monday preceeding today
      # and the Sunday following today
      my $delta = ($target - $today + 7) % 7;
      $start->add( days => $delta - 7 );
      $end->add( days => $delta - 1 );
    }
    
    # I clone the DateTime object again because, for some reason,
    # I'm wary of using $start directly...
    my $cur_date = $start->clone();
    
    while ($cur_date <= $end)
    {
      my $date_ymd = $cur_date->ymd;
      print "$date_ymd\n";
      $cur_date->add( days => 1 );
    }
    

    如前所述,这是可行的,但它是最快的还是最有效的?我猜快速和效率可能不一定是一致的,但您的反馈非常感谢。

    4 回复  |  直到 15 年前
        1
  •  14
  •   Dave Rolsky    15 年前

    弗里多答案的一个稍有改进的版本…

    my $start_of_week =
        DateTime->today()
                ->truncate( to => 'week' );
    
    for ( 0..6 ) {
        print $start_of_week->clone()->add( days => $_ );
    }
    

    但是,这假定星期一是一周的第一天。星期天,从…

    my $start_of_week =
        DateTime->today()
                ->truncate( to => 'week' )
                ->subtract( days => 1 );
    

    不管怎样,最好使用 truncate 方法,而不是像Friedo那样重新实现它;)

        2
  •  4
  •   friedo    15 年前

    可以使用datetime对象将一周中的当前日期作为数字(1-7)获取。然后用它来查找本周的星期一。例如:

    my $today = DateTime->now;
    my $start = $today->clone;
    
    # move $start to Monday
    $start->subtract( days => ( $today->wday - 1 ) );   # Monday gives 1, so on monday we
                                                        # subtract zero. 
    
    my $end = $start->clone->add( days => 7 );
    

    上面的内容没有经过测试,但是这个想法应该是可行的。

        3
  •  2
  •   Axeman maxelost    15 年前

    这是否有效:

    use strict;
    use warnings;
    use POSIX qw<strftime>;
    my ( $day, $pmon, $pyear, $wday ) = ( localtime )[3..6];
    $day -= $wday - 1; # Get monday
    for my $d ( map { $day + $_ } 0..6 ) { 
        print strftime( '%A, %B %d, %Y', ( 0 ) x 3, $d, $pmon, $pyear ), "\n";
    }
    

    我只是把它们作为插图印刷。您可以将它们存储为时间戳,如下所示:

    use POSIX qw<mktime>;
    my @week = map { mktime(( 0 ) x 3, $day + $_, $pmon, $pyear ) } 0..6;
    
        4
  •  1
  •   Snake Plissken    15 年前

    这应该有效:

    use POSIX; # for strftime
    my $time = time ();
    my $seconds = 24*60*60;
    my @time = gmtime ();
    $time = $time - $time[6] * $seconds;
    for my $wday (0..6) {
        $time += $seconds;
        my @wday = gmtime ($time);
        print strftime ("%A %d %B %Y\n", @wday);
    }
    

    给我:

    $ ./week.pl 
    Monday 24 May 2010
    Tuesday 25 May 2010
    Wednesday 26 May 2010
    Thursday 27 May 2010
    Friday 28 May 2010
    Saturday 29 May 2010
    Sunday 30 May 2010
    

    如果你想从星期天开始有几个星期,改变 $time[6] ($time[6] + 1) .

    这假设您需要格林尼治标准时间周。变化 gmtime localtime 获取本地时区周数。