Skip Menu |

This queue is for tickets about the DateTime-Format-Excel CPAN distribution.

Report information
The Basics
Id: 7498
Status: resolved
Estimated: 3 hours (180 min)
Worked: 2 hours (120 min)
Priority: 0/
Queue: DateTime-Format-Excel

People
Owner: ABURS [...] cpan.org
Requestors: john.lengeling [...] radisys.com
Cc: aburs [...] cpan.com
AdminCc:

Bug Information
Severity: Important
Broken in: 0.26
Fixed in: (no value)



Subject: DateTime-Format-Excel does not convert the seconds portion of an Excel Date/Time value
The DateTime-Format-Excel package will correctly convert the date portion of an Excel Date/Time format, but not the H:M:S. The bug is in the parse_datetime function of Excel.pm The H:M:S is stored as a fraction where 1 second = 1 / (60*60*24). I found useful information on this web page: http://www.mvps.org/dmcritchie/excel/datetime.htm Here is a test script that I used: #!/usr/local/bin/perl use strict; use Spreadsheet::ParseExcel::Simple; use DateTime::Format::Excel; my $days; my $secs; my $curtime = "37987.0000115741"; $curtime =~ /^ (\d+ (?: (\.\d+) )? ) $/x; print "days = $1\n"; print "secs = $2\n"; my $datetime = DateTime::Format::Excel->parse_datetime($curtime); print $datetime->strftime("%F %r") . "\n"; print $datetime->strftime("%F %T") . "\n"; print $datetime->strftime("%F %z") . "\n"; Attached are the changes I made to the .2901 version of Excel.pm to fix the problem. Environment: Solaris 2.8, Perl v5.6.1
package DateTime::Format::Excel; # $Id: Excel.pm,v 1.6 2004/01/26 19:04:02 autarch Exp $ =head1 NAME DateTime::Format::Excel - Convert between DateTime and Excel dates. =cut use strict; use 5.005; use Carp; use DateTime 0.1705; use vars qw( $VERSION ); $VERSION = '0.2901'; =head1 SYNOPSIS use DateTime::Format::Excel; # From Excel via class method: my $datetime = DateTime::Format::Excel->parse_datetime( 37680 ); print $datetime->ymd('.'); # '2003.02.28' # or via an object my $excel = DateTime::Format::Excel->new(); print $excel->parse_datetime( 25569 )->ymd; # '1970-01-01' # Back to Excel number: use DateTime; my $dt = DateTime->new( year => 1979, month => 7, day => 16 ); my $daynum = DateTime::Format::Excel->format_datetime( $dt ); print $daynum; # 29052 # or via an object my $other_daynum = $excel->format_datetime( $dt ); print $other_daynum; # 29052 =head1 DESCRIPTION Excel uses a different system for its dates than most Unix programs. This module allows you to convert between a few of the Excel raw formats and C<DateTime> objects, which can then be further converted via any of the other C<DateTime::Format::*> modules, or just with C<DateTime>'s methods. If you happen to be dealing with dates between S<1 Jan 1900> and S<1 Mar 1900> please read the notes on L<epochs|/EPOCHS>. If you're wanting to handle actual spreadsheet files, you may find L<Spreadsheet::WriteExcel> and L<Spreadsheet::ParseExcel> of use. =head1 CONSTRUCTORS =head2 new Creates a new C<DateTime::Format::Excel> instance. This is generally not required for simple operations. If you wish to use a different epoch, however, then you'll need to create an object. my $excel = DateTime::Format::Excel->new() my $copy = $excel->new(); It takes no parameters. If called on an existing object then it clones the object. =cut sub new { my $class = shift; croak "${class}->new takes no parameters." if @_; my $self = bless {}, ref($class)||$class; if (ref $class) { # If called on an object, clone $self->_epoch( scalar $class->epoch ); # and that's it. we don't store that much info per object } $self; } =head2 clone This method is provided For those who prefer to explicitly clone via a method called C<clone()>. If called as a class method it will die. my $clone = $original->clone(); =cut sub clone { my $self = shift; croak 'Calling object method as class method!' unless ref $self; return $self->new(); } =head1 CLASS/OBJECT METHODS These methods work as both class and object methods. =head2 parse_datetime Given an Excel day number, return a C<DateTime> object representing that date and time. # As a class method my $datetime = DateTime::format::Excel->parse_datetime( 37680 ); print $datetime->ymd('.'); # '2003.02.28' # Or via an object my $excel = DateTime::Format::Excel->new(); my $viaobj $excel->parse_datetime( 25569 ); print $viaobj->ymd; # '1970-01-01' =cut sub parse_datetime { my $self = shift; croak 'No date specified.' unless @_; #croak 'Invalid number of days' unless $_[0] =~ /^ (\d+ (?: \.\d+ )? ) $/x; croak 'Invalid number of days' unless $_[0] =~ /^ (\d+ (?: (\.\d+) )? ) $/x; my $days = $1; my $secs = $2 * 86400; my $dt = DateTime->new( $self->epoch ); $dt->add( days => $days, seconds => $secs ); return $dt; } =head2 format_datetime Given a C<DateTime> object, return the Excel daynum time. use DateTime; my $dt = DateTime->new( year => 1979, month => 7, day => 16 ); my $daynum = DateTime::Format::Excel->format_datetime( $dt ); print $daynum; # 29052 # or via an object my $excel = DateTime::Format::Excel->new(); $excel->epoch_mac(); # Let's imagine we want the Mac number my $mac_daynum = $excel->format_datetime( $dt ); print $mac_daynum; # 27590 =cut sub format_datetime { my $self = shift; croak 'No DateTime object specified.' unless @_; my $dt = shift; my $base = DateTime->new( $self->epoch ); my $excel = int( $dt->jd - $base->jd ); return $excel; } =begin _development =head1 BETA METHODS I don't really know whether durations should be handled by this module. They're nothing interesting. =cut sub parse_duration { my $self = shift; croak 'No duration specified.' unless @_; croak 'Invalid number of days' unless $_[0] =~ /^ (\d+ (?: \.\d+ )? ) $/x; my $days = $1; return DateTime::Duration->new( days => $days ); } sub format_duration { my $self = shift; croak 'No DateTime::Duration object specified.' unless @_; return $_[0]->delta_days(); } =end _development =head1 OBJECT METHODS =head2 epoch In scalar context, returns a string identifying the current epoch. my $epoch = $excel->epoch(); Currently either `mac' or `win' with the default being `win'. In list context, returns appropriate parameters with which to create a C<DateTime> object representing the start of the epoch. my $base = DateTime->new( $excel->epoch ); =cut sub epoch { $_[0]->_epoch() } =head2 epoch_mac Set the object to use a Macintosh epoch. $excel->epoch_mac(); # epoch is now 1 Jan 1904 Thus, 1 maps to C<2 Jan 1904>. =cut sub epoch_mac { $_[0]->_epoch('mac') } =head2 epoch_win Set the object to use a Windows Excel epoch. $excel->epoch_win(); # epoch is now 30 Dec 1899 Thus, 2 maps to C<1 Jan 1900>. =cut sub epoch_win { $_[0]->_epoch('win') } =head1 EPOCHS Excel uses ``number of days since S<31 Dec 1899>''. Naturally, Microsoft messed this up because they happened to believe that 1900 was a leap year. In this module, we assume what Psion assumed for their Abacus / Sheet program: S<1 Jan 1900> maps to 2 rather than 1. Thus, 61 maps to S<1 Mar 1900> in both Excel and this module (and Abacus). I<Excel for Macintosh> has a little option hidden away in its calculations preferences. It can use either the Windows epoch, or it can use the Macintosh epoch, which means that the day number is calculated as ``number of days since S< 1 Jan 1904>''. This module supports both notations. B<Note>: the results of this module have only been compared with I<Microsoft Excel for Macintosh 98> and I<Abacus> on the I<Acorn Pocket Book>. Where they have differed, I've opted for I<Abacus>'s result rather than I<Excel>'s. =cut { my %epochs = ( win => [ year => 1899, month => 12, day => 30 ], mac => [ year => 1904, month => 1, day => 1 ], ); sub _epoch { my $self = shift; if (@_) { croak 'Calling object method as class method!' unless ref $self; croak 'Invalid epoch' unless exists $epochs{$_[0]}; $self->{epoch} = $_[0]; return $self; # more useful this way, I feel. } else { my $epoch; $epoch = $self->{epoch} if ref $self; $epoch ||= 'win'; return wantarray ? @{ $epochs{$epoch} } : $epoch; } } } 1; __END__ =head1 THANKS Dave Rolsky (DROLSKY) for kickstarting the DateTime project. =head1 SUPPORT Support for this module is provided via the datetime@perl.org email list. See http://lists.perl.org/ for more details. Alternatively, log them via the CPAN RT system via the web or email: http://rt.cpan.org/NoAuth/ReportBug.html?Queue=DateTime%3A%3AFormat%3A%3AExcel bug-datetime-format-excel@rt.cpan.org This makes it much easier for me to track things and thus means your problem is less likely to be neglected. =head1 LICENCE AND COPYRIGHT Copyright E<copy> 2003 Iain Truskett. All rights reserved. This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself. The full text of the licences can be found in the F<Artistic> and F<COPYING> files included with this module. =head1 AUTHOR Originally written by Iain Truskett <spoon@cpan.org>, who died on December 29, 2003. Maintained by Dave Rolsky <autarch@urth.org>. =head1 SEE ALSO datetime@perl.org mailing list. http://datetime.perl.org/ L<perl>, L<DateTime>, L<Spreadsheet::WriteExcel> =cut
[guest - Fri Aug 27 11:07:41 2004]: Show quoted text
> The DateTime-Format-Excel package will correctly convert the date > portion of an Excel Date/Time format, but not the H:M:S. The bug > is in the parse_datetime function of Excel.pm > > The H:M:S is stored as a fraction where 1 second = 1 / (60*60*24). I > found useful information on this web page: > > http://www.mvps.org/dmcritchie/excel/datetime.htm > > Here is a test script that I used: > > #!/usr/local/bin/perl > > use strict; > use Spreadsheet::ParseExcel::Simple; > use DateTime::Format::Excel; > my $days; > my $secs; > > my $curtime = "37987.0000115741"; > $curtime =~ /^ (\d+ (?: (\.\d+) )? ) $/x; > print "days = $1\n"; > print "secs = $2\n"; > > my $datetime = DateTime::Format::Excel->parse_datetime($curtime); > print $datetime->strftime("%F %r") . "\n"; > print $datetime->strftime("%F %T") . "\n"; > print $datetime->strftime("%F %z") . "\n"; > > Attached are the changes I made to the .2901 version of Excel.pm to > fix the problem.
If you could send this in the form of a patch, I'd probably be interested in applying it. A patch that included doc and test updates would be even better ;)
From: cpan [...] pjedwards.co.uk
On Thu Sep 09 10:08:11 2004, DROLSKY wrote: Show quoted text
> [guest - Fri Aug 27 11:07:41 2004]: >
> > The DateTime-Format-Excel package will correctly convert the date > > portion of an Excel Date/Time format, but not the H:M:S. The bug > > is in the parse_datetime function of Excel.pm > > > > The H:M:S is stored as a fraction where 1 second = 1 / (60*60*24). I > > found useful information on this web page: > > > > http://www.mvps.org/dmcritchie/excel/datetime.htm > > > > Here is a test script that I used: > > > > #!/usr/local/bin/perl > > > > use strict; > > use Spreadsheet::ParseExcel::Simple; > > use DateTime::Format::Excel; > > my $days; > > my $secs; > > > > my $curtime = "37987.0000115741"; > > $curtime =~ /^ (\d+ (?: (\.\d+) )? ) $/x; > > print "days = $1\n"; > > print "secs = $2\n"; > > > > my $datetime = DateTime::Format::Excel->parse_datetime($curtime); > > print $datetime->strftime("%F %r") . "\n"; > > print $datetime->strftime("%F %T") . "\n"; > > print $datetime->strftime("%F %z") . "\n"; > > > > Attached are the changes I made to the .2901 version of Excel.pm to > > fix the problem.
> > If you could send this in the form of a patch, I'd probably be > interested in applying it. A patch that included doc and test updates > would be even better ;)
Thanks for all the DateTime modules. I also found myself adding support for H:M:S to this module. Here is my patch: File DATETIME-FORMAT-EXCEL-0_29]T5440004970.TMP;1 130 croak 'Invalid number of days' unless $_[0] =~ /^ (\d+ (?: \.\d+ )? ) $/x; 131 my $excel = $1; 132 133 my $dt = DateTime->new( $self->epoch ); 134 $dt->add( days => $excel ); 135 136 return $dt; ****** File DATETIME-FORMAT-EXCEL-0_29.LIB.DATETIME.FORMAT]EXCEL.PM;21 130 croak 'Invalid number of days' unless $_[0] =~ /^ (\d+ (?: (\.\d+ ) )? ) $/x; 131 my $excel_days = $1; 132 my $excel_secs = $2; 133 my $dt = DateTime->new( $self->epoch ); 134 if(defined $excel_secs){ 135 $excel_secs = $excel_secs * 86400; # RT7498 136 my $excel_nanoseconds = ($excel_secs - int($excel_secs)) * 1_000_000_000; 137 $dt->add( days => $excel_days , 138 seconds => $excel_secs, 139 nanoseconds => $excel_nanoseconds); 140 } else { 141 $dt->add( days => $excel_days ); 142 } 143 return $dt; ************ ************ File DATETIME-FORMAT-EXCEL-0_29]T5440004970.TMP;1 164 my $excel = int( $dt->jd - $base->jd ); 165 ****** File DATETIME-FORMAT-EXCEL-0_29.LIB.DATETIME.FORMAT]EXCEL.PM;21 171 my $excel = $dt->jd - $base->jd; # RT7498 172 ************ It differs from the original suggested patch in this bug as it takes into account fractions of a second (nanoseconds), without this I was observing rounding behaviour. Here is a test file: type [.t]decimal.t use strict; use Test::More tests => 28; use DateTime::Format::Excel; my @test_data = ( { year => 2003, month => 2, day => 28, hour => 0, minute => 0, second => 0, excel => 37680, iso8601 => '2003-02-28T00:00:00', }, { year => 1899, month => 12, day => 31, hour => 0, minute => 0, second => 0, excel => 1, iso8601 => '1899-12-31T00:00:00', }, { year => 1900, month => 1, day => 1, hour => 0, minute => 0, second => 0, excel => 2, iso8601 => '1900-01-01T00:00:00', }, { year => 1900, month => 1, day => 2, hour => 0, minute => 0, second => 0, excel => 3, iso8601 => '1900-01-02T00:00:00', }, { year => 1900, month => 1, day => 3, hour => 0, minute => 0, second => 0, excel => 4, iso8601 => '1900-01-03T00:00:00', }, { year => 1970, month => 1, day => 1, hour => 0, minute => 0, second => 0, excel => 25569, iso8601 => '1970-01-01T00:00:00', }, { year => 9999, month => 12, day => 31, hour => 0, minute => 0, second => 0, excel => 2958465, iso8601 => '9999-12-31T00:00:00', }, { year => 1900, month => 2, day => 28, hour => 0, minute => 0, second => 0, excel => 60, iso8601 => '1900-02-28T00:00:00', }, { year => 1900, month => 3, day => 1, hour => 0, minute => 0, second => 0, excel => 61, iso8601 => '1900-03-01T00:00:00', }, { year => 2007, month => 9, day => 9, hour => 23, minute => 56, second => 29, excel => 39334.9975578706, iso8601 => '2007-09-09T23:56:29', }, { year => 2007, month => 9, day => 9, hour => 23, minute => 56, second => 30, excel => 39334.9975694446, iso8601 => '2007-09-09T23:56:30', }, { year => 2007, month => 9, day => 9, hour => 23, minute => 56, second => 45, excel => 39334.9977430557, iso8601 => '2007-09-09T23:56:45', }, { year => 1985, month => 10, day => 26, hour => 1, minute => 17, second => 00, excel => 31346.0534722223, iso8601 => '1985-10-26T01:17:00', }, { year => 1955, month => 11, day => 12, hour => 9, minute => 28, second => 00, excel => 20405.3944444442, iso8601 => '1955-11-12T09:28:00', }, ); foreach my $test_data (@test_data){ my $dt = DateTime->new( year => $test_data->{year}, month => $test_data->{month}, day => $test_data->{day}, hour => $test_data->{hour}, minute => $test_data->{minute}, second => $test_data->{second} ); my $got_excel = DateTime::Format::Excel->format_datetime( $dt ); is ( $got_excel => $test_data->{excel} , " \$got_excel ($got_excel) ~ excel ($test_data->{excel})"); my $got_dt = DateTime::Format::Excel->parse_datetime( $test_data->{excel} ); my $got_iso8601 = $got_dt->iso8601(); is ( $got_iso8601 => $test_data->{iso8601} , " \$got_iso8601 ($got_iso8601) ~ iso8601 ($test_data->{iso8601})"); } Let me know if you would prefer a patch in a different format. Anyone using this with DateTime objects that have H:M:S:N specified and these are not 0:0:0:0, will now get a floating point number back, previously the number was rounded to an int. (I can't see any other dists requiring this module: http://cpants.perl.org/dist/DateTime-Format-Excel) Cheers, Peter (Stig) Edwards
Subject: Re: [rt.cpan.org #7498] DateTime-Format-Excel does not convert the seconds portion of an Excel Date/Time value
Date: Tue, 11 Sep 2007 09:37:54 -0500 (CDT)
To: "cpan [...] pjedwards.co.uk via RT" <bug-DateTime-Format-Excel [...] rt.cpan.org>
From: Dave Rolsky <autarch [...] urth.org>
On Tue, 11 Sep 2007, cpan@pjedwards.co.uk via RT wrote: Show quoted text
> I also found myself adding support for H:M:S to this module. Here is my > patch: > > File DATETIME-FORMAT-EXCEL-0_29]T5440004970.TMP;1 > 130 croak 'Invalid number of days' unless $_[0] =~ /^ (\d+ (?: > \.\d+ )? ) $/x; > 131 my $excel = $1; > 132 > 133 my $dt = DateTime->new( $self->epoch ); > 134 $dt->add( days => $excel ); > 135 > 136 return $dt; > ****** > File DATETIME-FORMAT-EXCEL-0_29.LIB.DATETIME.FORMAT]EXCEL.PM;21 > 130 croak 'Invalid number of days' unless $_[0] =~ /^ (\d+ (?: > (\.\d+ ) )? ) $/x; > 131 my $excel_days = $1; > 132 my $excel_secs = $2; > 133 my $dt = DateTime->new( $self->epoch ); > 134 if(defined $excel_secs){ > 135 $excel_secs = $excel_secs * 86400; # RT7498 > 136 my $excel_nanoseconds = ($excel_secs - int($excel_secs)) > * 1_000_000_000; > 137 $dt->add( days => $excel_days , > 138 seconds => $excel_secs, > 139 nanoseconds => $excel_nanoseconds); > 140 } else { > 141 $dt->add( days => $excel_days ); > 142 } > 143 return $dt;
That's a very weird "patch". Did you generate it with the diff progrma? If not, can you use "diff -Nru" to make a proper patch for the whole distro (so as to include the new test). -dave /*=================================================== VegGuide.Org www.BookIRead.com Your guide to all that's veg. My book blog ===================================================*/
Show quoted text
> That's a very weird "patch". Did you generate it with the diff
progrma? If Show quoted text
> not, can you use "diff -Nru" to make a proper patch for the whole distro > (so as to include the new test). > > -dave
I was on VMS. Here is the "diff -Nru" done on Linux against version 0.2901 Cheers, Peter (Stig) Edwards
diff -Nru ../DateTime-Format-Excel-0.2901_orig/MANIFEST ./MANIFEST --- ../DateTime-Format-Excel-0.2901_orig/MANIFEST 2004-01-26 14:06:42.000000000 -0500 +++ ./MANIFEST 2007-09-11 16:40:04.000000000 -0400 @@ -14,5 +14,6 @@ t/00signature.t t/basic.t t/clone.t +t/decimal.t SIGNATURE Added here by Module::Build diff -Nru ../DateTime-Format-Excel-0.2901_orig/lib/DateTime/Format/Excel.pm ./lib/DateTime/Format/Excel.pm --- ../DateTime-Format-Excel-0.2901_orig/lib/DateTime/Format/Excel.pm 2004-01-26 14:04:02.000000000 -0500 +++ ./lib/DateTime/Format/Excel.pm 2007-09-11 16:42:14.000000000 -0400 @@ -127,12 +127,19 @@ { my $self = shift; croak 'No date specified.' unless @_; - croak 'Invalid number of days' unless $_[0] =~ /^ (\d+ (?: \.\d+ )? ) $/x; - my $excel = $1; - + croak 'Invalid number of days' unless $_[0] =~ /^ (\d+ (?: (\.\d+ ) )? ) $/x; + my $excel_days = $1; + my $excel_secs = $2; my $dt = DateTime->new( $self->epoch ); - $dt->add( days => $excel ); - + if(defined $excel_secs){ + $excel_secs = $excel_secs * 86400; # RT7498 + my $excel_nanoseconds = ($excel_secs - int($excel_secs)) * 1_000_000_000; + $dt->add( days => $excel_days, + seconds => $excel_secs, + nanoseconds => $excel_nanoseconds); + } else { + $dt->add( days => $excel_days ); + } return $dt; } @@ -161,7 +168,7 @@ my $dt = shift; my $base = DateTime->new( $self->epoch ); - my $excel = int( $dt->jd - $base->jd ); + my $excel = $dt->jd - $base->jd; # RT7498 return $excel; } diff -Nru ../DateTime-Format-Excel-0.2901_orig/t/decimal.t ./t/decimal.t --- ../DateTime-Format-Excel-0.2901_orig/t/decimal.t 1969-12-31 19:00:00.000000000 -0500 +++ ./t/decimal.t 2007-09-11 16:39:13.000000000 -0400 @@ -0,0 +1,106 @@ +use strict; +use Test::More tests => 28; +use DateTime::Format::Excel; + +my @test_data = ( + { + year => 2003, month => 2, day => 28, + hour => 0, minute => 0, second => 0, + excel => 37680, + iso8601 => '2003-02-28T00:00:00', + }, + { + year => 1899, month => 12, day => 31, + hour => 0, minute => 0, second => 0, + excel => 1, + iso8601 => '1899-12-31T00:00:00', + }, + { + year => 1900, month => 1, day => 1, + hour => 0, minute => 0, second => 0, + excel => 2, + iso8601 => '1900-01-01T00:00:00', + }, + { + year => 1900, month => 1, day => 2, + hour => 0, minute => 0, second => 0, + excel => 3, + iso8601 => '1900-01-02T00:00:00', + }, + { + year => 1900, month => 1, day => 3, + hour => 0, minute => 0, second => 0, + excel => 4, + iso8601 => '1900-01-03T00:00:00', + }, + { + year => 1970, month => 1, day => 1, + hour => 0, minute => 0, second => 0, + excel => 25569, + iso8601 => '1970-01-01T00:00:00', + }, + { + year => 9999, month => 12, day => 31, + hour => 0, minute => 0, second => 0, + excel => 2958465, + iso8601 => '9999-12-31T00:00:00', + }, + { + year => 1900, month => 2, day => 28, + hour => 0, minute => 0, second => 0, + excel => 60, + iso8601 => '1900-02-28T00:00:00', + }, + { + year => 1900, month => 3, day => 1, + hour => 0, minute => 0, second => 0, + excel => 61, + iso8601 => '1900-03-01T00:00:00', + }, + { + year => 2007, month => 9, day => 9, + hour => 23, minute => 56, second => 29, + excel => 39334.9975578706, + iso8601 => '2007-09-09T23:56:29', + }, + { + year => 2007, month => 9, day => 9, + hour => 23, minute => 56, second => 30, + excel => 39334.9975694446, + iso8601 => '2007-09-09T23:56:30', + }, + { + year => 2007, month => 9, day => 9, + hour => 23, minute => 56, second => 45, + excel => 39334.9977430557, + iso8601 => '2007-09-09T23:56:45', + }, + { + year => 1985, month => 10, day => 26, + hour => 1, minute => 17, second => 00, + excel => 31346.0534722223, + iso8601 => '1985-10-26T01:17:00', + }, + { + year => 1955, month => 11, day => 12, + hour => 9, minute => 28, second => 00, + excel => 20405.3944444442, + iso8601 => '1955-11-12T09:28:00', + }, +); + +foreach my $test_data (@test_data){ + my $dt = DateTime->new( + year => $test_data->{year}, + month => $test_data->{month}, + day => $test_data->{day}, + hour => $test_data->{hour}, + minute => $test_data->{minute}, + second => $test_data->{second} + ); + my $got_excel = DateTime::Format::Excel->format_datetime( $dt ); + is ( $got_excel => $test_data->{excel} , " \$got_excel ($got_excel) ~ excel ($test_data->{excel})"); + my $got_dt = DateTime::Format::Excel->parse_datetime( $test_data->{excel} ); + my $got_iso8601 = $got_dt->iso8601(); + is ( $got_iso8601 => $test_data->{iso8601} , " \$got_iso8601 ($got_iso8601) ~ iso8601 ($test_data->{iso8601})"); +}
Hi, I just took over this module from Dave, and I'll release a new v0.30 soon. That will have this bug fixed.
Sorry for the long delay, there simply was nobody in charge of this module who had time to do anything with it.