【问题标题】:Extract day of week using perl and mysql date format使用 perl 和 mysql 日期格式提取星期几
【发布时间】:2012-06-10 18:51:31
【问题描述】:

我正在循环浏览一系列连续日期。我需要找出哪些是周末,以便可以丢弃它们。一种方法是通过 perl(我的脚本是用什么编写的)来确定星期几,或者在每次通过循环时进行查询。要检查的日期永远不会超过 30 个,通常是 5 个或更少。加载 Date::Time 并使用 perl 或在不需要模块的情况下运行 Query 会更有效吗?如果 perl 是最好的方法,我可以帮助从 YYYY-MM-DD 格式中提取星期几。我可以使用 1-7 号或短名 mon-sun。

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

不确定这是否可能,但也许更合适的解决方案是编写一个查询(因为我知道开始和结束并且它们是连续的)来计算 x 和 y 之间的天数,其中 dayofweek NOT IN(6,7)

【问题讨论】:

  • 由于日期是连续的,一旦知道第一个日期的星期几,就很容易找到第一个周末并知道所有其他周末都在 7 天后。
  • 我仍然需要遍历这个日期列表(日期存在于文本文件中,而不是从查询中提取)我的最终目标是在一个范围内计算工作日的总数。愤怒可能在一个月的任何一天开始。我看不出你的回答如何解决我的问题。

标签: mysql perl datetime


【解决方案1】:

请参阅 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】:

    MySQL有一个day of week function可以直接使用。

    【讨论】:

      【解决方案3】:

      最明显的解决方案是使用Time::Piece 模块,它自 v5.9 以来一直是 Perl 的核心模块,因此可能不需要在您的系统上安装。

      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)
      

      【讨论】:

        【解决方案4】:

        您可以使用核心 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: 星期二 (2)
        2012-05-02: 星期三 (3)
        2012-05-03:周四(4)
        2012-05-04:周五(5)
        2012-05-05: 星期六 (6) *
        2012-05-06: 太阳 (0) *

        为了好玩,您可以使用 Swiss Army Chainsaw 并抓取 cal 实用程序的输出。

        #! /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: 工作日
        2012-05-02:工作日
        2012-05-03:平日
        2012-05-04:平日
        2012-05-05:周末
        2012-05-06:周末

        我不建议在生产中这样做。

        【讨论】:

          【解决方案5】:
          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
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2014-10-08
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多