Changes to Date/Time conversion functions to use DateTime objects internally rather than unix timestamps;

Changes to Date/Time methods to make them more intuitive and correct (eg `excelToTimestamp` rather than `excelToPHP`)
TODO - Still need to write unit tests, and convert Examples to use the new names
This commit is contained in:
MarkBaker 2016-08-13 11:49:01 +01:00
parent 0ffd678c65
commit 745499cc55
6 changed files with 116 additions and 122 deletions

View File

@ -123,7 +123,7 @@ class DateTime
private static function adjustDateByMonths($dateValue = 0, $adjustmentMonths = 0)
{
// Execute function
$PHPDateObject = \PHPExcel\Shared\Date::excelToPHPObject($dateValue);
$PHPDateObject = \PHPExcel\Shared\Date::excelToDateTimeObject($dateValue);
$oMonth = (int) $PHPDateObject->format('m');
$oYear = (int) $PHPDateObject->format('Y');
@ -218,10 +218,10 @@ class DateTime
$retValue = (float) $excelDateTime;
break;
case Functions::RETURNDATE_PHP_NUMERIC:
$retValue = (integer) \PHPExcel\Shared\Date::excelToPHP($excelDateTime);
$retValue = (integer) \PHPExcel\Shared\Date::excelToTimestamp($excelDateTime);
break;
case Functions::RETURNDATE_PHP_OBJECT:
$retValue = \PHPExcel\Shared\Date::excelToPHPObject($excelDateTime);
$retValue = \PHPExcel\Shared\Date::excelToDateTimeObject($excelDateTime);
break;
}
date_default_timezone_set($saveTimeZone);
@ -341,9 +341,9 @@ class DateTime
case Functions::RETURNDATE_EXCEL:
return (float) $excelDateValue;
case Functions::RETURNDATE_PHP_NUMERIC:
return (integer) \PHPExcel\Shared\Date::excelToPHP($excelDateValue);
return (integer) \PHPExcel\Shared\Date::excelToTimestamp($excelDateValue);
case Functions::RETURNDATE_PHP_OBJECT:
return \PHPExcel\Shared\Date::excelToPHPObject($excelDateValue);
return \PHPExcel\Shared\Date::excelToDateTimeObject($excelDateValue);
}
}
@ -435,7 +435,7 @@ class DateTime
}
return (float) \PHPExcel\Shared\Date::formattedPHPToExcel($calendar, 1, $date, $hour, $minute, $second);
case Functions::RETURNDATE_PHP_NUMERIC:
return (integer) \PHPExcel\Shared\Date::excelToPHP(\PHPExcel\Shared\Date::formattedPHPToExcel(1970, 1, 1, $hour, $minute, $second)); // -2147468400; // -2147472000 + 3600
return (integer) \PHPExcel\Shared\Date::excelToTimestamp(\PHPExcel\Shared\Date::formattedPHPToExcel(1970, 1, 1, $hour, $minute, $second)); // -2147468400; // -2147472000 + 3600
case Functions::RETURNDATE_PHP_OBJECT:
$dayAdjust = 0;
if ($hour < 0) {
@ -584,7 +584,7 @@ class DateTime
case Functions::RETURNDATE_EXCEL:
return (float) $excelDateValue;
case Functions::RETURNDATE_PHP_NUMERIC:
return (integer) \PHPExcel\Shared\Date::excelToPHP($excelDateValue);
return (integer) \PHPExcel\Shared\Date::excelToTimestamp($excelDateValue);
case Functions::RETURNDATE_PHP_OBJECT:
return new \DateTime($PHPDateArray['year'].'-'.$PHPDateArray['month'].'-'.$PHPDateArray['day'].' 00:00:00');
}
@ -645,7 +645,7 @@ class DateTime
case Functions::RETURNDATE_EXCEL:
return (float) $excelDateValue;
case Functions::RETURNDATE_PHP_NUMERIC:
return (integer) $phpDateValue = \PHPExcel\Shared\Date::excelToPHP($excelDateValue+25569) - 3600;
return (integer) $phpDateValue = \PHPExcel\Shared\Date::excelToTimestamp($excelDateValue+25569) - 3600;
case Functions::RETURNDATE_PHP_OBJECT:
return new \DateTime('1900-01-01 '.$PHPDateArray['hour'].':'.$PHPDateArray['minute'].':'.$PHPDateArray['second']);
}
@ -685,12 +685,12 @@ class DateTime
// Execute function
$difference = $endDate - $startDate;
$PHPStartDateObject = \PHPExcel\Shared\Date::excelToPHPObject($startDate);
$PHPStartDateObject = \PHPExcel\Shared\Date::excelToDateTimeObject($startDate);
$startDays = $PHPStartDateObject->format('j');
$startMonths = $PHPStartDateObject->format('n');
$startYears = $PHPStartDateObject->format('Y');
$PHPEndDateObject = \PHPExcel\Shared\Date::excelToPHPObject($endDate);
$PHPEndDateObject = \PHPExcel\Shared\Date::excelToDateTimeObject($endDate);
$endDays = $PHPEndDateObject->format('j');
$endMonths = $PHPEndDateObject->format('n');
$endYears = $PHPEndDateObject->format('Y');
@ -805,12 +805,12 @@ class DateTime
}
// Execute function
$PHPStartDateObject = \PHPExcel\Shared\Date::excelToPHPObject($startDate);
$PHPStartDateObject = \PHPExcel\Shared\Date::excelToDateTimeObject($startDate);
$startDay = $PHPStartDateObject->format('j');
$startMonth = $PHPStartDateObject->format('n');
$startYear = $PHPStartDateObject->format('Y');
$PHPEndDateObject = \PHPExcel\Shared\Date::excelToPHPObject($endDate);
$PHPEndDateObject = \PHPExcel\Shared\Date::excelToDateTimeObject($endDate);
$endDay = $PHPEndDateObject->format('j');
$endMonth = $PHPEndDateObject->format('n');
$endYear = $PHPEndDateObject->format('Y');
@ -1112,9 +1112,9 @@ class DateTime
case Functions::RETURNDATE_EXCEL:
return (float) $endDate;
case Functions::RETURNDATE_PHP_NUMERIC:
return (integer) \PHPExcel\Shared\Date::excelToPHP($endDate);
return (integer) \PHPExcel\Shared\Date::excelToTimestamp($endDate);
case Functions::RETURNDATE_PHP_OBJECT:
return \PHPExcel\Shared\Date::excelToPHPObject($endDate);
return \PHPExcel\Shared\Date::excelToDateTimeObject($endDate);
}
}
@ -1147,7 +1147,7 @@ class DateTime
}
// Execute function
$PHPDateObject = \PHPExcel\Shared\Date::excelToPHPObject($dateValue);
$PHPDateObject = \PHPExcel\Shared\Date::excelToDateTimeObject($dateValue);
return (int) $PHPDateObject->format('j');
}
@ -1191,7 +1191,7 @@ class DateTime
}
// Execute function
$PHPDateObject = \PHPExcel\Shared\Date::excelToPHPObject($dateValue);
$PHPDateObject = \PHPExcel\Shared\Date::excelToDateTimeObject($dateValue);
$DoW = $PHPDateObject->format('w');
$firstDay = 1;
@ -1267,7 +1267,7 @@ class DateTime
}
// Execute function
$PHPDateObject = \PHPExcel\Shared\Date::excelToPHPObject($dateValue);
$PHPDateObject = \PHPExcel\Shared\Date::excelToDateTimeObject($dateValue);
$dayOfYear = $PHPDateObject->format('z');
$PHPDateObject->modify('-' . $dayOfYear . ' days');
$dow = $PHPDateObject->format('w');
@ -1306,7 +1306,7 @@ class DateTime
}
// Execute function
$PHPDateObject = \PHPExcel\Shared\Date::excelToPHPObject($dateValue);
$PHPDateObject = \PHPExcel\Shared\Date::excelToDateTimeObject($dateValue);
return (int) $PHPDateObject->format('n');
}
@ -1338,7 +1338,7 @@ class DateTime
}
// Execute function
$PHPDateObject = \PHPExcel\Shared\Date::excelToPHPObject($dateValue);
$PHPDateObject = \PHPExcel\Shared\Date::excelToDateTimeObject($dateValue);
return (int) $PHPDateObject->format('Y');
}
@ -1379,7 +1379,7 @@ class DateTime
} elseif ($timeValue < 0.0) {
return Functions::NAN();
}
$timeValue = \PHPExcel\Shared\Date::excelToPHP($timeValue);
$timeValue = \PHPExcel\Shared\Date::excelToTimestamp($timeValue);
return (int) gmdate('G', $timeValue);
}
@ -1420,7 +1420,7 @@ class DateTime
} elseif ($timeValue < 0.0) {
return Functions::NAN();
}
$timeValue = \PHPExcel\Shared\Date::excelToPHP($timeValue);
$timeValue = \PHPExcel\Shared\Date::excelToTimestamp($timeValue);
return (int) gmdate('i', $timeValue);
}
@ -1461,7 +1461,7 @@ class DateTime
} elseif ($timeValue < 0.0) {
return Functions::NAN();
}
$timeValue = \PHPExcel\Shared\Date::excelToPHP($timeValue);
$timeValue = \PHPExcel\Shared\Date::excelToTimestamp($timeValue);
return (int) gmdate('s', $timeValue);
}
@ -1507,7 +1507,7 @@ class DateTime
case Functions::RETURNDATE_EXCEL:
return (float) \PHPExcel\Shared\Date::PHPToExcel($PHPDateObject);
case Functions::RETURNDATE_PHP_NUMERIC:
return (integer) \PHPExcel\Shared\Date::excelToPHP(\PHPExcel\Shared\Date::PHPToExcel($PHPDateObject));
return (integer) \PHPExcel\Shared\Date::excelToTimestamp(\PHPExcel\Shared\Date::PHPToExcel($PHPDateObject));
case Functions::RETURNDATE_PHP_OBJECT:
return $PHPDateObject;
}
@ -1556,7 +1556,7 @@ class DateTime
case Functions::RETURNDATE_EXCEL:
return (float) \PHPExcel\Shared\Date::PHPToExcel($PHPDateObject);
case Functions::RETURNDATE_PHP_NUMERIC:
return (integer) \PHPExcel\Shared\Date::excelToPHP(\PHPExcel\Shared\Date::PHPToExcel($PHPDateObject));
return (integer) \PHPExcel\Shared\Date::excelToTimestamp(\PHPExcel\Shared\Date::PHPToExcel($PHPDateObject));
case Functions::RETURNDATE_PHP_OBJECT:
return $PHPDateObject;
}

