Perl 日付のフォーマット出力

 先日、日付関連のプログラムを作ったついでに日付を良く使いそうな形式を連想配列に定型出力するスプリクトを考えてみました。


sub timeformat{
  my $t=$_[0];
  my $diff=$_[1];

  #エラー処理
  if($t eq ""){$t=0;}
  if($diff eq ""){$diff=0;}
  if($t !~ /^[+-]?[0-9]+$/){return();}
  if($diff !~ /^[+-]?[0-9]+$/){return();}
  if($diff<-86399){return();}
  if($diff>86399){return();}

  #西暦0年0月0日00:00:00以前は処理しない
  if( ($t+$diff) < -62167219200){return();}
  #西暦9999年12月31日23:59:59 以前は処理しない
  if( ($t+$diff) > 253402300799){return();}
  my %output;

  my @weeks = ('Sun','Mon','Tue','Wed','Thu','Fri','Sat');
  my @weeks2 = ('Sunday','Monday','Tuesday','Wednesday',
  'Thursday','Friday','Saturday');
  my @weeksj = ('日','月','火','水','木','金','土');
  my @months= ('Jan','Feb','Mar','Apr','May','Jun','Jul','Aug',
  'Sep','Oct','Nov','Dec');
  my @months2= ('January','February','March','April','May','June',
  'July','August','September','October','November','December');

  my($sec,$min,$hour,$day,$mon,$year,$week,$yday,$summer) = gmtime($t+$diff);
  $year += 1900;
  if($year>9999){return();}  #西暦9999年以上は出力しない
  $year2=$year-int($year/100)*100;  #2桁の西暦
  $mon += 1;

  $output{t0}=$_[0];        #引数そのまま
  $output{t1}=$_[1];        #引数そのまま
  $output{y}=$year;        #年の処理
  $output{yyyy}=$year;
  $output{yy}=sprintf("%02d", $year2);
  $output{m}=$mon;         #月の処理
  $output{mm}=sprintf("%02d", $mon);
  $output{M}=$months[$mon-1]; 
  $output{MM}=$months2[$mon-1]; 
  $output{d}=$day;         #日の処理
  $output{dd}=sprintf("%02d", $day);
  $output{h}=$hour;        #時間の処理
  $output{hh}=sprintf("%02d", $hour);
  if($hour<12){
    $output{a}="am";
    $output{A}="AM";
    $output{aa}="a.m.";
    $output{aj}="午前";
    $output{H}=$hour;
    $output{HH}=sprintf("%02d", $hour);
  }else{
    $output{a}="pm";
    $output{A}="PM";
    $output{aa}="p.m.";
    $output{aj}="午後";
    $output{H}=$hour-12;
    $output{HH}=sprintf("%02d", $hour-12);
  }
  $output{n}=$min;         #分の処理
  $output{nn}=sprintf("%02d", $min);
  $output{s}=$sec;         #秒の処理
  $output{ss}=sprintf("%02d", $sec);
  $output{w}=$weeks[$week];#週の処理
  $output{ww}=$weeks2[$week]; 
  $output{wj}=$weeksj[$week]; 

  #和暦の処理
  if( $t >=600188400){  #1989年1月8日以降は平成
    $output{g}="H";
    $output{gg}="平";
    $output{ggg}="平成";
    $output{e}=$year-1988;
    $output{ee}=sprintf("%02d", $year-1988);
  }elsif($t >= -1357635600){ #1926年12月25日以降は昭和
    $output{g}="S";
    $output{gg}="昭";
    $output{ggg}="昭和";
    $output{e}=$year-1925;
    $output{ee}=sprintf("%02d", $year-1925);
  }elsif($t >= -1812186000){ #1912年7月30日以降は大正
    $output{g}="T";
    $output{gg}="大";
    $output{ggg}="大正";
    $output{e}=$year-1911;
    $output{ee}=sprintf("%02d", $year-1911);
  }elsif($t >= -3216790800){ #1868年1月25日以降は明治
    $output{g}="M";
    $output{gg}="明";
    $output{ggg}="明治";
    $output{e}=$year-1867;  
    $output{ee}=sprintf("%02d", $year-1867);
  }

  #一括設定
  $output{"yyyy/mm/dd"}="$output{yyyy}/$output{mm}/$output{dd}";
  $output{"yy/mm/dd"}="$output{yy}/$output{mm}/$output{dd}";
  $output{"mm/dd"}="$output{yyyy}/$output{mm}/$output{dd}";
  $output{"yyyy-mm-dd"}="$output{yyyy}-$output{mm}-$output{dd}";
  $output{"yy-mm-dd"}="$output{yy}-$output{mm}-$output{dd}";

  $output{"hh:nn:ss"}="$output{hh}:$output{nn}:$output{ss}";
  $output{"hh:nn"}="$output{hh}:$output{nn}";

  return(%output);
}

