Найти первый экземпляр дня недели в Perl - PullRequest
1 голос
/ 25 февраля 2020

Я пытаюсь найти первый экземпляр указанного c дня недели в месяце, например, первый понедельник указанного c месяца / года, который я ему даю.

Возиться с DateTime Я знаю, что могу создать свой объект даты с помощью

my $dt = DateTime->new(
    year     => $year,
    month    => $month
);

, а затем я даже могу использовать $dt->day_of_week, чтобы получить 1-7 назад, чтобы узнать, какой сегодня день недели. Мой первоначальный план состоял в том, чтобы сделать это и просто oop через одну неделю и увеличивать день на единицу каждый раз, проблема в том, что, как только я создаю DateTime объект, он становится неизменным, и поэтому я могу ' Обновление дня.

Есть ли лучший способ сделать это?

Ответы [ 4 ]

3 голосов
/ 25 февраля 2020

Вы можете использовать Time :: Piece , которая является базовой библиотекой (и ее объекты являются изменяемыми) . Кроме того, вам не нужно l oop в течение нескольких дней, просто используйте математику, чтобы найти количество дней для добавления.

#!/usr/bin/perl
use warnings;
use strict;
use feature qw{ say };

use Time::Piece;

for my $year (2000 .. 2020) {
    for my $month (1 .. 12) {
        my $tp = 'Time::Piece'->strptime("$year$month", '%Y%m');
        $tp += Time::Seconds::ONE_DAY * ((8 - $tp->day_of_week) % 7);
        say join "\t", $tp->mday, $tp;
    }
}
1 голос
/ 26 февраля 2020

С Время :: Момент (который по конструкции неизменен):

use strict;
use warnings;
use feature 'say';
use Time::Moment;
for my $year (2000 .. 2020) {
    for my $month (1 .. 12) {
        my $monday = Time::Moment->new(year => $year, month => $month, day => 1)
            ->with_day_of_week(1); # 1 == Monday
        # correct the week if that day was in the previous month
        $monday = $monday->plus_weeks(1) if $monday->month != $month;
        say join "\t", $monday->day_of_month, $monday;
    }
}
1 голос
/ 25 февраля 2020

Что-то вроде приведенного ниже кода должно сделать это

use strict;
use warnings;
use feature 'say';

use DateTime;

my $year  = 2056;
my $month = 11;
my $find  = 'monday';

                                    #  ucfirst lc - for consistency
say findDayOfWeek($year,$month,$find) . " is " . ucfirst lc $find;

sub findDayOfWeek {             # find first occurrence day of week 
    my $year  = shift;
    my $month = shift;
    my $dow   = shift;          # day of week

    $dow = ucfirst lc $dow;     # ucfirst lc - for consistency

    my %dayOfWeek = ( 
                        Monday => 1, Tuesday => 2, Wednesday => 3, 
                        Thursday => 4, Friday => 5, Saturday => 6,
                        Sunday => 7
                    );
    my $date;
    my $day = 1;

    my $dt = DateTime->new(
                year    => $year,
                month   => $month,
                day     => $day
            );

    my $dayOfWeek = $dt->day_of_week;

    if( $dayOfWeek != $dayOfWeek{$dow} ) {      # we are missed the target
        $day += $dayOfWeek{$dow}>$dayOfWeek     # correct it
                ? $dayOfWeek{$dow}-$dayOfWeek
                : 7+$dayOfWeek{$dow}-$dayOfWeek;
    }

    $date = sprintf "%4d-%02d-%02d", $year, $month, $day;

    return $date;
}

Вывод

2056-11-06 is Monday
1 голос
/ 25 февраля 2020

Поскольку вы спрашивали об объектах DateTime, тот же самый подход, который Чороба использовал для объектов Time :: Piece, можно использовать для объектов DateTime.

#!/usr/bin/perl
use warnings;
use strict;
use feature qw{ say };

use DateTime;

for my $year (2000 .. 2020) {
    for my $month (1 .. 12) {
        my $dt = DateTime->new( year => $year, month => $month );
        $dt->add( days => ((8 - $dt->day_of_week) % 7) );
        say join "\t", $dt->day, $dt;
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...