View File

@ -67,7 +67,7 @@ class Financial
{
$months = 12 / $frequency;
$result = \PHPExcel\Shared\Date::excelToPHPObject($maturity);
$result = \PHPExcel\Shared\Date::excelToDateTimeObject($maturity);
$eom = self::isLastDayOfMonth($result);
while ($settlement < \PHPExcel\Shared\Date::PHPToExcel($result)) {

View File

@ -33,50 +33,23 @@ class Date
const CALENDAR_WINDOWS_1900 = 1900; // Base date of 1st Jan 1900 = 1.0
const CALENDAR_MAC_1904 = 1904; // Base date of 2nd Jan 1904 = 1.0
/*
* Names of the months of the year, indexed by shortname
* Planned usage for locale settings
*
* @public
* @var string[]
*/
public static $monthNames = [
'Jan' => 'January',
'Feb' => 'February',
'Mar' => 'March',
'Apr' => 'April',
'May' => 'May',
'Jun' => 'June',
'Jul' => 'July',
'Aug' => 'August',
'Sep' => 'September',
'Oct' => 'October',
'Nov' => 'November',
'Dec' => 'December',
];
/*
* Names of the months of the year, indexed by shortname
* Planned usage for locale settings
*
* @public
* @var string[]
*/
public static $numberSuffixes = [
'st',
'nd',
'rd',
'th',
];
/*
* Base calendar year to use for calculations
* Value is either CALENDAR_WINDOWS_1900 (1900) or CALENDAR_MAC_1904 (1904)
*
* @private
* @var int
*/
protected static $excelBaseDate = self::CALENDAR_WINDOWS_1900;
/*
* Default timezone to use for DateTime objects
*
* @private
* @var null|\DateTimeZone
*/
protected static $defaultTimeZone;
/**
* Set the Excel calendar (Windows 1900 or Mac 1904)
*
@ -87,13 +60,12 @@ class Date
{
if (($baseDate == self::CALENDAR_WINDOWS_1900) ||
($baseDate == self::CALENDAR_MAC_1904)) {
self::$excelBaseDate = $baseDate;
self::$excelCalendar = $baseDate;
return true;
}
return false;
}
/**
* Return the Excel calendar (Windows 1900 or Mac 1904)
*
@ -101,72 +73,94 @@ class Date
*/
public static function getExcelCalendar()
{
return self::$excelBaseDate;
return self::$excelCalendar;
}
/**
* Convert a date from Excel to PHP
* Set the Default timezone to use for dates
*
* @param integer $dateValue Excel date/time value
* @param boolean $adjustToTimezone Flag indicating whether $dateValue should be treated as
* a UST timestamp, or adjusted to UST
* @param string $timezone The timezone for finding the adjustment from UST
* @return integer PHP serialized date/time
* @param string|\DateTimeZone $timezone The timezone to set for all Excel datetimestamp to PHP DateTime Object conversions
* @return boolean Success or failure
* @throws \Exception
*/
public static function excelToPHP($dateValue = 0, $adjustToTimezone = false, $timezone = null)
public static function setDefaultTimezone($timeZone)
{
if (self::$excelBaseDate == self::CALENDAR_WINDOWS_1900) {
$myexcelBaseDate = 25569;
// Adjust for the spurious 29-Feb-1900 (Day 60)
if ($dateValue < 60) {
--$myexcelBaseDate;
if ($timeZone = self::validateTimeZone($timeZone)) {
self::$defaultTimeZone = $timeZone;
return true;
}
} else {
$myexcelBaseDate = 24107;
return false;
}
// Perform conversion
if ($dateValue >= 1) {
$utcDays = $dateValue - $myexcelBaseDate;
$returnValue = round($utcDays * 86400);
if (($returnValue <= PHP_INT_MAX) && ($returnValue >= -PHP_INT_MAX)) {
$returnValue = (integer) $returnValue;
}
} else {
$hours = round($dateValue * 24);
$mins = round($dateValue * 1440) - round($hours * 60);
$secs = round($dateValue * 86400) - round($hours * 3600) - round($mins * 60);
$returnValue = (integer) gmmktime($hours, $mins, $secs);
}
$timezoneAdjustment = ($adjustToTimezone) ?
TimeZone::getTimezoneAdjustment($timezone, $returnValue) :
0;
return $returnValue + $timezoneAdjustment;
}
/**
* Convert a date from Excel to a PHP Date/Time object
* Return the Default timezone being used for dates
*
* @param integer $dateValue Excel date/time value
* @return \DateTimeZone The timezone being used as default for Excel timestamp to PHP DateTime object
*/
public static function getDefaultTimezone()
{
if (self::$defaultTimeZone === null) {
self::$defaultTimeZone = new \DateTimeZone('UTC');
}
return self::$defaultTimeZone;
}
/**
* Validate a timezone
*
* @param string|\DateTimeZone $timezone The timezone to validate, either as a timezone string or object
* @return \DateTimeZone The timezone as a timezone object
* @throws \Exception
*/
protected static function validateTimeZone($timeZone) {
if (is_object($timeZone) && $timeZone instanceof \DateTimeZone) {
return $timeZone;
} elseif (is_string($timeZone)) {
return new \DateTimeZone($timeZone);
}
throw new \Exception('Invalid timezone');
}
/**
* Convert a MS serialized datetime value from Excel to a PHP Date/Time object
*
* @param integer|float $dateValue Excel date/time value
* @param \DateTimeZone|string|null $timezone The timezone to assume for the Excel timestamp,
* if you don't want to treat it as a UTC value
* @return \DateTime PHP date/time object
* @throws \Exception
*/
public static function excelToPHPObject($dateValue = 0)
{
$dateTime = self::excelToPHP($dateValue);
$days = floor($dateTime / 86400);
$time = round((($dateTime / 86400) - $days) * 86400);
$hours = round($time / 3600);
$minutes = round($time / 60) - ($hours * 60);
$seconds = round($time) - ($hours * 3600) - ($minutes * 60);
public static function excelToDateTimeObject($excelTimestamp = 0, $timeZone = null) {
$timeZone = ($timeZone === null) ? self::getDefaultTimezone() : self::validateTimeZone($timeZone);
if (self::$excelBaseDate == self::CALENDAR_WINDOWS_1900) {
$baseDate = ($excelTimestamp < 60) ? new \DateTime('1899-12-31', $timeZone) : new \DateTime('1899-12-30', $timeZone);
} else {
$baseDate = new \DateTime('1904-01-01', $timeZone);
}
$days = floor($excelTimestamp);
$partDay = $excelTimestamp - $days;
$hours = floor($partDay * 24);
$partDay = $partDay * 24 - $hours;
$minutes = floor($partDay * 60);
$partDay = $partDay * 60 - $minutes;
$seconds = floor($partDay * 60);
// $fraction = $partDay - $seconds;
$dateObj = date_create('1-Jan-1970+'.$days.' days');
$dateObj->setTime($hours, $minutes, $seconds);
$interval = '+' . $days . ' days';
return $baseDate->modify($interval)
->setTime($hours, $minutes, $seconds);
}
return $dateObj;
/**
* Convert a MS serialized datetime value from Excel to a unix timestamp
*
* @param integer|float $dateValue Excel date/time value
* @return integer Unix timetamp for this date/time
* @throws \Exception
*/
public static function excelToTimestamp($excelTimestampexcelTimestamp = 0, $timeZone = null) {
return self::excelToTimestamp($excelTimestamp, $timeZone)
->format('U');
}

View File

@ -1,4 +1,4 @@
<?php
<!----><?php
namespace PHPExcel;
@ -21,9 +21,9 @@ namespace PHPExcel;
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* @category PHPExcel
* @package PHPExcel
* @copyright Copyright (c) 2006 - 2015 PHPExcel (http://www.codeplex.com/PHPExcel)
* @category PHPSpreadsheet
* @package PHPSpreadsheet
* @copyright Copyright (c) 2006 PHPOffice (http://www.github.com/PHPOffice)
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL
* @version ##VERSION##, ##DATE##
*/

View File

@ -487,7 +487,7 @@ class NumberFormat extends Supervisor implements \PHPExcel\IComparable
// escape any quoted characters so that DateTime format() will render them correctly
$format = preg_replace_callback('/"(.*)"/U', ['self', 'escapeQuotesCallback'], $format);
$dateObj = \PHPExcel\Shared\Date::excelToPHPObject($value);
$dateObj = \PHPExcel\Shared\Date::excelToDateTimeObject($value);
$value = $dateObj->format($format);
}

View File

@ -327,7 +327,7 @@ class AutoFilter
}
if (is_numeric($cellValue)) {
$dateValue = \PHPExcel\Shared\Date::excelToPHP($cellValue);
$dateValue = \PHPExcel\Shared\Date::excelToTimestamp($cellValue);
if ($cellValue < 1) {
// Just the time part
$dtVal = date('His', $dateValue);
@ -444,7 +444,7 @@ class AutoFilter
}
if (is_numeric($cellValue)) {
$dateValue = date('m', \PHPExcel\Shared\Date::excelToPHP($cellValue));
$dateValue = date('m', \PHPExcel\Shared\Date::excelToTimestamp($cellValue));
if (in_array($dateValue, $monthSet)) {
return true;
}