Как я могу получить даты этой недели в Perl? - PullRequest
6 голосов
/ 27 мая 2010

У меня есть следующий цикл, чтобы вычислить даты текущей недели и распечатать их. Это работает, но я плаваю в количестве возможностей даты / времени в 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 ]

14 голосов
/ 27 мая 2010

Немного улучшенная версия ответа Фридо ...

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;)

4 голосов
/ 27 мая 2010

Вы можете использовать объект 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 );

Выше не проверено, но идея должна работать.

2 голосов
/ 27 мая 2010

Будет ли это работать:

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;
1 голос
/ 27 мая 2010

Это должно работать:

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, чтобы получить недели по местному часовому поясу.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...