diff --git a/SpreadSheetPlugin/lib/Foswiki/Plugins/SpreadSheetPlugin/Calc.pm b/SpreadSheetPlugin/lib/Foswiki/Plugins/SpreadSheetPlugin/Calc.pm index 872808cb6e..b0a4d1c115 100644 --- a/SpreadSheetPlugin/lib/Foswiki/Plugins/SpreadSheetPlugin/Calc.pm +++ b/SpreadSheetPlugin/lib/Foswiki/Plugins/SpreadSheetPlugin/Calc.pm @@ -1104,7 +1104,7 @@ sub _FORMATTIME { #elsif ( $theFunc =~ /^(FORMATTIME|FORMATGMTIME)$/ ) { my ( $time, $str ) = split( /,\s*/, $_[0], 2 ); - if ( $time =~ /([0-9]+)/ ) { + if ( $time =~ /(-?[0-9]+)/ ) { $time = $1; } else { @@ -1123,7 +1123,7 @@ sub _FORMATTIMEDIFF { $prec = int( _getNumber($prec) - 1 ); $prec = 0 if ( $prec < 0 ); $time = _getNumber($time); - $time = 0 if ( $time < 0 ); + $time *= -1 if ( $time < 0 ); my @unit = ( 0, 0, 0, 0, 0, 0 ); # sec, min, hours, days, month, years my @factor = ( 1, 60, 60, 24, 30.4166, 12 ); # sec, min, hours, days, month, years @@ -1212,8 +1212,8 @@ sub _TIMEADD { $time = 0 unless ($time); $value = 0 unless ($value); $scale = "" unless ($scale); - $time =~ s/.*?([0-9]+).*/$1/ || 0; - $value =~ s/.*?(\-?[0-9\.]+).*/$1/ || 0; + $time =~ s/.*?(-?[0-9]+).*/$1/ || 0; + $value =~ s/.*?(-?[0-9\.]+).*/$1/ || 0; $value *= 60 if ( $scale =~ /^min/i ); $value *= 3600 if ( $scale =~ /^hou/i ); $value *= 3600 * 24 if ( $scale =~ /^day/i ); @@ -1232,8 +1232,8 @@ sub _TIMEDIFF { $scale ||= ''; $time1 = 0 unless ($time1); $time2 = 0 unless ($time2); - $time1 =~ s/.*?([0-9]+).*/$1/ || 0; - $time2 =~ s/.*?([0-9]+).*/$1/ || 0; + $time1 =~ s/[^-0-9]*?(-?[0-9]+).*/$1/ || 0; + $time2 =~ s/[^-0-9]*?(-?[0-9]+).*/$1/ || 0; my $result = $time2 - $time1; $result /= 60 if ( $scale =~ /^min/i ); $result /= 3600 if ( $scale =~ /^hou/i ); @@ -1738,7 +1738,7 @@ m|([Dd][Oo][Yy])\s*([0-9]{4})[\.]([0-9]{1,3})[\.]([0-9]{1,2})[\.]([0-9]{1,2})[\. { # "DOY2003.122.23.15.59", "DOY2003.2.9.3.5.9" i.e. year.ddd.hh.mm.ss - $year = $2 - 1900; + $year = $2; $day = $3; $hour = $4; $min = $5; @@ -1750,7 +1750,7 @@ m|([Dd][Oo][Yy])\s*([0-9]{4})[\.]([0-9]{1,3})[\.]([0-9]{1,2})[\.]([0-9]{1,2})| { # "DOY2003.122.23.15", "DOY2003.2.9.3" i.e. year.ddd.hh.mm - $year = $2 - 1900; + $year = $2; $day = $3; $hour = $4; $min = $5; @@ -1760,14 +1760,14 @@ m|([Dd][Oo][Yy])\s*([0-9]{4})[\.]([0-9]{1,3})[\.]([0-9]{1,2})[\.]([0-9]{1,2})| { # "DOY2003.122.23", "DOY2003.2.9" i.e. year.ddd.hh - $year = $2 - 1900; + $year = $2; $day = $3; $hour = $4; } elsif ( $theText =~ m|([Dd][Oo][Yy])\s*([0-9]{4})[\.]([0-9]{1,3})| ) { # "DOY2003.122", "DOY2003.2" i.e. year.ddd - $year = $2 - 1900; + $year = $2; $day = $3; } elsif ( $theText =~ @@ -1778,7 +1778,7 @@ m|([0-9]{1,2})[-\s/]+([A-Z][a-z][a-z])[-\s/]+([0-9]{4})[-\s/]+([0-9]{1,2}):([0-9 # "31 Dec 2003 - 23:59:59", "31-Dec-2003 - 23:59:59", "31 Dec 2003 - 23:59:59 - any suffix" $day = $1; $mon = $mon2num{$2} || 0; - $year = $3 - 1900; + $year = $3; $hour = $4; $min = $5; $sec = $6; @@ -1791,7 +1791,7 @@ m|([0-9]{1,2})[-\s/]+([A-Z][a-z][a-z])[-\s/]+([0-9]{4})[-\s/]+([0-9]{1,2}):([0-9 # "31 Dec 2003 - 23:59", "31-Dec-2003 - 23:59", "31 Dec 2003 - 23:59 - any suffix" $day = $1; $mon = $mon2num{$2} || 0; - $year = $3 - 1900; + $year = $3; $hour = $4; $min = $5; } @@ -1803,8 +1803,8 @@ m|([0-9]{1,2})[-\s/]+([A-Z][a-z][a-z])[-\s/]+([0-9]{4})[-\s/]+([0-9]{1,2}):([0-9 $day = $1; $mon = $mon2num{$2} || 0; $year = $3; - $year += 100 if ( $year < 80 ); # "05" --> "105" (leave "99" as is) - $year -= 1900 if ( $year >= 1900 ); # "2005" --> "105" + $year += 2000 if ( $year < 80 ); + $year += 1900 if ( $year < 100 and $year >= 80 ); } elsif ( $theText =~ m|([0-9]{4})[-/\.]([0-9]{1,2})[-/\.]([0-9]{1,2})[-/\.\,\s]+([0-9]{1,2})[-\:/\.]([0-9]{1,2})[-\:/\.]([0-9]{1,2})| @@ -1812,7 +1812,7 @@ m|([0-9]{4})[-/\.]([0-9]{1,2})[-/\.]([0-9]{1,2})[-/\.\,\s]+([0-9]{1,2})[-\:/\.]( { # "2003/12/31 23:59:59", "2003-12-31-23-59-59", "2003.12.31.23.59.59" - $year = $1 - 1900; + $year = $1; $mon = $2 - 1; $day = $3; $hour = $4; @@ -1825,7 +1825,7 @@ m|([0-9]{4})[-/\.]([0-9]{1,2})[-/\.]([0-9]{1,2})[-/\.\,\s]+([0-9]{1,2})[-\:/\.]( { # "2003/12/31 23:59", "2003-12-31-23-59", "2003.12.31.23.59" - $year = $1 - 1900; + $year = $1; $mon = $2 - 1; $day = $3; $hour = $4; @@ -1834,7 +1834,7 @@ m|([0-9]{4})[-/\.]([0-9]{1,2})[-/\.]([0-9]{1,2})[-/\.\,\s]+([0-9]{1,2})[-\:/\.]( elsif ( $theText =~ m|([0-9]{4})[-/]([0-9]{1,2})[-/]([0-9]{1,2})| ) { # "2003/12/31", "2003-12-31" - $year = $1 - 1900; + $year = $1; $mon = $2 - 1; $day = $3; } @@ -1845,8 +1845,8 @@ m|([0-9]{4})[-/\.]([0-9]{1,2})[-/\.]([0-9]{1,2})[-/\.\,\s]+([0-9]{1,2})[-\:/\.]( $year = $3; $mon = $1 - 1; $day = $2; - $year += 100 if ( $year < 80 ); # "05" --> "105" (leave "99" as is) - $year -= 1900 if ( $year >= 1900 ); # "2005" --> "105" + $year += 2000 if ( $year < 80 ); + $year += 1900 if ( $year < 100 and $year >= 80 ); } else { diff --git a/SpreadSheetPlugin/test/unit/SpreadSheetPlugin/SpreadSheetPluginTests.pm b/SpreadSheetPlugin/test/unit/SpreadSheetPlugin/SpreadSheetPluginTests.pm index 7249db2116..fef1b3c1d9 100755 --- a/SpreadSheetPlugin/test/unit/SpreadSheetPlugin/SpreadSheetPluginTests.pm +++ b/SpreadSheetPlugin/test/unit/SpreadSheetPlugin/SpreadSheetPluginTests.pm @@ -406,48 +406,61 @@ sub test_FORMAT { sub test_FORMATGMTIME { my ($this) = @_; - $this->assert( $this->CALC('$FORMATGMTIME(1041379200, $day $mon $year)') eq - '01 Jan 2003' ); - $this->assert_equals( - '2004-W53-6', - $this->CALC( - '$FORMATGMTIME($TIME(2005-01-01), $isoweek($year-W$wk-$day))') - ); - $this->assert_equals( - '2009-W01-1', - $this->CALC( - '$FORMATGMTIME($TIME(2008-12-29), $isoweek($year-W$wk-$day))') - ); + $this->assert_equals( '01 Jan 1970 - 00 00 00', + $this->CALC('$FORMATGMTIME(0, $day $mon $year - $hour $min $sec)') ); + $this->assert_equals( '31 Dec 1969 - 23 59 59', + $this->CALC('$FORMATGMTIME(-1, $day $mon $year - $hour $min $sec)') ); + $this->assert_equals( '19 Jan 2038 - 03 14 08', + $this->CALC('$FORMATGMTIME(2147483648, $day $mon $year - $hour $min $sec)') ); + $this->assert_equals( '13 Dec 1901 - 20 45 51', + $this->CALC('$FORMATGMTIME(-2147483649, $day $mon $year - $hour $min $sec)') ); + + $this->assert_equals( '2004-W53-6', + $this->CALC('$FORMATGMTIME($TIME(2005-01-01), $isoweek($year-W$wk-$day))') ); + $this->assert_equals( '2009-W01-1', + $this->CALC('$FORMATGMTIME($TIME(2008-12-29), $isoweek($year-W$wk-$day))') ); } sub test_FORMATTIME { my ($this) = @_; - $this->assert( $this->CALC('$FORMATTIME(0, $year/$month/$day GMT)') eq - '1970/01/01 GMT' ); - $this->assert_equals( - '2004-W53-6 GMT', - $this->CALC( - '$FORMATTIME($TIME(2005-01-01 gmt), $isoweek($year-W$wk-$day) GMT)') - ); - $this->assert_equals( - '2009-W01-1 GMT', - $this->CALC( - '$FORMATTIME($TIME(2008-12-29 gmt), $isoweek($year-W$wk-$day) GMT)') - ); + + $this->assert_equals( '1970/01/01 00:00:00 GMT', + $this->CALC('$FORMATTIME(0, $year/$month/$day $hour:$minute:$second GMT)') ); + $this->assert_equals( '1969/12/31 23:59:59 GMT', + $this->CALC('$FORMATTIME(-1, $year/$month/$day $hour:$minute:$second GMT)') ); + $this->assert_equals( '2038/01/19 03:14:08 GMT', + $this->CALC('$FORMATTIME(2147483648, $year/$month/$day $hour:$minute:$second GMT)') ); + $this->assert_equals( '1901/12/13 20:45:51 GMT', + $this->CALC('$FORMATTIME(-2147483649, $year/$month/$day $hour:$minute:$second GMT)') ); + + $this->assert_equals( '2004-W53-6 GMT', + $this->CALC('$FORMATTIME($TIME(2005-01-01 gmt), $isoweek($year-W$wk-$day) GMT)') ); + $this->assert_equals( '2009-W01-1 GMT', + $this->CALC('$FORMATTIME($TIME(2008-12-29 gmt), $isoweek($year-W$wk-$day) GMT)') ); } sub test_FORMATTIMEDIFF { my ($this) = @_; - $this->assert( $this->CALC('$FORMATTIMEDIFF(min, 1, 200)') eq '3 hours' ); - $this->assert( $this->CALC('$FORMATTIMEDIFF(min, 2, 200)') eq - '3 hours and 20 minutes' ); - $this->assert( $this->CALC('$FORMATTIMEDIFF(min, 1, 1640)') eq '1 day' ); - $this->assert( - $this->CALC('$FORMATTIMEDIFF(min, 2, 1640)') eq '1 day and 3 hours' ); - $this->assert( $this->CALC('$FORMATTIMEDIFF(min, 3, 1640)') eq - '1 day, 3 hours and 20 minutes' ); + + $this->assert_equals( '0 minutes', + $this->CALC('$FORMATTIMEDIFF(min, 1, 0)') ); + $this->assert_equals( '3 hours', + $this->CALC('$FORMATTIMEDIFF(min, 1, 200)') ); + $this->assert_equals( '3 hours and 20 minutes', + $this->CALC('$FORMATTIMEDIFF(min, 2, 200)') ); + $this->assert_equals( '1 day', + $this->CALC('$FORMATTIMEDIFF(min, 1, 1640)') ); + $this->assert_equals( '1 day and 3 hours', + $this->CALC('$FORMATTIMEDIFF(min, 2, 1640)') ); + $this->assert_equals( '1 day, 3 hours and 20 minutes', + $this->CALC('$FORMATTIMEDIFF(min, 3, 1640)') ); + + $this->assert_equals( '0 minutes', + $this->CALC('$FORMATTIMEDIFF(min, 1, -0)') ); + $this->assert_equals( '3 hours and 20 minutes', + $this->CALC('$FORMATTIMEDIFF(min, 2, -200)') ); } sub test_GET_SET { @@ -1225,8 +1238,25 @@ sub test_T { sub test_TIME { my ($this) = @_; - $this->assert_equals( '1066089600', $this->CALC('$TIME(2003/10/14 GMT)') ); - $this->assert_equals( '1066089600', $this->CALC('$TIME(DOY2003.287)') ); + + $this->assert_equals( '0', + $this->CALC('$TIME(1970/01/01 GMT)') ); + $this->assert_equals( '-31536000', + $this->CALC('$TIME(1969/01/01 GMT)') ); + $this->assert_equals( '0', + $this->CALC('$TIME(1970/01/01 - 00:00:00 GMT)') ); + $this->assert_equals( '-1', + $this->CALC('$TIME(1969/12/31 - 23:59:59 GMT)') ); + $this->assert_equals( '2147483648', + $this->CALC('$TIME(2038/01/19 - 03:14:08 GMT)') ); + $this->assert_equals( '-2147483649', + $this->CALC('$TIME(1901/12/13 - 20:45:51 GMT)') ); + + $this->assert_equals( '1066089600', + $this->CALC('$TIME(2003/10/14 GMT)') ); + $this->assert_equals( '1066089600', + $this->CALC('$TIME(DOY2003.287)') ); + $this->assert_equals( $this->CALC('$TIME(2003/12/31 - 23:59:59)'), $this->CALC('$TIME(DOY2003.365.23.59.59)') @@ -1266,8 +1296,29 @@ sub test_TIMEADD { sub test_TIMEDIFF { my ($this) = @_; - $this->assert( - $this->CALC('$TIMEDIFF($TIME(), $EVAL($TIME()+90), minute)') == 1.5 ); + + $this->assert_equals( '1.5', + $this->CALC('$TIMEDIFF($TIME(), $EVAL($TIME()+90), minute)') ); + + $this->assert_equals( '1', + int( $this->CALC('$TIMEDIFF($TIME(2008/09/28 GMT), $TIME(2010/01/28 GMT), years)') ) ); + $this->assert_equals( '16', + int( $this->CALC('$TIMEDIFF($TIME(2008/09/28 GMT), $TIME(2010/01/28 GMT), month)') ) ); + $this->assert_equals( '487', + int( $this->CALC('$TIMEDIFF($TIME(2008/09/28 GMT), $TIME(2010/01/28 GMT), days)') ) ); + $this->assert_equals( '11688', + int( $this->CALC('$TIMEDIFF($TIME(2008/09/28 GMT), $TIME(2010/01/28 GMT), hours)') ) ); + $this->assert_equals( '701280', + int( $this->CALC('$TIMEDIFF($TIME(2008/09/28 GMT), $TIME(2010/01/28 GMT), minutes)') ) ); + $this->assert_equals( '42076800', + int( $this->CALC('$TIMEDIFF($TIME(2008/09/28 GMT), $TIME(2010/01/28 GMT), seconds)') ) ); + + $this->assert_equals( '18', + int( $this->CALC('$TIMEDIFF($TIME(1990/1/1 GMT), $TIME(2008/1/1 GMT), year)') ) ); + $this->assert_equals( '38', + int( $this->CALC('$TIMEDIFF($TIME(1970/1/1 GMT), $TIME(2008/1/1 GMT), year)') ) ); + $this->assert_equals( '58', + int( $this->CALC('$TIMEDIFF($TIME(1950/1/1 GMT), $TIME(2008/1/1 GMT), year)') ) ); } sub test_TODAY {