2012-06-06 7 views
1

Я перебираю ряд последовательных дат. Мне нужно выяснить, какие выходные, чтобы их можно было отбросить. Один из методов - определить день недели через perl (то, что написано в моем скрипте) или запросить с каждым прохождением через цикл. Для проверки не будет более 30 дат, обычно 5 или менее. Было бы более эффективно загружать Date :: Time и использовать perl или запускать запрос без необходимости в модулях? Если perl - лучший метод, я могу использовать небольшую помощь для извлечения дня недели из формата YYYY-MM-DD. Я был бы в порядке с номером 1-7 или коротким именем mon-sun.Извлечь день недели, используя формат даты perl и mysql

2012-05-01 
2012-05-02 
2012-05-03 
2012-05-04 
2012-05-05 
2012-05-06 

не уверен, если это возможно, но, возможно, более подходящим решением было бы написать запрос (так как я знаю, что начало и конец, и они являются последовательными), чтобы считать дни между х и у, где день недели НЕ В (6,7)

+0

Поскольку даты являются последовательными, как только вы знаете день недели первой даты, тривиально найти первые выходные и знать, что все другие выходные дни происходят через 7 дней. – eggyal

+0

Мне по-прежнему приходится перебирать этот список дат (даты существуют в текстовом файле, а не вытаскиваются из запроса), моя конечная цель - иметь общее количество недельных дней в диапазоне. ярость может начаться в любой день месяца. Я не вижу, как ваш ответ затрагивает мой вопрос. – chrisrth

ответ

0
use Date::Simple qw/date/; 
use Date::Range; 

my ($start, $end) = (date('2012-05-02'), date('2012-05-16')); 
my $range = Date::Range->new($start, $end); 
my @all_dates = $range->dates; 

foreach my $d (@all_dates) { 
    my $date = Date::Simple->new($d); 
    print $date->day_of_week." ".$d."<br />"; 
    } 

#--OUTPUT--# 

3 2012-05-02 
4 2012-05-03 
5 2012-05-04 
6 2012-05-05 
0 2012-05-06 
1 2012-05-07 
2 2012-05-08 
3 2012-05-09 
4 2012-05-10 
5 2012-05-11 
6 2012-05-12 
0 2012-05-13 
1 2012-05-14 
2 2012-05-15 
3 2012-05-16 
3

См. DateTime::Format::Strptime и DateTime.

use 5.010; 
use strictures; 
use DateTime::Format::Strptime qw(); 
my $parser = DateTime::Format::Strptime->new(pattern => '%F'); 
for my $date (qw(
    2012-05-01 
    2012-05-02 
    2012-05-03 
    2012-05-04 
    2012-05-05 
    2012-05-06 
)) { 
    my $dow = $parser->parse_datetime($date)->day_of_week; 
    say "$date is a weekend day" if 6 == $dow or 7 == $dow; 
} 
2

Наиболее очевидным решением является использование модуля Time::Piece, который является основным модулем Perl с версии v5.9 и поэтому, вероятно, не требуется установка в вашей системе.

Метод wday возвращает числовой день недели, где 1 == Воскресенье, поэтому на выходные вы ищете значения 7 (суббота) или 1. Это можно настроить так, чтобы суббота была представлена ​​нулем вместо (и воскресенье на 1) в письменной форме

my $dow = $tp->wday % 7; 

, после чего тест на выходные просто $dow < 2.

Вот несколько примеров для демонстрации.

use strict; 
use warnings; 

use Time::Piece; 

while (<DATA>) { 
    chomp; 
    my $tp = Time::Piece->strptime($_, '%Y-%m-%d'); 
    my $dow = $tp->wday % 7; 
    print $_; 
    print " (weekend)" if $dow < 2; 
    print "\n"; 
} 

__DATA__ 
2012-05-01 
2012-05-02 
2012-05-03 
2012-05-04 
2012-05-05 
2012-05-06 

выход

2012-05-01 
2012-05-02 
2012-05-03 
2012-05-04 
2012-05-05 (weekend) 
2012-05-06 (weekend) 
2

Вы можете использовать модуль ядра Time::Local, а затем вычислить день недели, используя localtime. День недели 0 соответствует воскресеньям, а 6 - суббота.

#! /usr/bin/env perl 

use strict; 
use warnings; 

use Time::Local; 

my @dates = qw(
    2012-05-01 
    2012-05-02 
    2012-05-03 
    2012-05-04 
    2012-05-05 
    2012-05-06 
); 

my @days = qw/ Sun Mon Tue Wed Thu Fri Sat /; 

foreach my $date (@dates) { 
    my($yyyy,$mm,$dd) = split /-/, $date; 
    my $time_t = timelocal 0, 0, 0, $dd, $mm-1, $yyyy-1900; 
    my $wday = (localtime $time_t)[6]; 
    my $weekend = ($wday == 0 || $wday == 6) ? " *" : ""; 

    print "$date: $days[$wday] ($wday)$weekend\n"; 
} 

Выход:

2012-05-01: Tue (2) 
2012-05-02: Wed (3) 
2012-05-03: Thu (4) 
2012-05-04: Fri (5) 
2012-05-05: Sat (6) * 
2012-05-06: Sun (0) *

Для удовольствия, вы могли бы пойти швейцарской армии бензопилу и скрести выход кал полезности.

#! /usr/bin/env perl 

use strict; 
use warnings; 

use 5.10.0; # for smart matching 

sub weekday_type { 
    my($date) = @_; 
    die "$0: unexpected date '$date'" 
    unless my($yyyy,$mm,$dd) = 
      $date =~ /^([0-9]{1,4})-([0-9]{1,2})-([0-9]{1,2})$/; 

    my $calendar = `cal -m $mm $yyyy`; 
    die "$0: cal -m $mm $yyyy failed" if $?; 

    for (split /\n/, $calendar) { 
    if (/^ \s* [0-9]{1,2} (?: \s+ [0-9]{1,2})* \s*$/x) { 
     my @dates = split; 
     my @weekend = splice @dates, @dates > 1 ? -2 : -1; 
     return "weekend" if ($dd+0) ~~ @weekend; 
    } 
    } 

    "weekday"; 
} 

Используйте его как в

my @dates = qw(
    2012-05-01 
    2012-05-02 
    2012-05-03 
    2012-05-04 
    2012-05-05 
    2012-05-06 
); 

my @days = qw/ Sun Mon Tue Wed Thu Fri Sat /; 

foreach my $date (@dates) { 
    my $type = weekday_type $date; 
    print "$date: $type\n"; 
} 

Выход:

2012-05-01: weekday 
2012-05-02: weekday 
2012-05-03: weekday 
2012-05-04: weekday 
2012-05-05: weekend 
2012-05-06: weekend

Я не рекомендую делать это таким образом в производстве.

Смежные вопросы