【问题标题】:Perl function localtime giving incorrect values for years between 1964 and 1967Perl 函数 localtime 给出了 1964 年到 1967 年之间年份的错误值
【发布时间】:2017-04-05 03:12:45
【问题描述】:

我从 Perl 中的 localtime 函数中得到了一些奇怪的值。以下是一些我得到不正确值的代码。

特别是,此代码用于确定每年第一天的工作日。

#!/usr/bin/perl
use strict 'vars';
use Time::Local;
use POSIX qw(strftime);

mytable();

sub mytable {
   print "Year" . " "x4 .  "Jan 1st (localtime)" . " "x4 . "Jan 1st (Gauss)\n";
   foreach my $year ( 1964 .. 2017 )
     {
       my $janlocaltime = evalweekday( 1,1,$year);
       my $jangauss     = gauss($year);
       my $diff = $jangauss - $janlocaltime;
       printf "%4s%10s%-12s ",$year,"",$janlocaltime;
       printf "%12s",$jangauss;
       printf " <----- ERROR: off by %2s", $diff if ( $diff != 0 );
     print "\n";
     }
}

sub evalweekday {
   ## Using "localtime"
   my ($day,$month,$year) = @_;
   my $epoch   =  timelocal(0,0,0, $day,$month-1,$year-1900);
   my $weekday = ( localtime($epoch) ) [6];
   return $weekday;
 }

sub gauss {
   ## Alternative approach
   my ($year) = @_;
   my $weekday =
     (  1 + 5 * ( ( $year - 1 ) % 4 )
      + 4 * ( ( $year - 1 ) % 100 )
      + 6 * ( ( $year - 1 ) % 400 )
    ) % 7;
   return $weekday;
 }

这是显示年份值不正确的输出:

Year    Jan 1st (localtime)    Jan 1st (Gauss)
1964          2                       3 <----- ERROR: off by  1
1965          4                       5 <----- ERROR: off by  1
1966          5                       6 <----- ERROR: off by  1
1967          6                       0 <----- ERROR: off by -6
1968          1                       1
1969          3                       3
1970          4                       4
1971          5                       5
1972          6                       6
1973          1                       1
1974          2                       2
1975          3                       3
1976          4                       4
1977          6                       6
1978          0                       0
1979          1                       1
1980          2                       2
1981          4                       4
1982          5                       5
1983          6                       6
1984          0                       0
1985          2                       2
1986          3                       3
1987          4                       4
1988          5                       5
1989          0                       0
1990          1                       1
1991          2                       2
1992          3                       3
1993          5                       5
1994          6                       6
1995          0                       0
1996          1                       1
1997          3                       3
1998          4                       4
1999          5                       5
2000          6                       6
2001          1                       1
2002          2                       2
2003          3                       3
2004          4                       4
2005          6                       6
2006          0                       0
2007          1                       1
2008          2                       2
2009          4                       4
2010          5                       5
2011          6                       6
2012          0                       0
2013          2                       2
2014          3                       3
2015          4                       4
2016          5                       5
2017          0                       0

事实上,这些错误似乎可以追溯到 1900 年,但我只是没有证实它们在 1964 年之前实际上是错误的。

perl --version 返回以下内容:

This is perl 5, version 18, subversion 2 (v5.18.2) built for darwin-thread-multi-2level
(with 2 registered patches, see perl -V for more detail)

Copyright 1987-2013, Larry Wall

Perl may be copied only under the terms of either the Artistic License or the
GNU General Public License, which may be found in the Perl 5 source kit.

Complete documentation for Perl, including FAQ lists, should be found on
this system using "man perl" or "perldoc perl".  If you have access to the
Internet, point your browser at http://www.perl.org/, the Perl Home Page.

我不确定它是否相关,但我的操作系统是 macOS Sierra 版本 10.12.3。

我已经通读了文档,但对于 1968 年之前返回的值,我没有看到任何内容(或者我是盲目的)。我也尝试进行网络搜索,但除了对数组值和一年中的月数和天数的典型误解。

有人可以帮我解释一下我做错了什么吗?或者,如果这是我的 Perl 版本的问题,请告诉我我可以做些什么来解决它。

【问题讨论】:

  • 我删除了函数调用前面的&amp;,因为这些不再需要(至少在过去 10 年中)。

标签: perl localtime


【解决方案1】:

这可能与 Time::Local 中负纪元值的处理方式有关。看看perldoc Time::Local #Negative-Epoch-Values

在我的 Linux 机器(perl 5.20)上,您的代码很好地演示了这个问题。如果打印出收到的 epoch 值,您会看到问题,即 timelocal 返回的 epoch 变得巨大而不是更负:

Year       Epoch Jan 1st (localtime)     Jan 1st (Gauss)
1964  2966342400 2                       3 <----- ERROR: off by  1
1965  2997964800 4                       5 <----- ERROR: off by  1
1966  3029500800 5                       6 <----- ERROR: off by  1
1967  3061036800 6                       0 <----- ERROR: off by -6
1968   -63185400 1                       1
1969   -31563000 3                       3
1970      -27000 4                       4
1971    31509000 5                       5
1972    63045000 6                       6

你为什么不尝试使用 DateTime 库来代替:

use DateTime;
my $dt = DateTime->new(
    year   => 1966, # Real Year
    day    => 1,    # 1-31
    month  => 1,    # 1-12
    hour   => 0,    # 0-23
    second => 0,    # 0-59
);
print $dt->dow . "\n";

6

6 = Saturday 匹配 Wikipedian 视图:Jan 1, 1966 (Saturday)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-01-01
    • 2019-08-10
    • 1970-01-01
    • 2016-08-12
    • 2017-02-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多