使い方
 &timeformat(time値,時差);
 で与えられた時間と時差から年/月/日/時/分/秒/曜/日/和暦など連想配列型で出力します。
 ・time値はtime()関数の数値
 ・時差秒で入力、日本の場合UTC+9時間なので32400と入力
 正しくない時間や下記の制限を超える数値を入力した場合、空値を返します。
 制限事項として西暦0年1月1日00:00:00から9999年12月31日23:59:59までしか扱えないため、time値と時差の合計が
「-62167219200~253402300799」の範囲にある事。

連想配列名との対応表
t0 = 引数の1つめtime値と同じ
t1 = 引数の2つめ時差と同じ
y = 西暦4桁(2001)
yyyy = 同上
yy = 西暦2桁(01)
m = 月 (1~12)
mm = 月 2桁(01~12)
M = 月英語短縮(Jan/Feb/~)
MM = 月英語(January/February/~)
d = 日 (1~31)
d = 日 2桁(01~31)
h = 時 (1~23)
hh = 時 2桁(01~23)
H = 時間 12時間制 (1~12)
HH = 時間 12時間制2桁 (01~12)
a = (am/pm)
A = (AM/PM)
aa = (a.m./p.m.)
aj = (午前/午後)
n = 分 (1~59)
nn = 分 2桁表記(01~59)
s = 秒 (1~59)
ss = 秒 2桁表記(01~59)
w =曜日英語短縮 (Sun/Mon/~)
ww =曜日英語 (Sunday/Monday/~)
wj =曜日日本語 (日/月/~)

和暦
g = (H/S/T/M)
gg = (平/昭/大/明)
ggg = (平成/昭和/大正/明治)
e = 元号 (1~)
ee = 元号2桁表記 (01~)

その他、よく使いそうな物をプリセットしてあります。
yyyy/mm/dd
yy/mm/dd
mm/dd
yyyy-mm-dd
yy-mm-dd
hh:nn:ss
hh:nn


使用例

 my $t=time();
  my %ft=&timeformat($t,32400);
  print $ft{"yyyy"}."/".$ft{"m"}"/".$ft{"d"};
  print $ft{"aj"}.$ft{"HH"}.":".$ft{"nn"}"/".$ft{"ss"};
  print $ft{"ggg"}.$ft{"ee"}."年";

とすれば
「2000/1/1」
「午後13:01:05」
「平成12年」
と表示されます。


メモ
注意
・分はminの頭文字のmでは無く「n」なので注意して下さい。
 (mは月で使用されているため)
・和暦は時差32400以外で使用した場合正しくない答えが出る可能性があります。
・和暦は明治から平成までしか対応していません。
・元号の1年目を元年と呼ぶのが一般的ですが、1年と表示されます。

プログラムの先頭でlocal宣言した変数に代入しておけば、最後まで様々な書式を使用する事ができます。

コメントを残す

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

CAPTCHA