2017-04-05 8 views
2

localtimeの関数がPerlで機能していました。以下は私が間違った値を取得するためのコードです。Perlの関数localtimeが1964年から1967年までの間に間違った値を返しました

特に、このコードは、毎年の最初の曜日を決定するためのものです。ここで

#!/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 Version 10.12.3です。

私はドキュメントを読んだことがありますが、1968年以前に返された値は何も表示されません(または私は見えません)。私はウェブ検索を試みましたが、配列値の典型的な誤解、および年と月のナンバリング。

誰かが私を助けて、私が間違っていることを説明できますか?または、これが私のPerlのバージョンで問題になっている場合は、私が修正するために何ができるか教えてください。

+1

を、これらは(少なくとも過去10年間のために)必要なくなっているように私は、 '&'関数呼び出しの前には削除されません。 – xxfelixxx

答えて

4

これは、負のエポック値がTime :: Localでどのように処理されるかと関連しています。一読するperldoc Time::Local #Negative-Epoch-Values

私のLinuxマシン(perl 5.20)では、コードが問題をうまく示しています。あなたが受け取ったエポック値を印刷する場合は、timelocalによって返されたエポックはなく、より多くの負の巨大になり、すなわちという、問題が表示されます。

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 = SaturdayJan 1, 1966 (Saturday)

関連する問題