Perl:日付の計算方法(その2)

 以前Perlで日付を数値型(秒)にする逆localtime関数のようなスプリクトを作りましたが、1970年1月1日0時0分0秒より前の日付に対応していなかったので、西暦0年1月1日0時0分0秒から使えるように改良してみました。


sub ymdhns2time2{
  my($i,$uru,$output);
  my $ye=$_[0];  #年 0年以上
  my $mo=$_[1];  #月 1~12
  my $da=$_[2];  #日 1~31(月によって異なる)
  my $ho=$_[3];  #時 0~23
  my $mi=$_[4];  #分 0~59
  my $se=$_[5];  #秒 0~59
  my $diff=$_[6]; #秒 -86399~86399 時差
  #各引数にデータが無い場合は
  if($ye eq ""){$ye=1970;}
  if($mo eq ""){$mo=1;}
  if($da eq ""){$da=1;}
  if($ho eq ""){$ho=0;}
  if($mi eq ""){$mi=0;}
  if($se eq ""){$se=0;}
  if($diff eq ""){$diff=0;}
  #引数のエラーチェック
  if($ye !~ /^[0-9]+$/){return();}
  if($ye<0){return();}
  if($ye>9999){return();}
  if($mo !~ /^[0-9]+$/){return();}
  if($mo<1){return();}
  if($mo>12){return();}
  if($da !~ /^[0-9]+$/){return();}
  if($da<1){return();}
  if($ho !~ /^[0-9]+$/){return();}
  if($ho<0){return();}
  if($ho>23){return();}
  if($mi !~ /^[0-9]+$/){return();}
  if($mi<0){return();}
  if($mi>59){return();}
  if($se !~ /^[0-9]+$/){return();}
  if($se<0){return();}
  if($se>59){return();}
  if($diff !~ /^[+-]?[0-9]+$/){return();}
  if($diff<-86399){return();}
  if($diff>86399){return();}
  $uru=0;
  if($ye % 4 == 0){
    $uru=1;
    if($ye % 100 == 0){
      if($ye % 400 != 0){$uru=0;}
    }
  }
  if(($mo==1)&&($da>31)){return();}
  if($uru==1){ #うるう年
    if(($mo==2)&&($da>29)){return();}
  }else{
    if(($mo==2)&&($da>28)){return();}
  }
  if(($mo==3)&&($da>31)){return();}
  if(($mo==4)&&($da>30)){return();}
  if(($mo==5)&&($da>31)){return();}
  if(($mo==6)&&($da>30)){return();}
  if(($mo==7)&&($da>31)){return();}
  if(($mo==8)&&($da>31)){return();}
  if(($mo==9)&&($da>30)){return();}
  if(($mo==10)&&($da>31)){return();}
  if(($mo==11)&&($da>30)){return();}
  if(($mo==12)&&($da>31)){return();}

  #0年1月1日0:00:00秒を-62167251600秒として
  #年の処理(経過秒+前年までのうるう年の秒数)
  $output=$ye*31536000-62167219200;
  for($i=0;$i<$ye;$i++){
    if($i % 4 == 0){
      if(($i % 100 == 0)&&($i % 400 != 0)){
        #平年
      }else{
        $output=$output+86400; #うるう年(1日加算)
      }
    }    
  }
  #月の処理(1月は年で処理しているので不要)
  if    ($mo==2){$output=$output+2678400;
  }elsif($mo==3){$output=$output+5097600;
  }elsif($mo==4){$output=$output+7776000;
  }elsif($mo==5){$output=$output+10368000;
  }elsif($mo==6){$output=$output+13046400;
  }elsif($mo==7){$output=$output+15638400;
  }elsif($mo==8){$output=$output+18316800;
  }elsif($mo==9){$output=$output+20995200;
  }elsif($mo==10){$output=$output+23587200;
  }elsif($mo==11){$output=$output+26265600;
  }elsif($mo==12){$output=$output+28857600;
  }
  if($uru==1){  #うるう年の3月以降は1日加算
    if($mo>=3){$output=$output+86400;}
  }
  #日の処理
  $output=$output+($da-1)*86400;
  #時の処理
  $output=$output+$ho*3600;
  #分の処理
  $output=$output+$mi*60;
  #秒の処理
  $output=$output+$se;
  #時差の処理
  $output=$output-$diff;

  return($output);
}

使い方
 &ymdhns2time2(年,月,日,時,分,秒,時差);
 で1970年1月1日0時0分を0秒とした秒数を返します。
 ・年は0~9999
 ・時は0~23時の24時間制
 ・時差は-86399~86399の範囲で秒で記入、日本の場合はUTC+9時間なので32400と入力
 正しくない値が渡された時は何も返しません。

 例えば、2000年1月1日 13時30分0秒の秒数が知りたければ
 $min=&ymdhns2time(2001,1,1,13,30,0,32400);
 とすれば$minに秒数が代入されます。

 引数を””や省略すると年=1970、月=1、日=1、時=0、分=0、秒=0、時差=0となります。
 ・&ymdhns2time();なら
 =1970/1/1 00:00:00(時差0)と同等→0
 ・&ymdhns2time(“”,2,””,””,””,””,32400);なら
 =1970/2/1 00:00:00(時差+9時間)と同等→2646000
 不要な項目は入れなくても計算できるので、年を指定しない日付だけの計算や、時間だけの計算なども可能です。
 ただし年を入れない場合はうるう年に注意が必要です。1970年はうるう年では無いので1年365日で計算されます。


前バージョンとの変更点
(2014/6/11 旧バージョンの記事)

 ・ルーチン名に2が追加された
 「&ymdhns2time」→「&ymdhns2time2」
 ・引数に1970年1月1日より前の日付を入力できるようになった。
 ・エラー時の戻値が「-1」から「””」(空値)になった。

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

CAPTCHA