どうやら、excelの日付&時刻型の実体は、日付を整数部、時刻を小数部にした小数で保持しているみたい。
例
オリジナル | excelの日付&時刻型 |
---|---|
2011/12/4 9:42:35 | 40881.4045717593 |
Spreadsheet::ParseExcel を使えば、perlでexcel(xls)ファイルを解析できますが、以前、この日付時刻型にハマったことがありましたが、Spreadsheet::WriteExcel::Utility の xl_parse_time() に、その答えがありました。
そこで、xl_parse_time() を写経して、excel形式との可逆変換を行えるparserを書いてみました。
#!/usr/local/bin/perl use strict; use Date::Calc qw(Delta_DHMS Add_Delta_Days); use Data::Dumper; my @EPOCH = (1899, 12, 31, 0, 0, 0); main(); sub main { my @org_date_time = (2011,12,4,9,42,35); print sprintf("ORIGINAL DATE TIME: %d/%d/%d %d:%d:%d",@org_date_time),"\n"; my $excel_date = date2excel_date(2011,12,4,9,42,35); print "ENCODE EXCEL TYPE : $excel_date\n"; my @date_time = excel_date2date($excel_date); print sprintf("DECODE ORIGINAL : %d/%d/%d %d:%d:%d",@date_time),"\n"; } #refer to http://search.cpan.org/perldoc?Spreadsheet::WriteExcel::Utility sub date2excel_date { my ($years, $months, $days, $hours, $minutes, $seconds) = @_; return undef unless $years; $months ||= 1; $days ||= 1; $hours ||= 0; $minutes ||= 0; $seconds ||= 0; my @date = ($years, $months, $days, $hours, $minutes, $seconds); #日時の差分 ($days, $hours, $minutes, $seconds) = Date::Calc::Delta_DHMS(@EPOCH, @date); my $date = $days + ($hours*3600 +$minutes*60 +$seconds)/(24*60*60); # Add a day for Excel's missing leap day in 1900 閏年...? $date++ if ($date > 59); return $date; } sub excel_date2date { my ($excel_date) = @_; $excel_date-- if $excel_date > 60; my $date_part = int($excel_date); my $time_part = $excel_date - $date_part; my @time = excel_time2time($time_part); my @date = Date::Calc::Add_Delta_Days(@EPOCH[0..2],$date_part); return (@date,@time); } sub excel_time2time { my ($excel_time) = @_; $excel_time = $excel_time*(24*60*60); my $hour = int($excel_time / 3600); my $minutes = int(($excel_time - $hour*3600) / 60); my $seconds = $excel_time % 60; return ($hour,$minutes,$seconds); }
実行結果
[endo@colinux tmp]$ ./foo.pl ORIGINAL DATE TIME: 2011/12/4 9:42:35 ENCODE EXCEL TYPE : 40881.4045717593 DECODE ORIGINAL : 2011/12/4 9:42:35