AutorÃa | Ultima modificación | Ver Log |
<?php
namespace PhpOffice\PhpSpreadsheet\Calculation\DateTimeExcel;
use Composer\Pcre\Preg;
use Datetime;
use PhpOffice\PhpSpreadsheet\Calculation\ArrayEnabled;
use PhpOffice\PhpSpreadsheet\Calculation\Functions;
use PhpOffice\PhpSpreadsheet\Calculation\Information\ExcelError;
use PhpOffice\PhpSpreadsheet\Shared\Date as SharedDateHelper;
class TimeValue
{
use ArrayEnabled;
private const EXTRACT_TIME = '/\b'
. '(\d+)' // match[1] - hour
. '(:' // start of match[2] (rest of string) - colon
. '(\d+' // start of match[3] - minute
. '(:\d+' // start of match[4] - colon and seconds
. '([.]\d+)?' // match[5] - optional decimal point followed by fractional seconds
. ')?' // end of match[4], which is optional
. ')' // end of match 3
// Excel does not require 'm' to trail 'a' or 'p'; Php does
. '(\s*(a|p))?' // match[6] optional whitespace followed by optional match[7] a or p
. ')' // end of match[2]
. '/i';
/**
* TIMEVALUE.
*
* Returns a value that represents a particular time.
* Use TIMEVALUE to convert a time represented by a text string to an Excel or PHP date/time stamp
* value.
*
* NOTE: When used in a Cell Formula, MS Excel changes the cell format so that it matches the time
* format of your regional settings. PhpSpreadsheet does not change cell formatting in this way.
*
* Excel Function:
* TIMEVALUE(timeValue)
*
* @param null|array|bool|float|int|string $timeValue A text string that represents a time in any one of the Microsoft
* Excel time formats; for example, "6:45 PM" and "18:45" text strings
* within quotation marks that represent time.
* Date information in time_text is ignored.
* Or can be an array of date/time values
*
* @return array|Datetime|float|int|string Excel date/time serial value, PHP date/time serial value or PHP date/time object,
* depending on the value of the ReturnDateType flag
* If an array of numbers is passed as the argument, then the returned result will also be an array
* with the same dimensions
*/
public static function fromString(null|array|string|int|bool|float $timeValue): array|string|Datetime|int|float
{
if (is_array($timeValue)) {
return self::evaluateSingleArgumentArray([self::class, __FUNCTION__], $timeValue);
}
// try to parse as time iff there is at least one digit
if (is_string($timeValue) && !Preg::isMatch('/\d/', $timeValue)) {
return ExcelError::VALUE();
}
$timeValue = trim((string) $timeValue, '"');
if (Preg::isMatch(self::EXTRACT_TIME, $timeValue, $matches)) {
if (empty($matches[6])) { // am/pm
$hour = (int) $matches[0];
$timeValue = ($hour % 24) . $matches[2];
} elseif ($matches[6] === $matches[7]) { // Excel wants space before am/pm
return ExcelError::VALUE();
} else {
$timeValue = $matches[0] . 'm';
}
}
$PHPDateArray = Helpers::dateParse($timeValue);
$retValue = ExcelError::VALUE();
if (Helpers::dateParseSucceeded($PHPDateArray)) {
$hour = $PHPDateArray['hour'];
$minute = $PHPDateArray['minute'];
$second = $PHPDateArray['second'];
// OpenOffice-specific code removed - it works just like Excel
$excelDateValue = SharedDateHelper::formattedPHPToExcel(1900, 1, 1, $hour, $minute, $second) - 1;
$retType = Functions::getReturnDateType();
if ($retType === Functions::RETURNDATE_EXCEL) {
$retValue = (float) $excelDateValue;
} elseif ($retType === Functions::RETURNDATE_UNIX_TIMESTAMP) {
$retValue = (int) SharedDateHelper::excelToTimestamp($excelDateValue + 25569) - 3600;
} else {
$retValue = new Datetime('1900-01-01 ' . $PHPDateArray['hour'] . ':' . $PHPDateArray['minute'] . ':' . $PHPDateArray['second']);
}
}
return $retValue;
}
}