diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon
index db5faf27..4ee0a9ef 100644
--- a/phpstan-baseline.neon
+++ b/phpstan-baseline.neon
@@ -2165,36 +2165,6 @@ parameters:
count: 1
path: src/PhpSpreadsheet/DefinedName.php
- -
- message: "#^Property PhpOffice\\\\PhpSpreadsheet\\\\Document\\\\Properties\\:\\:\\$created \\(int\\) does not accept int\\|false\\.$#"
- count: 1
- path: src/PhpSpreadsheet/Document/Properties.php
-
- -
- message: "#^Property PhpOffice\\\\PhpSpreadsheet\\\\Document\\\\Properties\\:\\:\\$modified \\(int\\) does not accept int\\|false\\.$#"
- count: 1
- path: src/PhpSpreadsheet/Document/Properties.php
-
- -
- message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Document\\\\Properties\\:\\:identifyPropertyType\\(\\) has no return typehint specified\\.$#"
- count: 1
- path: src/PhpSpreadsheet/Document/Properties.php
-
- -
- message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Document\\\\Properties\\:\\:identifyPropertyType\\(\\) has parameter \\$propertyValue with no typehint specified\\.$#"
- count: 1
- path: src/PhpSpreadsheet/Document/Properties.php
-
- -
- message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Document\\\\Properties\\:\\:convertProperty\\(\\) has no return typehint specified\\.$#"
- count: 1
- path: src/PhpSpreadsheet/Document/Properties.php
-
- -
- message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Document\\\\Properties\\:\\:convertProperty\\(\\) has parameter \\$propertyValue with no typehint specified\\.$#"
- count: 1
- path: src/PhpSpreadsheet/Document/Properties.php
-
-
message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\HashTable\\:\\:getIndexForHashCode\\(\\) should return int but returns int\\|string\\|false\\.$#"
count: 1
@@ -2640,16 +2610,6 @@ parameters:
count: 1
path: src/PhpSpreadsheet/Reader/Ods/Properties.php
- -
- message: "#^Parameter \\#1 \\$timestamp of method PhpOffice\\\\PhpSpreadsheet\\\\Document\\\\Properties\\:\\:setCreated\\(\\) expects int\\|string\\|null, int\\|false given\\.$#"
- count: 2
- path: src/PhpSpreadsheet/Reader/Ods/Properties.php
-
- -
- message: "#^Parameter \\#1 \\$timestamp of method PhpOffice\\\\PhpSpreadsheet\\\\Document\\\\Properties\\:\\:setModified\\(\\) expects int\\|string\\|null, int\\|false given\\.$#"
- count: 1
- path: src/PhpSpreadsheet/Reader/Ods/Properties.php
-
-
message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Reader\\\\Ods\\\\Properties\\:\\:setMetaProperties\\(\\) has parameter \\$namespacesMeta with no typehint specified\\.$#"
count: 1
@@ -2860,61 +2820,6 @@ parameters:
count: 1
path: src/PhpSpreadsheet/Reader/Xls.php
- -
- message: "#^Parameter \\#1 \\$codePage of static method PhpOffice\\\\PhpSpreadsheet\\\\Shared\\\\CodePage\\:\\:numberToName\\(\\) expects int, int\\|string\\|null given\\.$#"
- count: 1
- path: src/PhpSpreadsheet/Reader/Xls.php
-
- -
- message: "#^Parameter \\#1 \\$title of method PhpOffice\\\\PhpSpreadsheet\\\\Document\\\\Properties\\:\\:setTitle\\(\\) expects string, int\\|string\\|null given\\.$#"
- count: 1
- path: src/PhpSpreadsheet/Reader/Xls.php
-
- -
- message: "#^Parameter \\#1 \\$subject of method PhpOffice\\\\PhpSpreadsheet\\\\Document\\\\Properties\\:\\:setSubject\\(\\) expects string, int\\|string\\|null given\\.$#"
- count: 1
- path: src/PhpSpreadsheet/Reader/Xls.php
-
- -
- message: "#^Parameter \\#1 \\$creator of method PhpOffice\\\\PhpSpreadsheet\\\\Document\\\\Properties\\:\\:setCreator\\(\\) expects string, int\\|string\\|null given\\.$#"
- count: 1
- path: src/PhpSpreadsheet/Reader/Xls.php
-
- -
- message: "#^Parameter \\#1 \\$keywords of method PhpOffice\\\\PhpSpreadsheet\\\\Document\\\\Properties\\:\\:setKeywords\\(\\) expects string, int\\|string\\|null given\\.$#"
- count: 1
- path: src/PhpSpreadsheet/Reader/Xls.php
-
- -
- message: "#^Parameter \\#1 \\$description of method PhpOffice\\\\PhpSpreadsheet\\\\Document\\\\Properties\\:\\:setDescription\\(\\) expects string, int\\|string\\|null given\\.$#"
- count: 1
- path: src/PhpSpreadsheet/Reader/Xls.php
-
- -
- message: "#^Parameter \\#1 \\$modifier of method PhpOffice\\\\PhpSpreadsheet\\\\Document\\\\Properties\\:\\:setLastModifiedBy\\(\\) expects string, int\\|string\\|null given\\.$#"
- count: 1
- path: src/PhpSpreadsheet/Reader/Xls.php
-
- -
- message: "#^Parameter \\#1 \\$codePage of static method PhpOffice\\\\PhpSpreadsheet\\\\Shared\\\\CodePage\\:\\:numberToName\\(\\) expects int, bool\\|int\\|string\\|null given\\.$#"
- count: 1
- path: src/PhpSpreadsheet/Reader/Xls.php
-
- -
- message: "#^Parameter \\#1 \\$category of method PhpOffice\\\\PhpSpreadsheet\\\\Document\\\\Properties\\:\\:setCategory\\(\\) expects string, bool\\|int\\|string\\|null given\\.$#"
- count: 1
- path: src/PhpSpreadsheet/Reader/Xls.php
-
- -
- message: "#^Parameter \\#1 \\$manager of method PhpOffice\\\\PhpSpreadsheet\\\\Document\\\\Properties\\:\\:setManager\\(\\) expects string, bool\\|int\\|string\\|null given\\.$#"
- count: 1
- path: src/PhpSpreadsheet/Reader/Xls.php
-
- -
- message: "#^Parameter \\#1 \\$company of method PhpOffice\\\\PhpSpreadsheet\\\\Document\\\\Properties\\:\\:setCompany\\(\\) expects string, bool\\|int\\|string\\|null given\\.$#"
- count: 1
- path: src/PhpSpreadsheet/Reader/Xls.php
-
-
message: "#^Parameter \\#3 \\$subject of function str_replace expects array\\|string, int\\|string\\|null given\\.$#"
count: 1
@@ -4520,16 +4425,6 @@ parameters:
count: 1
path: src/PhpSpreadsheet/Shared/OLE.php
- -
- message: "#^Parameter \\#1 \\$time_1st of class PhpOffice\\\\PhpSpreadsheet\\\\Shared\\\\OLE\\\\PPS\\\\Root constructor expects int, null given\\.$#"
- count: 1
- path: src/PhpSpreadsheet/Shared/OLE.php
-
- -
- message: "#^Parameter \\#2 \\$time_2nd of class PhpOffice\\\\PhpSpreadsheet\\\\Shared\\\\OLE\\\\PPS\\\\Root constructor expects int, null given\\.$#"
- count: 1
- path: src/PhpSpreadsheet/Shared/OLE.php
-
-
message: "#^Parameter \\#1 \\$No of class PhpOffice\\\\PhpSpreadsheet\\\\Shared\\\\OLE\\\\PPS constructor expects int, null given\\.$#"
count: 1
@@ -4560,16 +4455,6 @@ parameters:
count: 1
path: src/PhpSpreadsheet/Shared/OLE.php
- -
- message: "#^Parameter \\#7 \\$time_1st of class PhpOffice\\\\PhpSpreadsheet\\\\Shared\\\\OLE\\\\PPS constructor expects int, null given\\.$#"
- count: 1
- path: src/PhpSpreadsheet/Shared/OLE.php
-
- -
- message: "#^Parameter \\#8 \\$time_2nd of class PhpOffice\\\\PhpSpreadsheet\\\\Shared\\\\OLE\\\\PPS constructor expects int, null given\\.$#"
- count: 1
- path: src/PhpSpreadsheet/Shared/OLE.php
-
-
message: "#^Parameter \\#9 \\$data of class PhpOffice\\\\PhpSpreadsheet\\\\Shared\\\\OLE\\\\PPS constructor expects string, null given\\.$#"
count: 1
@@ -4640,16 +4525,6 @@ parameters:
count: 1
path: src/PhpSpreadsheet/Shared/OLE/PPS/File.php
- -
- message: "#^Parameter \\#7 \\$time_1st of method PhpOffice\\\\PhpSpreadsheet\\\\Shared\\\\OLE\\\\PPS\\:\\:__construct\\(\\) expects int, null given\\.$#"
- count: 1
- path: src/PhpSpreadsheet/Shared/OLE/PPS/File.php
-
- -
- message: "#^Parameter \\#8 \\$time_2nd of method PhpOffice\\\\PhpSpreadsheet\\\\Shared\\\\OLE\\\\PPS\\:\\:__construct\\(\\) expects int, null given\\.$#"
- count: 1
- path: src/PhpSpreadsheet/Shared/OLE/PPS/File.php
-
-
message: "#^Parameter \\#1 \\$No of method PhpOffice\\\\PhpSpreadsheet\\\\Shared\\\\OLE\\\\PPS\\:\\:__construct\\(\\) expects int, null given\\.$#"
count: 1
@@ -4795,11 +4670,6 @@ parameters:
count: 1
path: src/PhpSpreadsheet/Shared/StringHelper.php
- -
- message: "#^Else branch is unreachable because previous condition is always true\\.$#"
- count: 1
- path: src/PhpSpreadsheet/Shared/TimeZone.php
-
-
message: "#^Property PhpOffice\\\\PhpSpreadsheet\\\\Shared\\\\Trend\\\\BestFit\\:\\:\\$goodnessOfFit has no typehint specified\\.$#"
count: 1
@@ -7545,31 +7415,11 @@ parameters:
count: 1
path: tests/PhpSpreadsheetTests/Reader/Xml/XmlTest.php
- -
- message: "#^Parameter \\#1 \\$timeZone of static method PhpOffice\\\\PhpSpreadsheet\\\\Shared\\\\Date\\:\\:setDefaultTimezone\\(\\) expects DateTimeZone\\|string, DateTimeZone\\|null given\\.$#"
- count: 1
- path: tests/PhpSpreadsheetTests/Shared/DateTest.php
-
-
message: "#^Parameter \\#1 \\$pValue of static method PhpOffice\\\\PhpSpreadsheet\\\\Shared\\\\StringHelper\\:\\:setCurrencyCode\\(\\) expects string, null given\\.$#"
count: 1
path: tests/PhpSpreadsheetTests/Shared/StringHelperTest.php
- -
- message: "#^Parameter \\#1 \\$timeZone of static method PhpOffice\\\\PhpSpreadsheet\\\\Shared\\\\Date\\:\\:setDefaultTimezone\\(\\) expects DateTimeZone\\|string, DateTimeZone\\|null given\\.$#"
- count: 1
- path: tests/PhpSpreadsheetTests/Shared/TimeZoneTest.php
-
- -
- message: "#^Cannot call method getTimestamp\\(\\) on DateTime\\|false\\.$#"
- count: 2
- path: tests/PhpSpreadsheetTests/Shared/TimeZoneTest.php
-
- -
- message: "#^Parameter \\#1 \\$timezone of static method PhpOffice\\\\PhpSpreadsheet\\\\Shared\\\\TimeZone\\:\\:getTimeZoneAdjustment\\(\\) expects string, null given\\.$#"
- count: 1
- path: tests/PhpSpreadsheetTests/Shared/TimeZoneTest.php
-
-
message: "#^Method PhpOffice\\\\PhpSpreadsheetTests\\\\SpreadsheetTest\\:\\:testGetSheetByName\\(\\) has parameter \\$index with no typehint specified\\.$#"
count: 1
diff --git a/samples/Basic/01_Simple.php b/samples/Basic/01_Simple.php
index 69309794..1ab182e1 100644
--- a/samples/Basic/01_Simple.php
+++ b/samples/Basic/01_Simple.php
@@ -61,4 +61,4 @@ $spreadsheet->getActiveSheet()
->setTitle('Simple');
// Save
-$helper->write($spreadsheet, __FILE__);
+$helper->write($spreadsheet, __FILE__, ['Xlsx', 'Xls', 'Ods']);
diff --git a/samples/Reading_workbook_data/Properties.php b/samples/Reading_workbook_data/Properties.php
index 5bf25b8e..8f7be375 100644
--- a/samples/Reading_workbook_data/Properties.php
+++ b/samples/Reading_workbook_data/Properties.php
@@ -1,6 +1,7 @@
log('Document Creator: ' . $creator);
// Read the Date when the workbook was created (as a PHP timestamp value)
$creationDatestamp = $spreadsheet->getProperties()->getCreated();
-// Format the date and time using the standard PHP date() function
-$creationDate = date('l, d<\s\up>S\s\up> F Y', $creationDatestamp);
-$creationTime = date('g:i A', $creationDatestamp);
+$creationDate = Date::formattedDateTimeFromTimestamp("$creationDatestamp", 'l, d<\s\up>S\s\up> F Y');
+$creationTime = Date::formattedDateTimeFromTimestamp("$creationDatestamp", 'g:i A');
$helper->log('Created On: ' . $creationDate . ' at ' . $creationTime);
// Read the name of the last person to modify this workbook
@@ -30,8 +30,8 @@ $helper->log('Last Modified By: ' . $modifiedBy);
// Read the Date when the workbook was last modified (as a PHP timestamp value)
$modifiedDatestamp = $spreadsheet->getProperties()->getModified();
// Format the date and time using the standard PHP date() function
-$modifiedDate = date('l, d<\s\up>S\s\up> F Y', $modifiedDatestamp);
-$modifiedTime = date('g:i A', $modifiedDatestamp);
+$modifiedDate = Date::formattedDateTimeFromTimestamp("$modifiedDatestamp", 'l, d<\s\up>S\s\up> F Y');
+$modifiedTime = Date::formattedDateTimeFromTimestamp("$modifiedDatestamp", 'g:i A');
$helper->log('Last Modified On: ' . $modifiedDate . ' at ' . $modifiedTime);
// Read the workbook title property
diff --git a/src/PhpSpreadsheet/Calculation/Calculation.php b/src/PhpSpreadsheet/Calculation/Calculation.php
index a2ad47bd..d03b3623 100644
--- a/src/PhpSpreadsheet/Calculation/Calculation.php
+++ b/src/PhpSpreadsheet/Calculation/Calculation.php
@@ -4687,7 +4687,7 @@ class Calculation
} else {
$this->executeNumericBinaryOperation($multiplier, $arg, '*', 'arrayTimesEquals', $stack);
}
- } elseif (preg_match('/^' . self::CALCULATION_REGEXP_CELLREF . '$/i', $token, $matches)) {
+ } elseif (preg_match('/^' . self::CALCULATION_REGEXP_CELLREF . '$/i', $token ?? '', $matches)) {
$cellRef = null;
if (isset($matches[8])) {
@@ -4765,7 +4765,7 @@ class Calculation
}
// if the token is a function, pop arguments off the stack, hand them to the function, and push the result back on
- } elseif (preg_match('/^' . self::CALCULATION_REGEXP_FUNCTION . '$/miu', $token, $matches)) {
+ } elseif (preg_match('/^' . self::CALCULATION_REGEXP_FUNCTION . '$/miu', $token ?? '', $matches)) {
if ($pCellParent) {
$pCell->attach($pCellParent);
}
@@ -4855,7 +4855,7 @@ class Calculation
}
} else {
// if the token is a number, boolean, string or an Excel error, push it onto the stack
- if (isset(self::$excelConstants[strtoupper($token)])) {
+ if (isset(self::$excelConstants[strtoupper($token ?? '')])) {
$excelConstant = strtoupper($token);
$stack->push('Constant Value', self::$excelConstants[$excelConstant]);
if (isset($storeKey)) {
diff --git a/src/PhpSpreadsheet/Calculation/MathTrig/Base.php b/src/PhpSpreadsheet/Calculation/MathTrig/Base.php
index becba9a2..4be7b7c7 100644
--- a/src/PhpSpreadsheet/Calculation/MathTrig/Base.php
+++ b/src/PhpSpreadsheet/Calculation/MathTrig/Base.php
@@ -24,7 +24,7 @@ class Base
public static function evaluate($number, $radix, $minLength = null)
{
try {
- $number = (int) Helpers::validateNumericNullBool($number);
+ $number = (float) floor(Helpers::validateNumericNullBool($number));
$radix = (int) Helpers::validateNumericNullBool($radix);
} catch (Exception $e) {
return $e->getMessage();
@@ -36,7 +36,7 @@ class Base
return Functions::NAN(); // Numeric range constraints
}
- $outcome = strtoupper((string) base_convert((string) $number, 10, $radix));
+ $outcome = strtoupper((string) base_convert("$number", 10, $radix));
if ($minLength !== null) {
$outcome = str_pad($outcome, (int) $minLength, '0', STR_PAD_LEFT); // String padding
}
diff --git a/src/PhpSpreadsheet/Calculation/Statistical.php b/src/PhpSpreadsheet/Calculation/Statistical.php
index 6c184f56..d43a85f9 100644
--- a/src/PhpSpreadsheet/Calculation/Statistical.php
+++ b/src/PhpSpreadsheet/Calculation/Statistical.php
@@ -1308,7 +1308,7 @@ class Statistical
* @param int $numObjs Number of different objects
* @param int $numInSet Number of objects in each permutation
*
- * @return int|string Number of permutations, or a string containing an error
+ * @return float|int|string Number of permutations, or a string containing an error
*/
public static function PERMUT($numObjs, $numInSet)
{
diff --git a/src/PhpSpreadsheet/Calculation/Statistical/Permutations.php b/src/PhpSpreadsheet/Calculation/Statistical/Permutations.php
index 0bad2a88..272a8a53 100644
--- a/src/PhpSpreadsheet/Calculation/Statistical/Permutations.php
+++ b/src/PhpSpreadsheet/Calculation/Statistical/Permutations.php
@@ -5,6 +5,7 @@ namespace PhpOffice\PhpSpreadsheet\Calculation\Statistical;
use PhpOffice\PhpSpreadsheet\Calculation\Exception;
use PhpOffice\PhpSpreadsheet\Calculation\Functions;
use PhpOffice\PhpSpreadsheet\Calculation\MathTrig;
+use PhpOffice\PhpSpreadsheet\Shared\IntOrFloat;
class Permutations
{
@@ -20,7 +21,7 @@ class Permutations
* @param mixed $numObjs Integer number of different objects
* @param mixed $numInSet Integer number of objects in each permutation
*
- * @return int|string Number of permutations, or a string containing an error
+ * @return float|int|string Number of permutations, or a string containing an error
*/
public static function PERMUT($numObjs, $numInSet)
{
@@ -37,8 +38,9 @@ class Permutations
if ($numObjs < $numInSet) {
return Functions::NAN();
}
+ $result = round(MathTrig\Factorial::fact($numObjs) / MathTrig\Factorial::fact($numObjs - $numInSet));
- return (int) round(MathTrig\Factorial::fact($numObjs) / MathTrig\Factorial::fact($numObjs - $numInSet));
+ return IntOrFloat::evaluate($result);
}
/**
@@ -50,7 +52,7 @@ class Permutations
* @param mixed $numObjs Integer number of different objects
* @param mixed $numInSet Integer number of objects in each permutation
*
- * @return int|string Number of permutations, or a string containing an error
+ * @return float|int|string Number of permutations, or a string containing an error
*/
public static function PERMUTATIONA($numObjs, $numInSet)
{
@@ -68,6 +70,8 @@ class Permutations
return Functions::NAN();
}
- return (int) ($numObjs ** $numInSet);
+ $result = $numObjs ** $numInSet;
+
+ return IntOrFloat::evaluate($result);
}
}
diff --git a/src/PhpSpreadsheet/Document/Properties.php b/src/PhpSpreadsheet/Document/Properties.php
index c099bccc..1030d98c 100644
--- a/src/PhpSpreadsheet/Document/Properties.php
+++ b/src/PhpSpreadsheet/Document/Properties.php
@@ -2,6 +2,9 @@
namespace PhpOffice\PhpSpreadsheet\Document;
+use DateTime;
+use PhpOffice\PhpSpreadsheet\Shared\IntOrFloat;
+
class Properties
{
/** constants */
@@ -37,14 +40,14 @@ class Properties
/**
* Created.
*
- * @var int
+ * @var float|int
*/
private $created;
/**
* Modified.
*
- * @var int
+ * @var float|int
*/
private $modified;
@@ -95,7 +98,7 @@ class Properties
*
* @var string
*/
- private $company = 'Microsoft Corporation';
+ private $company = '';
/**
* Custom Properties.
@@ -111,8 +114,8 @@ class Properties
{
// Initialise values
$this->lastModifiedBy = $this->creator;
- $this->created = time();
- $this->modified = time();
+ $this->created = self::intOrFloatTimestamp(null);
+ $this->modified = self::intOrFloatTimestamp(null);
}
/**
@@ -156,9 +159,32 @@ class Properties
}
/**
- * Get Created.
+ * @param null|float|int|string $timestamp
+ *
+ * @return float|int
*/
- public function getCreated(): int
+ private static function intOrFloatTimestamp($timestamp)
+ {
+ if ($timestamp === null) {
+ $timestamp = (float) (new DateTime())->format('U');
+ } elseif (is_string($timestamp)) {
+ if (is_numeric($timestamp)) {
+ $timestamp = (float) $timestamp;
+ } else {
+ $timestamp = preg_replace('/[.][0-9]*$/', '', $timestamp) ?? '';
+ $timestamp = (float) (new DateTime($timestamp))->format('U');
+ }
+ }
+
+ return IntOrFloat::evaluate($timestamp);
+ }
+
+ /**
+ * Get Created.
+ *
+ * @return float|int
+ */
+ public function getCreated()
{
return $this->created;
}
@@ -166,31 +192,23 @@ class Properties
/**
* Set Created.
*
- * @param null|int|string $timestamp
+ * @param null|float|int|string $timestamp
*
* @return $this
*/
public function setCreated($timestamp): self
{
- if ($timestamp === null) {
- $timestamp = time();
- } elseif (is_string($timestamp)) {
- if (is_numeric($timestamp)) {
- $timestamp = (int) $timestamp;
- } else {
- $timestamp = strtotime($timestamp);
- }
- }
-
- $this->created = $timestamp;
+ $this->created = self::intOrFloatTimestamp($timestamp);
return $this;
}
/**
* Get Modified.
+ *
+ * @return float|int
*/
- public function getModified(): int
+ public function getModified()
{
return $this->modified;
}
@@ -198,23 +216,13 @@ class Properties
/**
* Set Modified.
*
- * @param null|int|string $timestamp
+ * @param null|float|int|string $timestamp
*
* @return $this
*/
public function setModified($timestamp): self
{
- if ($timestamp === null) {
- $timestamp = time();
- } elseif (is_string($timestamp)) {
- if (is_numeric($timestamp)) {
- $timestamp = (int) $timestamp;
- } else {
- $timestamp = strtotime($timestamp);
- }
- }
-
- $this->modified = $timestamp;
+ $this->modified = self::intOrFloatTimestamp($timestamp);
return $this;
}
@@ -387,6 +395,8 @@ class Properties
if (isset($this->customProperties[$propertyName])) {
return $this->customProperties[$propertyName]['value'];
}
+
+ return null;
}
/**
@@ -399,15 +409,18 @@ class Properties
return $this->customProperties[$propertyName]['type'] ?? null;
}
- private function identifyPropertyType($propertyValue)
+ /**
+ * @param mixed $propertyValue
+ */
+ private function identifyPropertyType($propertyValue): string
{
- if ($propertyValue === null) {
- return self::PROPERTY_TYPE_STRING;
- } elseif (is_float($propertyValue)) {
+ if (is_float($propertyValue)) {
return self::PROPERTY_TYPE_FLOAT;
- } elseif (is_int($propertyValue)) {
+ }
+ if (is_int($propertyValue)) {
return self::PROPERTY_TYPE_INTEGER;
- } elseif (is_bool($propertyValue)) {
+ }
+ if (is_bool($propertyValue)) {
return self::PROPERTY_TYPE_BOOLEAN;
}
@@ -433,125 +446,90 @@ class Properties
$propertyType = $this->identifyPropertyType($propertyValue);
}
- $this->customProperties[$propertyName] = [
- 'value' => $propertyValue,
- 'type' => $propertyType,
- ];
+ if (!is_object($propertyValue)) {
+ $this->customProperties[$propertyName] = [
+ 'value' => self::convertProperty($propertyValue, $propertyType),
+ 'type' => $propertyType,
+ ];
+ }
return $this;
}
- /**
- * Implement PHP __clone to create a deep clone, not just a shallow copy.
- */
- public function __clone()
- {
- $vars = get_object_vars($this);
- foreach ($vars as $key => $value) {
- if (is_object($value)) {
- $this->$key = clone $value;
- } else {
- $this->$key = $value;
- }
- }
- }
+ private const PROPERTY_TYPE_ARRAY = [
+ 'i' => self::PROPERTY_TYPE_INTEGER, // Integer
+ 'i1' => self::PROPERTY_TYPE_INTEGER, // 1-Byte Signed Integer
+ 'i2' => self::PROPERTY_TYPE_INTEGER, // 2-Byte Signed Integer
+ 'i4' => self::PROPERTY_TYPE_INTEGER, // 4-Byte Signed Integer
+ 'i8' => self::PROPERTY_TYPE_INTEGER, // 8-Byte Signed Integer
+ 'int' => self::PROPERTY_TYPE_INTEGER, // Integer
+ 'ui1' => self::PROPERTY_TYPE_INTEGER, // 1-Byte Unsigned Integer
+ 'ui2' => self::PROPERTY_TYPE_INTEGER, // 2-Byte Unsigned Integer
+ 'ui4' => self::PROPERTY_TYPE_INTEGER, // 4-Byte Unsigned Integer
+ 'ui8' => self::PROPERTY_TYPE_INTEGER, // 8-Byte Unsigned Integer
+ 'uint' => self::PROPERTY_TYPE_INTEGER, // Unsigned Integer
+ 'f' => self::PROPERTY_TYPE_FLOAT, // Real Number
+ 'r4' => self::PROPERTY_TYPE_FLOAT, // 4-Byte Real Number
+ 'r8' => self::PROPERTY_TYPE_FLOAT, // 8-Byte Real Number
+ 'decimal' => self::PROPERTY_TYPE_FLOAT, // Decimal
+ 's' => self::PROPERTY_TYPE_STRING, // String
+ 'empty' => self::PROPERTY_TYPE_STRING, // Empty
+ 'null' => self::PROPERTY_TYPE_STRING, // Null
+ 'lpstr' => self::PROPERTY_TYPE_STRING, // LPSTR
+ 'lpwstr' => self::PROPERTY_TYPE_STRING, // LPWSTR
+ 'bstr' => self::PROPERTY_TYPE_STRING, // Basic String
+ 'd' => self::PROPERTY_TYPE_DATE, // Date and Time
+ 'date' => self::PROPERTY_TYPE_DATE, // Date and Time
+ 'filetime' => self::PROPERTY_TYPE_DATE, // File Time
+ 'b' => self::PROPERTY_TYPE_BOOLEAN, // Boolean
+ 'bool' => self::PROPERTY_TYPE_BOOLEAN, // Boolean
+ ];
+ private const SPECIAL_TYPES = [
+ 'empty' => '',
+ 'null' => null,
+ ];
+
+ /**
+ * Convert property to form desired by Excel.
+ *
+ * @param mixed $propertyValue
+ *
+ * @return mixed
+ */
public static function convertProperty($propertyValue, string $propertyType)
{
+ return self::SPECIAL_TYPES[$propertyType] ?? self::convertProperty2($propertyValue, $propertyType);
+ }
+
+ /**
+ * Convert property to form desired by Excel.
+ *
+ * @param mixed $propertyValue
+ *
+ * @return mixed
+ */
+ private static function convertProperty2($propertyValue, string $type)
+ {
+ $propertyType = self::convertPropertyType($type);
switch ($propertyType) {
- case 'empty': // Empty
- return '';
- case 'null': // Null
- return null;
- case 'i1': // 1-Byte Signed Integer
- case 'i2': // 2-Byte Signed Integer
- case 'i4': // 4-Byte Signed Integer
- case 'i8': // 8-Byte Signed Integer
- case 'int': // Integer
- return (int) $propertyValue;
- case 'ui1': // 1-Byte Unsigned Integer
- case 'ui2': // 2-Byte Unsigned Integer
- case 'ui4': // 4-Byte Unsigned Integer
- case 'ui8': // 8-Byte Unsigned Integer
- case 'uint': // Unsigned Integer
- return abs((int) $propertyValue);
- case 'r4': // 4-Byte Real Number
- case 'r8': // 8-Byte Real Number
- case 'decimal': // Decimal
+ case self::PROPERTY_TYPE_INTEGER:
+ $intValue = (int) $propertyValue;
+
+ return ($type[0] === 'u') ? abs($intValue) : $intValue;
+ case self::PROPERTY_TYPE_FLOAT:
return (float) $propertyValue;
- case 'lpstr': // LPSTR
- case 'lpwstr': // LPWSTR
- case 'bstr': // Basic String
- return $propertyValue;
- case 'date': // Date and Time
- case 'filetime': // File Time
- return strtotime($propertyValue);
- case 'bool': // Boolean
- return $propertyValue == 'true';
- case 'cy': // Currency
- case 'error': // Error Status Code
- case 'vector': // Vector
- case 'array': // Array
- case 'blob': // Binary Blob
- case 'oblob': // Binary Blob Object
- case 'stream': // Binary Stream
- case 'ostream': // Binary Stream Object
- case 'storage': // Binary Storage
- case 'ostorage': // Binary Storage Object
- case 'vstream': // Binary Versioned Stream
- case 'clsid': // Class ID
- case 'cf': // Clipboard Data
+ case self::PROPERTY_TYPE_DATE:
+ return self::intOrFloatTimestamp($propertyValue);
+ case self::PROPERTY_TYPE_BOOLEAN:
+ return is_bool($propertyValue) ? $propertyValue : ($propertyValue === 'true');
+ default: // includes string
return $propertyValue;
}
-
- return $propertyValue;
}
public static function convertPropertyType(string $propertyType): string
{
- switch ($propertyType) {
- case 'i1': // 1-Byte Signed Integer
- case 'i2': // 2-Byte Signed Integer
- case 'i4': // 4-Byte Signed Integer
- case 'i8': // 8-Byte Signed Integer
- case 'int': // Integer
- case 'ui1': // 1-Byte Unsigned Integer
- case 'ui2': // 2-Byte Unsigned Integer
- case 'ui4': // 4-Byte Unsigned Integer
- case 'ui8': // 8-Byte Unsigned Integer
- case 'uint': // Unsigned Integer
- return self::PROPERTY_TYPE_INTEGER;
- case 'r4': // 4-Byte Real Number
- case 'r8': // 8-Byte Real Number
- case 'decimal': // Decimal
- return self::PROPERTY_TYPE_FLOAT;
- case 'empty': // Empty
- case 'null': // Null
- case 'lpstr': // LPSTR
- case 'lpwstr': // LPWSTR
- case 'bstr': // Basic String
- return self::PROPERTY_TYPE_STRING;
- case 'date': // Date and Time
- case 'filetime': // File Time
- return self::PROPERTY_TYPE_DATE;
- case 'bool': // Boolean
- return self::PROPERTY_TYPE_BOOLEAN;
- case 'cy': // Currency
- case 'error': // Error Status Code
- case 'vector': // Vector
- case 'array': // Array
- case 'blob': // Binary Blob
- case 'oblob': // Binary Blob Object
- case 'stream': // Binary Stream
- case 'ostream': // Binary Stream Object
- case 'storage': // Binary Storage
- case 'ostorage': // Binary Storage Object
- case 'vstream': // Binary Versioned Stream
- case 'clsid': // Class ID
- case 'cf': // Clipboard Data
- return self::PROPERTY_TYPE_UNKNOWN;
- }
-
- return self::PROPERTY_TYPE_UNKNOWN;
+ return self::PROPERTY_TYPE_ARRAY[$propertyType] ?? self::PROPERTY_TYPE_UNKNOWN;
}
}
diff --git a/src/PhpSpreadsheet/Reader/Ods.php b/src/PhpSpreadsheet/Reader/Ods.php
index 26151cdc..760aa10d 100644
--- a/src/PhpSpreadsheet/Reader/Ods.php
+++ b/src/PhpSpreadsheet/Reader/Ods.php
@@ -3,7 +3,6 @@
namespace PhpOffice\PhpSpreadsheet\Reader;
use DateTime;
-use DateTimeZone;
use DOMAttr;
use DOMDocument;
use DOMElement;
@@ -256,9 +255,6 @@ class Ods extends BaseReader
{
File::assertFile($pFilename);
- $timezoneObj = new DateTimeZone('Europe/London');
- $GMT = new DateTimeZone('UTC');
-
$zip = new ZipArchive();
if ($zip->open($pFilename) !== true) {
throw new Exception("Could not open {$pFilename} for reading! Error opening file.");
@@ -502,8 +498,7 @@ class Ods extends BaseReader
$type = DataType::TYPE_NUMERIC;
$value = $cellData->getAttributeNS($officeNs, 'date-value');
- $dateObj = new DateTime($value, $GMT);
- $dateObj->setTimeZone($timezoneObj);
+ $dateObj = new DateTime($value);
[$year, $month, $day, $hour, $minute, $second] = explode(
' ',
$dateObj->format('Y m d H i s')
diff --git a/src/PhpSpreadsheet/Reader/Ods/Properties.php b/src/PhpSpreadsheet/Reader/Ods/Properties.php
index d0a45e6a..b94d1ef6 100644
--- a/src/PhpSpreadsheet/Reader/Ods/Properties.php
+++ b/src/PhpSpreadsheet/Reader/Ods/Properties.php
@@ -55,9 +55,7 @@ class Properties
break;
case 'date':
- $creationDate = strtotime($propertyValue);
- $docProps->setCreated($creationDate);
- $docProps->setModified($creationDate);
+ $docProps->setModified($propertyValue);
break;
case 'description':
@@ -86,8 +84,7 @@ class Properties
break;
case 'creation-date':
- $creationDate = strtotime($propertyValue);
- $docProps->setCreated($creationDate);
+ $docProps->setCreated($propertyValue);
break;
case 'user-defined':
diff --git a/src/PhpSpreadsheet/Reader/Xls.php b/src/PhpSpreadsheet/Reader/Xls.php
index 470bbacc..bfdd5583 100644
--- a/src/PhpSpreadsheet/Reader/Xls.php
+++ b/src/PhpSpreadsheet/Reader/Xls.php
@@ -1455,34 +1455,34 @@ class Xls extends BaseReader
switch ($id) {
case 0x01: // Code Page
- $codePage = CodePage::numberToName($value);
+ $codePage = CodePage::numberToName((int) $value);
break;
case 0x02: // Title
- $this->spreadsheet->getProperties()->setTitle($value);
+ $this->spreadsheet->getProperties()->setTitle("$value");
break;
case 0x03: // Subject
- $this->spreadsheet->getProperties()->setSubject($value);
+ $this->spreadsheet->getProperties()->setSubject("$value");
break;
case 0x04: // Author (Creator)
- $this->spreadsheet->getProperties()->setCreator($value);
+ $this->spreadsheet->getProperties()->setCreator("$value");
break;
case 0x05: // Keywords
- $this->spreadsheet->getProperties()->setKeywords($value);
+ $this->spreadsheet->getProperties()->setKeywords("$value");
break;
case 0x06: // Comments (Description)
- $this->spreadsheet->getProperties()->setDescription($value);
+ $this->spreadsheet->getProperties()->setDescription("$value");
break;
case 0x07: // Template
// Not supported by PhpSpreadsheet
break;
case 0x08: // Last Saved By (LastModifiedBy)
- $this->spreadsheet->getProperties()->setLastModifiedBy($value);
+ $this->spreadsheet->getProperties()->setLastModifiedBy("$value");
break;
case 0x09: // Revision
@@ -1607,11 +1607,11 @@ class Xls extends BaseReader
switch ($id) {
case 0x01: // Code Page
- $codePage = CodePage::numberToName($value);
+ $codePage = CodePage::numberToName((int) $value);
break;
case 0x02: // Category
- $this->spreadsheet->getProperties()->setCategory($value);
+ $this->spreadsheet->getProperties()->setCategory("$value");
break;
case 0x03: // Presentation Target
@@ -1648,11 +1648,11 @@ class Xls extends BaseReader
// Not supported by PhpSpreadsheet
break;
case 0x0E: // Manager
- $this->spreadsheet->getProperties()->setManager($value);
+ $this->spreadsheet->getProperties()->setManager("$value");
break;
case 0x0F: // Company
- $this->spreadsheet->getProperties()->setCompany($value);
+ $this->spreadsheet->getProperties()->setCompany("$value");
break;
case 0x10: // Links up-to-date
diff --git a/src/PhpSpreadsheet/Reader/Xlsx/Properties.php b/src/PhpSpreadsheet/Reader/Xlsx/Properties.php
index b6f3c61f..ffc7ec45 100644
--- a/src/PhpSpreadsheet/Reader/Xlsx/Properties.php
+++ b/src/PhpSpreadsheet/Reader/Xlsx/Properties.php
@@ -39,8 +39,10 @@ class Properties
$this->docProps->setCreator((string) self::getArrayItem($xmlCore->xpath('dc:creator')));
$this->docProps->setLastModifiedBy((string) self::getArrayItem($xmlCore->xpath('cp:lastModifiedBy')));
- $this->docProps->setCreated(strtotime(self::getArrayItem($xmlCore->xpath('dcterms:created')))); //! respect xsi:type
- $this->docProps->setModified(strtotime(self::getArrayItem($xmlCore->xpath('dcterms:modified')))); //! respect xsi:type
+ $created = (string) self::getArrayItem($xmlCore->xpath('dcterms:created')); //! respect xsi:type
+ $this->docProps->setCreated($created);
+ $modified = (string) self::getArrayItem($xmlCore->xpath('dcterms:modified')); //! respect xsi:type
+ $this->docProps->setModified($modified); //! respect xsi:type
$this->docProps->setTitle((string) self::getArrayItem($xmlCore->xpath('dc:title')));
$this->docProps->setDescription((string) self::getArrayItem($xmlCore->xpath('dc:description')));
$this->docProps->setSubject((string) self::getArrayItem($xmlCore->xpath('dc:subject')));
diff --git a/src/PhpSpreadsheet/Shared/Date.php b/src/PhpSpreadsheet/Shared/Date.php
index 3b4c635d..7ddce046 100644
--- a/src/PhpSpreadsheet/Shared/Date.php
+++ b/src/PhpSpreadsheet/Shared/Date.php
@@ -97,7 +97,7 @@ class Date
/**
* Set the Default timezone to use for dates.
*
- * @param DateTimeZone|string $timeZone The timezone to set for all Excel datetimestamp to PHP DateTime Object conversions
+ * @param null|DateTimeZone|string $timeZone The timezone to set for all Excel datetimestamp to PHP DateTime Object conversions
*
* @return bool Success or failure
*/
@@ -115,29 +115,39 @@ class Date
}
/**
- * Return the Default timezone being used for dates.
- *
- * @return DateTimeZone The timezone being used as default for Excel timestamp to PHP DateTime object
+ * Return the Default timezone, or UTC if default not set.
*/
- public static function getDefaultTimezone()
+ public static function getDefaultTimezone(): DateTimeZone
{
- if (self::$defaultTimeZone === null) {
- self::$defaultTimeZone = new DateTimeZone('UTC');
- }
+ return self::$defaultTimeZone ?? new DateTimeZone('UTC');
+ }
+ /**
+ * Return the Default timezone, or local timezone if default is not set.
+ */
+ public static function getDefaultOrLocalTimezone(): DateTimeZone
+ {
+ return self::$defaultTimeZone ?? new DateTimeZone(date_default_timezone_get());
+ }
+
+ /**
+ * Return the Default timezone even if null.
+ */
+ public static function getDefaultTimezoneOrNull(): ?DateTimeZone
+ {
return self::$defaultTimeZone;
}
/**
* Validate a timezone.
*
- * @param DateTimeZone|string $timeZone The timezone to validate, either as a timezone string or object
+ * @param null|DateTimeZone|string $timeZone The timezone to validate, either as a timezone string or object
*
- * @return DateTimeZone The timezone as a timezone object
+ * @return ?DateTimeZone The timezone as a timezone object
*/
private static function validateTimeZone($timeZone)
{
- if ($timeZone instanceof DateTimeZone) {
+ if ($timeZone instanceof DateTimeZone || $timeZone === null) {
return $timeZone;
}
if (in_array($timeZone, DateTimeZone::listIdentifiers(DateTimeZone::ALL_WITH_BC))) {
@@ -490,4 +500,19 @@ class Date
return $day;
}
+
+ public static function dateTimeFromTimestamp(string $date, ?DateTimeZone $timeZone = null): DateTime
+ {
+ $dtobj = DateTime::createFromFormat('U', $date) ?: new DateTime();
+ $dtobj->setTimeZone($timeZone ?? self::getDefaultOrLocalTimezone());
+
+ return $dtobj;
+ }
+
+ public static function formattedDateTimeFromTimestamp(string $date, string $format, ?DateTimeZone $timeZone = null): string
+ {
+ $dtobj = self::dateTimeFromTimestamp($date, $timeZone);
+
+ return $dtobj->format($format);
+ }
}
diff --git a/src/PhpSpreadsheet/Shared/IntOrFloat.php b/src/PhpSpreadsheet/Shared/IntOrFloat.php
new file mode 100644
index 00000000..060f09c8
--- /dev/null
+++ b/src/PhpSpreadsheet/Shared/IntOrFloat.php
@@ -0,0 +1,21 @@
+format('U');
// multiply just to make MS happy
$big_date *= 10000000;
@@ -537,7 +538,7 @@ class OLE
*
* @param string $oleTimestamp A binary string with the encoded date
*
- * @return int The Unix timestamp corresponding to the string
+ * @return float|int The Unix timestamp corresponding to the string
*/
public static function OLE2LocalDate($oleTimestamp)
{
@@ -560,9 +561,6 @@ class OLE
// translate to seconds since 1970:
$unixTimestamp = floor(65536.0 * 65536.0 * $timestampHigh + $timestampLow - $days * 24 * 3600 + 0.5);
- $iTimestamp = (int) $unixTimestamp;
-
- // Overflow conditions can't happen on 64-bit system
- return ($iTimestamp == $unixTimestamp) ? $iTimestamp : ($unixTimestamp >= 0.0 ? PHP_INT_MAX : PHP_INT_MIN);
+ return IntOrFloat::evaluate($unixTimestamp);
}
}
diff --git a/src/PhpSpreadsheet/Shared/OLE/PPS.php b/src/PhpSpreadsheet/Shared/OLE/PPS.php
index 104b0d6a..8b9e92a8 100644
--- a/src/PhpSpreadsheet/Shared/OLE/PPS.php
+++ b/src/PhpSpreadsheet/Shared/OLE/PPS.php
@@ -74,14 +74,14 @@ class PPS
/**
* A timestamp.
*
- * @var int
+ * @var float|int
*/
public $Time1st;
/**
* A timestamp.
*
- * @var int
+ * @var float|int
*/
public $Time2nd;
@@ -129,8 +129,8 @@ class PPS
* @param int $prev The index of the previous PPS
* @param int $next The index of the next PPS
* @param int $dir The index of it's first child if this is a Dir or Root PPS
- * @param int $time_1st A timestamp
- * @param int $time_2nd A timestamp
+ * @param null|float|int $time_1st A timestamp
+ * @param null|float|int $time_2nd A timestamp
* @param string $data The (usually binary) source data of the PPS
* @param array $children Array containing children PPS for this PPS
*/
@@ -142,8 +142,8 @@ class PPS
$this->PrevPps = $prev;
$this->NextPps = $next;
$this->DirPps = $dir;
- $this->Time1st = $time_1st;
- $this->Time2nd = $time_2nd;
+ $this->Time1st = $time_1st ?? 0;
+ $this->Time2nd = $time_2nd ?? 0;
$this->_data = $data;
$this->children = $children;
if ($data != '') {
diff --git a/src/PhpSpreadsheet/Shared/OLE/PPS/Root.php b/src/PhpSpreadsheet/Shared/OLE/PPS/Root.php
index 2fe41055..c9b99a85 100644
--- a/src/PhpSpreadsheet/Shared/OLE/PPS/Root.php
+++ b/src/PhpSpreadsheet/Shared/OLE/PPS/Root.php
@@ -46,8 +46,8 @@ class Root extends PPS
private $bigBlockSize;
/**
- * @param int $time_1st A timestamp
- * @param int $time_2nd A timestamp
+ * @param null|float|int $time_1st A timestamp
+ * @param null|float|int $time_2nd A timestamp
* @param File[] $raChild
*/
public function __construct($time_1st, $time_2nd, $raChild)
diff --git a/src/PhpSpreadsheet/Shared/TimeZone.php b/src/PhpSpreadsheet/Shared/TimeZone.php
index 43fd3653..a6f98507 100644
--- a/src/PhpSpreadsheet/Shared/TimeZone.php
+++ b/src/PhpSpreadsheet/Shared/TimeZone.php
@@ -58,24 +58,20 @@ class TimeZone
* Return the Timezone offset used for date/time conversions to/from UST
* This requires both the timezone and the calculated date/time to allow for local DST.
*
- * @param string $timezone The timezone for finding the adjustment to UST
- * @param int $timestamp PHP date/time value
+ * @param ?string $timezone The timezone for finding the adjustment to UST
+ * @param float|int $timestamp PHP date/time value
*
* @return int Number of seconds for timezone adjustment
*/
public static function getTimeZoneAdjustment($timezone, $timestamp)
{
- if ($timezone !== null) {
- if (!self::validateTimezone($timezone)) {
- throw new PhpSpreadsheetException('Invalid timezone ' . $timezone);
- }
- } else {
- $timezone = self::$timezone;
+ $timezone = $timezone ?? self::$timezone;
+ $dtobj = Date::dateTimeFromTimestamp("$timestamp");
+ if (!self::validateTimezone($timezone)) {
+ throw new PhpSpreadsheetException("Invalid timezone $timezone");
}
+ $dtobj->setTimeZone(new DateTimeZone($timezone));
- $objTimezone = new DateTimeZone($timezone);
- $transitions = $objTimezone->getTransitions($timestamp, $timestamp);
-
- return (count($transitions) > 0) ? $transitions[0]['offset'] : 0;
+ return $dtobj->getOffset();
}
}
diff --git a/src/PhpSpreadsheet/Writer/Ods/Meta.php b/src/PhpSpreadsheet/Writer/Ods/Meta.php
index cd3054c0..16f7c8b5 100644
--- a/src/PhpSpreadsheet/Writer/Ods/Meta.php
+++ b/src/PhpSpreadsheet/Writer/Ods/Meta.php
@@ -2,7 +2,10 @@
namespace PhpOffice\PhpSpreadsheet\Writer\Ods;
+use PhpOffice\PhpSpreadsheet\Document\Properties;
+use PhpOffice\PhpSpreadsheet\Shared\Date;
use PhpOffice\PhpSpreadsheet\Shared\XMLWriter;
+use PhpOffice\PhpSpreadsheet\Spreadsheet;
class Meta extends WriterPart
{
@@ -40,15 +43,24 @@ class Meta extends WriterPart
$objWriter->writeElement('meta:initial-creator', $spreadsheet->getProperties()->getCreator());
$objWriter->writeElement('dc:creator', $spreadsheet->getProperties()->getCreator());
- $objWriter->writeElement('meta:creation-date', date(DATE_W3C, $spreadsheet->getProperties()->getCreated()));
- $objWriter->writeElement('dc:date', date(DATE_W3C, $spreadsheet->getProperties()->getCreated()));
+ $created = $spreadsheet->getProperties()->getCreated();
+ $date = Date::dateTimeFromTimestamp("$created");
+ $date->setTimeZone(Date::getDefaultOrLocalTimeZone());
+ $objWriter->writeElement('meta:creation-date', $date->format(DATE_W3C));
+ $created = $spreadsheet->getProperties()->getModified();
+ $date = Date::dateTimeFromTimestamp("$created");
+ $date->setTimeZone(Date::getDefaultOrLocalTimeZone());
+ $objWriter->writeElement('dc:date', $date->format(DATE_W3C));
$objWriter->writeElement('dc:title', $spreadsheet->getProperties()->getTitle());
$objWriter->writeElement('dc:description', $spreadsheet->getProperties()->getDescription());
$objWriter->writeElement('dc:subject', $spreadsheet->getProperties()->getSubject());
- $keywords = explode(' ', $spreadsheet->getProperties()->getKeywords());
- foreach ($keywords as $keyword) {
- $objWriter->writeElement('meta:keyword', $keyword);
- }
+ $objWriter->writeElement('meta:keyword', $spreadsheet->getProperties()->getKeywords());
+ // Don't know if this changed over time, but the keywords are all
+ // in a single declaration now.
+ //$keywords = explode(' ', $spreadsheet->getProperties()->getKeywords());
+ //foreach ($keywords as $keyword) {
+ // $objWriter->writeElement('meta:keyword', $keyword);
+ //}
//
$objWriter->startElement('meta:user-defined');
@@ -61,10 +73,50 @@ class Meta extends WriterPart
$objWriter->writeRaw($spreadsheet->getProperties()->getCategory());
$objWriter->endElement();
+ self::writeDocPropsCustom($objWriter, $spreadsheet);
+
$objWriter->endElement();
$objWriter->endElement();
return $objWriter->getData();
}
+
+ private static function writeDocPropsCustom(XMLWriter $objWriter, Spreadsheet $spreadsheet): void
+ {
+ $customPropertyList = $spreadsheet->getProperties()->getCustomProperties();
+ foreach ($customPropertyList as $key => $customProperty) {
+ $propertyValue = $spreadsheet->getProperties()->getCustomPropertyValue($customProperty);
+ $propertyType = $spreadsheet->getProperties()->getCustomPropertyType($customProperty);
+
+ $objWriter->startElement('meta:user-defined');
+ $objWriter->writeAttribute('meta:name', $customProperty);
+
+ switch ($propertyType) {
+ case Properties::PROPERTY_TYPE_INTEGER:
+ case Properties::PROPERTY_TYPE_FLOAT:
+ $objWriter->writeAttribute('meta:value-type', 'float');
+ $objWriter->writeRawData($propertyValue);
+
+ break;
+ case Properties::PROPERTY_TYPE_BOOLEAN:
+ $objWriter->writeAttribute('meta:value-type', 'boolean');
+ $objWriter->writeRawData($propertyValue ? 'true' : 'false');
+
+ break;
+ case Properties::PROPERTY_TYPE_DATE:
+ $objWriter->writeAttribute('meta:value-type', 'date');
+ $dtobj = Date::dateTimeFromTimestamp($propertyValue ?? 0);
+ $objWriter->writeRawData($dtobj->format(DATE_W3C));
+
+ break;
+ default:
+ $objWriter->writeRawData($propertyValue);
+
+ break;
+ }
+
+ $objWriter->endElement();
+ }
+ }
}
diff --git a/src/PhpSpreadsheet/Writer/Xls.php b/src/PhpSpreadsheet/Writer/Xls.php
index 4bece774..624dc414 100644
--- a/src/PhpSpreadsheet/Writer/Xls.php
+++ b/src/PhpSpreadsheet/Writer/Xls.php
@@ -766,7 +766,10 @@ class Xls extends BaseWriter
return $data;
}
- private function writeSummaryPropOle(int $dataProp, int &$dataSection_NumProps, array &$dataSection, int $sumdata, int $typdata): void
+ /**
+ * @param float|int $dataProp
+ */
+ private function writeSummaryPropOle($dataProp, int &$dataSection_NumProps, array &$dataSection, int $sumdata, int $typdata): void
{
if ($dataProp) {
$dataSection[] = [
diff --git a/src/PhpSpreadsheet/Writer/Xlsx/DocProps.php b/src/PhpSpreadsheet/Writer/Xlsx/DocProps.php
index 6332a34d..43ce442f 100644
--- a/src/PhpSpreadsheet/Writer/Xlsx/DocProps.php
+++ b/src/PhpSpreadsheet/Writer/Xlsx/DocProps.php
@@ -2,6 +2,8 @@
namespace PhpOffice\PhpSpreadsheet\Writer\Xlsx;
+use PhpOffice\PhpSpreadsheet\Document\Properties;
+use PhpOffice\PhpSpreadsheet\Shared\Date;
use PhpOffice\PhpSpreadsheet\Shared\XMLWriter;
use PhpOffice\PhpSpreadsheet\Spreadsheet;
@@ -137,13 +139,17 @@ class DocProps extends WriterPart
// dcterms:created
$objWriter->startElement('dcterms:created');
$objWriter->writeAttribute('xsi:type', 'dcterms:W3CDTF');
- $objWriter->writeRawData(date(DATE_W3C, $spreadsheet->getProperties()->getCreated()));
+ $created = $spreadsheet->getProperties()->getCreated();
+ $date = Date::dateTimeFromTimestamp("$created");
+ $objWriter->writeRawData($date->format(DATE_W3C));
$objWriter->endElement();
// dcterms:modified
$objWriter->startElement('dcterms:modified');
$objWriter->writeAttribute('xsi:type', 'dcterms:W3CDTF');
- $objWriter->writeRawData(date(DATE_W3C, $spreadsheet->getProperties()->getModified()));
+ $created = $spreadsheet->getProperties()->getModified();
+ $date = Date::dateTimeFromTimestamp("$created");
+ $objWriter->writeRawData($date->format(DATE_W3C));
$objWriter->endElement();
// dc:title
@@ -205,21 +211,22 @@ class DocProps extends WriterPart
$objWriter->writeAttribute('name', $customProperty);
switch ($propertyType) {
- case 'i':
+ case Properties::PROPERTY_TYPE_INTEGER:
$objWriter->writeElement('vt:i4', $propertyValue);
break;
- case 'f':
+ case Properties::PROPERTY_TYPE_FLOAT:
$objWriter->writeElement('vt:r8', $propertyValue);
break;
- case 'b':
+ case Properties::PROPERTY_TYPE_BOOLEAN:
$objWriter->writeElement('vt:bool', ($propertyValue) ? 'true' : 'false');
break;
- case 'd':
+ case Properties::PROPERTY_TYPE_DATE:
$objWriter->startElement('vt:filetime');
- $objWriter->writeRawData(date(DATE_W3C, $propertyValue));
+ $date = Date::dateTimeFromTimestamp("$propertyValue");
+ $objWriter->writeRawData($date->format(DATE_W3C));
$objWriter->endElement();
break;
diff --git a/tests/PhpSpreadsheetTests/Document/EpochTest.php b/tests/PhpSpreadsheetTests/Document/EpochTest.php
new file mode 100644
index 00000000..63c51a59
--- /dev/null
+++ b/tests/PhpSpreadsheetTests/Document/EpochTest.php
@@ -0,0 +1,94 @@
+getActiveSheet();
+ $sheet->getCell('A1')->setValue(1);
+ $spreadsheet->getProperties()->setCreated($timestamp);
+ $timestamp2 = preg_replace('/1-/', '2-', $timestamp);
+ self::AssertNotEquals($timestamp, $timestamp2);
+ $spreadsheet->getProperties()->setModified($timestamp2);
+ $timestamp3 = preg_replace('/1-/', '3-', $timestamp);
+ self::AssertNotEquals($timestamp, $timestamp3);
+ self::AssertNotEquals($timestamp2, $timestamp3);
+ $spreadsheet->getProperties()->setCustomProperty('cprop', $timestamp3, 'd');
+ $reloadedSpreadsheet = $this->writeAndReload($spreadsheet, $format);
+ $created = $reloadedSpreadsheet->getProperties()->getCreated();
+ $dt1 = DateTime::createFromFormat('U', "$created");
+ $modified = $reloadedSpreadsheet->getProperties()->getModified();
+ $dt2 = DateTime::createFromFormat('U', "$modified");
+ if ($dt1 === false || $dt2 === false) {
+ self::fail('Invalid timestamp for created or modified');
+ } else {
+ self::assertSame($timestamp, $dt1->format('Y-m-d H:i:s') . 'Z');
+ self::assertSame($timestamp2, $dt2->format('Y-m-d H:i:s') . 'Z');
+ }
+ if ($format === 'Xlsx' || $format === 'Ods') {
+ // No custom property support in Xls
+ $cprop = $reloadedSpreadsheet->getProperties()->getCustomPropertyValue('cprop');
+ if (!is_numeric($cprop)) {
+ self::fail('Cannot find custom property');
+ } else {
+ $dt3 = DateTime::createFromFormat('U', "$cprop");
+ if ($dt3 === false) {
+ self::fail('Invalid timestamp for custom property');
+ } else {
+ self::assertSame($timestamp3, $dt3->format('Y-m-d H:i:s') . 'Z');
+ }
+ }
+ }
+ }
+
+ public function providerFormats2(): array
+ {
+ return [
+ ['Ods'],
+ ['Xls'],
+ ['Xlsx'],
+ ];
+ }
+
+ /**
+ * @dataProvider providerFormats2
+ */
+ public function testConsistentTimeStamp(string $format): void
+ {
+ $pgmstart = (float) (new DateTime())->format('U');
+ $spreadsheet = new Spreadsheet();
+ $sheet = $spreadsheet->getActiveSheet();
+ $sheet->getCell('A1')->setValue(1);
+ $reloadedSpreadsheet = $this->writeAndReload($spreadsheet, $format);
+ $pgmend = (float) (new DateTime())->format('U');
+ self::assertLessThanOrEqual($pgmend, $pgmstart);
+ $created = $reloadedSpreadsheet->getProperties()->getCreated();
+ $modified = $reloadedSpreadsheet->getProperties()->getModified();
+ self::assertLessThanOrEqual($pgmend, $created);
+ self::assertLessThanOrEqual($pgmend, $modified);
+ self::assertLessThanOrEqual($created, $pgmstart);
+ self::assertLessThanOrEqual($modified, $pgmstart);
+ }
+}
diff --git a/tests/PhpSpreadsheetTests/Document/PropertiesTest.php b/tests/PhpSpreadsheetTests/Document/PropertiesTest.php
index 54932bb8..c539da09 100644
--- a/tests/PhpSpreadsheetTests/Document/PropertiesTest.php
+++ b/tests/PhpSpreadsheetTests/Document/PropertiesTest.php
@@ -2,7 +2,9 @@
namespace PhpOffice\PhpSpreadsheetTests\Document;
+use DateTimeZone;
use PhpOffice\PhpSpreadsheet\Document\Properties;
+use PhpOffice\PhpSpreadsheet\Shared\Date;
use PHPUnit\Framework\TestCase;
class PropertiesTest extends TestCase
@@ -23,7 +25,7 @@ class PropertiesTest extends TestCase
self::assertSame('Unknown Creator', $this->properties->getCreator());
self::assertSame('Unknown Creator', $this->properties->getLastModifiedBy());
self::assertSame('Untitled Spreadsheet', $this->properties->getTitle());
- self::assertSame('Microsoft Corporation', $this->properties->getCompany());
+ self::assertSame('', $this->properties->getCompany());
self::assertSame($createdTime, $this->properties->getCreated());
self::assertSame($modifiedTime, $this->properties->getModified());
}
@@ -159,8 +161,12 @@ class PropertiesTest extends TestCase
{
$this->properties->setCustomProperty($propertyName, ...$args);
self::assertTrue($this->properties->isCustomPropertySet($propertyName));
- self::assertSame($expectedValue, $this->properties->getCustomPropertyValue($propertyName));
self::assertSame($expectedType, $this->properties->getCustomPropertyType($propertyName));
+ $result = $this->properties->getCustomPropertyValue($propertyName);
+ if ($expectedType === Properties::PROPERTY_TYPE_DATE) {
+ $result = Date::formattedDateTimeFromTimestamp("$result", 'Y-m-d', new DateTimeZone('UTC'));
+ }
+ self::assertSame($expectedValue, $result);
}
public function providerCustomProperties(): array
diff --git a/tests/PhpSpreadsheetTests/Reader/Ods/OdsPropertiesTest.php b/tests/PhpSpreadsheetTests/Reader/Ods/OdsPropertiesTest.php
new file mode 100644
index 00000000..577b4221
--- /dev/null
+++ b/tests/PhpSpreadsheetTests/Reader/Ods/OdsPropertiesTest.php
@@ -0,0 +1,112 @@
+timeZone = date_default_timezone_get();
+ date_default_timezone_set('UTC');
+ }
+
+ protected function tearDown(): void
+ {
+ date_default_timezone_set($this->timeZone);
+ }
+
+ public function testLoadOdsWorkbookProperties(): void
+ {
+ $customPropertySet = [
+ 'Owner' => ['type' => Properties::PROPERTY_TYPE_STRING, 'value' => 'PHPOffice'],
+ 'Tested' => ['type' => Properties::PROPERTY_TYPE_BOOLEAN, 'value' => true],
+ 'Counter' => ['type' => Properties::PROPERTY_TYPE_FLOAT, 'value' => 10.0],
+ 'TestDate' => ['type' => Properties::PROPERTY_TYPE_DATE, 'value' => '2019-06-30'],
+ 'HereAndNow' => ['type' => Properties::PROPERTY_TYPE_DATE, 'value' => '2019-06-30'],
+ ];
+
+ $filename = 'tests/data/Reader/Ods/propertyTest.ods';
+ $reader = new Ods();
+ $spreadsheet = $reader->load($filename);
+
+ $properties = $spreadsheet->getProperties();
+ // Core Properties
+// self::assertSame('Mark Baker', $properties->getCreator());
+ self::assertSame('Property Test File', $properties->getTitle());
+ self::assertSame('Testing for Properties', $properties->getSubject());
+ self::assertSame('TEST ODS PHPSpreadsheet', $properties->getKeywords());
+
+ // Extended Properties
+// self::assertSame('PHPOffice', $properties->getCompany());
+// self::assertSame('The Big Boss', $properties->getManager());
+
+ // Custom Properties
+ $customProperties = $properties->getCustomProperties();
+ self::assertIsArray($customProperties);
+ $customProperties = array_flip($customProperties);
+ self::assertArrayHasKey('TestDate', $customProperties);
+
+ foreach ($customPropertySet as $propertyName => $testData) {
+ self::assertTrue($properties->isCustomPropertySet($propertyName));
+ self::assertSame($testData['type'], $properties->getCustomPropertyType($propertyName));
+ $result = $properties->getCustomPropertyValue($propertyName);
+ if ($properties->getCustomPropertyType($propertyName) == Properties::PROPERTY_TYPE_DATE) {
+ $result = Date::formattedDateTimeFromTimestamp("$result", 'Y-m-d');
+ }
+ self::assertSame($testData['value'], $result);
+ }
+ }
+
+ public function testReloadOdsWorkbookProperties(): void
+ {
+ $customPropertySet = [
+ 'Owner' => ['type' => Properties::PROPERTY_TYPE_STRING, 'value' => 'PHPOffice'],
+ 'Tested' => ['type' => Properties::PROPERTY_TYPE_BOOLEAN, 'value' => true],
+ 'Counter' => ['type' => Properties::PROPERTY_TYPE_FLOAT, 'value' => 10.0],
+ 'TestDate' => ['type' => Properties::PROPERTY_TYPE_DATE, 'value' => '2019-06-30'],
+ 'HereAndNow' => ['type' => Properties::PROPERTY_TYPE_DATE, 'value' => '2019-06-30'],
+ ];
+
+ $filename = 'tests/data/Reader/Ods/propertyTest.ods';
+ $reader = new Ods();
+ $spreadsheetOld = $reader->load($filename);
+ $spreadsheet = $this->writeAndReload($spreadsheetOld, 'Ods');
+
+ $properties = $spreadsheet->getProperties();
+ // Core Properties
+// self::assertSame('Mark Baker', $properties->getCreator());
+ self::assertSame('Property Test File', $properties->getTitle());
+ self::assertSame('Testing for Properties', $properties->getSubject());
+ self::assertSame('TEST ODS PHPSpreadsheet', $properties->getKeywords());
+
+ // Extended Properties
+// self::assertSame('PHPOffice', $properties->getCompany());
+// self::assertSame('The Big Boss', $properties->getManager());
+
+ // Custom Properties
+ $customProperties = $properties->getCustomProperties();
+ self::assertIsArray($customProperties);
+ $customProperties = array_flip($customProperties);
+ self::assertArrayHasKey('TestDate', $customProperties);
+
+ foreach ($customPropertySet as $propertyName => $testData) {
+ self::assertTrue($properties->isCustomPropertySet($propertyName));
+ self::assertSame($testData['type'], $properties->getCustomPropertyType($propertyName));
+ $result = $properties->getCustomPropertyValue($propertyName);
+ if ($properties->getCustomPropertyType($propertyName) == Properties::PROPERTY_TYPE_DATE) {
+ $result = Date::formattedDateTimeFromTimestamp("$result", 'Y-m-d');
+ }
+ self::assertSame($testData['value'], $result);
+ }
+ }
+}
diff --git a/tests/PhpSpreadsheetTests/Reader/Ods/OdsTest.php b/tests/PhpSpreadsheetTests/Reader/Ods/OdsTest.php
index 10910207..a7f1466c 100644
--- a/tests/PhpSpreadsheetTests/Reader/Ods/OdsTest.php
+++ b/tests/PhpSpreadsheetTests/Reader/Ods/OdsTest.php
@@ -290,46 +290,4 @@ class OdsTest extends TestCase
self::assertTrue($style->getFont()->getBold());
self::assertTrue($style->getFont()->getItalic());
}
-
- public function testLoadOdsWorkbookProperties(): void
- {
- $customPropertySet = [
- 'Owner' => ['type' => Properties::PROPERTY_TYPE_STRING, 'value' => 'PHPOffice'],
- 'Tested' => ['type' => Properties::PROPERTY_TYPE_BOOLEAN, 'value' => true],
- 'Counter' => ['type' => Properties::PROPERTY_TYPE_FLOAT, 'value' => 10.0],
- 'TestDate' => ['type' => Properties::PROPERTY_TYPE_DATE, 'value' => '2019-06-30'],
- 'HereAndNow' => ['type' => Properties::PROPERTY_TYPE_DATE, 'value' => '2019-06-30'],
- ];
-
- $filename = 'tests/data/Reader/Ods/propertyTest.ods';
- $reader = new Ods();
- $spreadsheet = $reader->load($filename);
-
- $properties = $spreadsheet->getProperties();
- // Core Properties
-// self::assertSame('Mark Baker', $properties->getCreator());
- self::assertSame('Property Test File', $properties->getTitle());
- self::assertSame('Testing for Properties', $properties->getSubject());
- self::assertSame('TEST ODS PHPSpreadsheet', $properties->getKeywords());
-
- // Extended Properties
-// self::assertSame('PHPOffice', $properties->getCompany());
-// self::assertSame('The Big Boss', $properties->getManager());
-
- // Custom Properties
- $customProperties = $properties->getCustomProperties();
- self::assertIsArray($customProperties);
- $customProperties = array_flip($customProperties);
- self::assertArrayHasKey('TestDate', $customProperties);
-
- foreach ($customPropertySet as $propertyName => $testData) {
- self::assertTrue($properties->isCustomPropertySet($propertyName));
- self::assertSame($testData['type'], $properties->getCustomPropertyType($propertyName));
- if ($properties->getCustomPropertyType($propertyName) == Properties::PROPERTY_TYPE_DATE) {
- self::assertSame($testData['value'], date('Y-m-d', $properties->getCustomPropertyValue($propertyName)));
- } else {
- self::assertSame($testData['value'], $properties->getCustomPropertyValue($propertyName));
- }
- }
- }
}
diff --git a/tests/PhpSpreadsheetTests/Reader/Xlsx/PropertiesTest.php b/tests/PhpSpreadsheetTests/Reader/Xlsx/PropertiesTest.php
new file mode 100644
index 00000000..bb414da5
--- /dev/null
+++ b/tests/PhpSpreadsheetTests/Reader/Xlsx/PropertiesTest.php
@@ -0,0 +1,95 @@
+ ['type' => Properties::PROPERTY_TYPE_STRING, 'value' => 'PHPOffice Suite'],
+ 'Tested' => ['type' => Properties::PROPERTY_TYPE_BOOLEAN, 'value' => true],
+ 'Counter' => ['type' => Properties::PROPERTY_TYPE_INTEGER, 'value' => 15],
+ 'Rate' => ['type' => Properties::PROPERTY_TYPE_FLOAT, 'value' => 1.15],
+ 'Refactor Date' => ['type' => Properties::PROPERTY_TYPE_DATE, 'value' => '2019-06-10'],
+ ];
+
+ $filename = 'tests/data/Reader/XLSX/propertyTest.xlsx';
+ $reader = new Xlsx();
+ $spreadsheet = $reader->load($filename);
+
+ $properties = $spreadsheet->getProperties();
+ // Core Properties
+ self::assertSame('Mark Baker', $properties->getCreator());
+ self::assertSame('Unit Testing', $properties->getTitle());
+ self::assertSame('Property Test', $properties->getSubject());
+
+ // Extended Properties
+ self::assertSame('PHPOffice', $properties->getCompany());
+ self::assertSame('The Big Boss', $properties->getManager());
+
+ // Custom Properties
+ $customProperties = $properties->getCustomProperties();
+ self::assertIsArray($customProperties);
+ $customProperties = array_flip($customProperties);
+ self::assertArrayHasKey('Publisher', $customProperties);
+
+ foreach ($customPropertySet as $propertyName => $testData) {
+ self::assertTrue($properties->isCustomPropertySet($propertyName));
+ self::assertSame($testData['type'], $properties->getCustomPropertyType($propertyName));
+ $result = $properties->getCustomPropertyValue($propertyName);
+ if ($properties->getCustomPropertyType($propertyName) == Properties::PROPERTY_TYPE_DATE) {
+ $result = Date::formattedDateTimeFromTimestamp("$result", 'Y-m-d', new DateTimeZone('UTC'));
+ }
+ self::assertSame($testData['value'], $result);
+ }
+ }
+
+ public function testReloadXlsxWorkbookProperties(): void
+ {
+ $customPropertySet = [
+ 'Publisher' => ['type' => Properties::PROPERTY_TYPE_STRING, 'value' => 'PHPOffice Suite'],
+ 'Tested' => ['type' => Properties::PROPERTY_TYPE_BOOLEAN, 'value' => true],
+ 'Counter' => ['type' => Properties::PROPERTY_TYPE_INTEGER, 'value' => 15],
+ 'Rate' => ['type' => Properties::PROPERTY_TYPE_FLOAT, 'value' => 1.15],
+ 'Refactor Date' => ['type' => Properties::PROPERTY_TYPE_DATE, 'value' => '2019-06-10'],
+ ];
+
+ $filename = 'tests/data/Reader/XLSX/propertyTest.xlsx';
+ $reader = new Xlsx();
+ $spreadsheetOld = $reader->load($filename);
+ $spreadsheet = $this->writeAndReload($spreadsheetOld, 'Xlsx');
+
+ $properties = $spreadsheet->getProperties();
+ // Core Properties
+ self::assertSame('Mark Baker', $properties->getCreator());
+ self::assertSame('Unit Testing', $properties->getTitle());
+ self::assertSame('Property Test', $properties->getSubject());
+
+ // Extended Properties
+ self::assertSame('PHPOffice', $properties->getCompany());
+ self::assertSame('The Big Boss', $properties->getManager());
+
+ // Custom Properties
+ $customProperties = $properties->getCustomProperties();
+ self::assertIsArray($customProperties);
+ $customProperties = array_flip($customProperties);
+ self::assertArrayHasKey('Publisher', $customProperties);
+
+ foreach ($customPropertySet as $propertyName => $testData) {
+ self::assertTrue($properties->isCustomPropertySet($propertyName));
+ self::assertSame($testData['type'], $properties->getCustomPropertyType($propertyName));
+ $result = $properties->getCustomPropertyValue($propertyName);
+ if ($properties->getCustomPropertyType($propertyName) == Properties::PROPERTY_TYPE_DATE) {
+ $result = Date::formattedDateTimeFromTimestamp("$result", 'Y-m-d', new DateTimeZone('UTC'));
+ }
+ self::assertSame($testData['value'], $result);
+ }
+ }
+}
diff --git a/tests/PhpSpreadsheetTests/Reader/XlsxTest.php b/tests/PhpSpreadsheetTests/Reader/XlsxTest.php
index 738a25b9..b5b26712 100644
--- a/tests/PhpSpreadsheetTests/Reader/XlsxTest.php
+++ b/tests/PhpSpreadsheetTests/Reader/XlsxTest.php
@@ -14,47 +14,6 @@ use PHPUnit\Framework\TestCase;
class XlsxTest extends TestCase
{
- public function testLoadXlsxWorkbookProperties(): void
- {
- $customPropertySet = [
- 'Publisher' => ['type' => Properties::PROPERTY_TYPE_STRING, 'value' => 'PHPOffice Suite'],
- 'Tested' => ['type' => Properties::PROPERTY_TYPE_BOOLEAN, 'value' => true],
- 'Counter' => ['type' => Properties::PROPERTY_TYPE_INTEGER, 'value' => 15],
- 'Rate' => ['type' => Properties::PROPERTY_TYPE_FLOAT, 'value' => 1.15],
- 'Refactor Date' => ['type' => Properties::PROPERTY_TYPE_DATE, 'value' => '2019-06-10'],
- ];
-
- $filename = 'tests/data/Reader/XLSX/propertyTest.xlsx';
- $reader = new Xlsx();
- $spreadsheet = $reader->load($filename);
-
- $properties = $spreadsheet->getProperties();
- // Core Properties
- self::assertSame('Mark Baker', $properties->getCreator());
- self::assertSame('Unit Testing', $properties->getTitle());
- self::assertSame('Property Test', $properties->getSubject());
-
- // Extended Properties
- self::assertSame('PHPOffice', $properties->getCompany());
- self::assertSame('The Big Boss', $properties->getManager());
-
- // Custom Properties
- $customProperties = $properties->getCustomProperties();
- self::assertIsArray($customProperties);
- $customProperties = array_flip($customProperties);
- self::assertArrayHasKey('Publisher', $customProperties);
-
- foreach ($customPropertySet as $propertyName => $testData) {
- self::assertTrue($properties->isCustomPropertySet($propertyName));
- self::assertSame($testData['type'], $properties->getCustomPropertyType($propertyName));
- if ($properties->getCustomPropertyType($propertyName) == Properties::PROPERTY_TYPE_DATE) {
- self::assertSame($testData['value'], date('Y-m-d', $properties->getCustomPropertyValue($propertyName)));
- } else {
- self::assertSame($testData['value'], $properties->getCustomPropertyValue($propertyName));
- }
- }
- }
-
public function testListWorksheetInfo(): void
{
$filename = 'tests/data/Reader/XLSX/rowColumnAttributeTest.xlsx';
diff --git a/tests/PhpSpreadsheetTests/Shared/DateTest.php b/tests/PhpSpreadsheetTests/Shared/DateTest.php
index 1ca4c674..e4bf6838 100644
--- a/tests/PhpSpreadsheetTests/Shared/DateTest.php
+++ b/tests/PhpSpreadsheetTests/Shared/DateTest.php
@@ -21,7 +21,7 @@ class DateTest extends TestCase
protected function setUp(): void
{
- $this->dttimezone = Date::getDefaultTimeZone();
+ $this->dttimezone = Date::getDefaultTimeZoneOrNull();
$this->excelCalendar = Date::getExcelCalendar();
}
diff --git a/tests/PhpSpreadsheetTests/Shared/TimeZoneTest.php b/tests/PhpSpreadsheetTests/Shared/TimeZoneTest.php
index edad6e6b..0efdc05f 100644
--- a/tests/PhpSpreadsheetTests/Shared/TimeZoneTest.php
+++ b/tests/PhpSpreadsheetTests/Shared/TimeZoneTest.php
@@ -23,7 +23,7 @@ class TimeZoneTest extends TestCase
protected function setUp(): void
{
$this->tztimezone = TimeZone::getTimeZone();
- $this->dttimezone = Date::getDefaultTimeZone();
+ $this->dttimezone = Date::getDefaultTimeZoneOrNull();
}
protected function tearDown(): void
@@ -72,24 +72,32 @@ class TimeZoneTest extends TestCase
{
$this->expectException(\PhpOffice\PhpSpreadsheet\Exception::class);
$dtobj = DateTime::createFromFormat('Y-m-d H:i:s', '2008-09-22 00:00:00');
- $tstmp = $dtobj->getTimestamp();
- $unsupportedTimeZone = 'XEtc/GMT+10';
- TimeZone::getTimeZoneAdjustment($unsupportedTimeZone, $tstmp);
+ if ($dtobj === false) {
+ self::fail('DateTime createFromFormat failed');
+ } else {
+ $tstmp = $dtobj->getTimestamp();
+ $unsupportedTimeZone = 'XEtc/GMT+10';
+ TimeZone::getTimeZoneAdjustment($unsupportedTimeZone, $tstmp);
+ }
}
public function testTimeZoneAdjustments(): void
{
$dtobj = DateTime::createFromFormat('Y-m-d H:i:s', '2008-01-01 00:00:00');
- $tstmp = $dtobj->getTimestamp();
- $supportedTimeZone = 'UTC';
- $adj = TimeZone::getTimeZoneAdjustment($supportedTimeZone, $tstmp);
- self::assertEquals(0, $adj);
- $supportedTimeZone = 'America/Toronto';
- $adj = TimeZone::getTimeZoneAdjustment($supportedTimeZone, $tstmp);
- self::assertEquals(-18000, $adj);
- $supportedTimeZone = 'America/Chicago';
- TimeZone::setTimeZone($supportedTimeZone);
- $adj = TimeZone::getTimeZoneAdjustment(null, $tstmp);
- self::assertEquals(-21600, $adj);
+ if ($dtobj === false) {
+ self::fail('DateTime createFromFormat failed');
+ } else {
+ $tstmp = $dtobj->getTimestamp();
+ $supportedTimeZone = 'UTC';
+ $adj = TimeZone::getTimeZoneAdjustment($supportedTimeZone, $tstmp);
+ self::assertEquals(0, $adj);
+ $supportedTimeZone = 'America/Toronto';
+ $adj = TimeZone::getTimeZoneAdjustment($supportedTimeZone, $tstmp);
+ self::assertEquals(-18000, $adj);
+ $supportedTimeZone = 'America/Chicago';
+ TimeZone::setTimeZone($supportedTimeZone);
+ $adj = TimeZone::getTimeZoneAdjustment(null, $tstmp);
+ self::assertEquals(-21600, $adj);
+ }
}
}
diff --git a/tests/PhpSpreadsheetTests/Writer/Xls/XlsGifBmpTest.php b/tests/PhpSpreadsheetTests/Writer/Xls/XlsGifBmpTest.php
index 03f201be..dea47522 100644
--- a/tests/PhpSpreadsheetTests/Writer/Xls/XlsGifBmpTest.php
+++ b/tests/PhpSpreadsheetTests/Writer/Xls/XlsGifBmpTest.php
@@ -2,6 +2,7 @@
namespace PhpOffice\PhpSpreadsheetTests\Writer\Xls;
+use DateTime;
use PhpOffice\PhpSpreadsheet\Spreadsheet;
use PhpOffice\PhpSpreadsheet\Worksheet\Drawing;
use PhpOffice\PhpSpreadsheet\Worksheet\MemoryDrawing;
@@ -24,7 +25,7 @@ class XlsGifBmpTest extends AbstractFunctional
public function testBmp(): void
{
- $pgmstart = time();
+ $pgmstart = (float) (new DateTime())->format('U');
$spreadsheet = new Spreadsheet();
$filstart = $spreadsheet->getProperties()->getModified();
self::assertLessThanOrEqual($filstart, $pgmstart);
@@ -49,7 +50,7 @@ class XlsGifBmpTest extends AbstractFunctional
$mimeType = ($drawing instanceof MemoryDrawing) ? $drawing->getMimeType() : 'notmemorydrawing';
self::assertEquals('image/png', $mimeType);
}
- $pgmend = time();
+ $pgmend = (float) (new DateTime())->format('U');
self::assertLessThanOrEqual($pgmend, $pgmstart);
self::assertLessThanOrEqual($pgmend, $filstart);