336 lines
11 KiB
PHP
336 lines
11 KiB
PHP
<?php
|
|
/**
|
|
* Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
|
|
*
|
|
* Licensed under The MIT License
|
|
* Redistributions of files must retain the above copyright notice.
|
|
*
|
|
* @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
|
|
* @copyright Copyright (c) Brian Nesbitt <brian@nesbot.com>
|
|
* @link http://cakephp.org CakePHP(tm) Project
|
|
* @license http://www.opensource.org/licenses/mit-license.php MIT License
|
|
*/
|
|
namespace Cake\Chronos\Traits;
|
|
|
|
use DateTimeInterface;
|
|
use DateTimeZone;
|
|
use InvalidArgumentException;
|
|
|
|
/**
|
|
* Provides a number of datetime related factory methods.
|
|
*/
|
|
trait FactoryTrait
|
|
{
|
|
/**
|
|
* Holds the last error generated by createFromFormat
|
|
*
|
|
* @var array
|
|
*/
|
|
protected static $_lastErrors = [];
|
|
|
|
/**
|
|
* Create a ChronosInterface instance from a DateTimeInterface one
|
|
*
|
|
* @param \DateTimeInterface $dt The datetime instance to convert.
|
|
* @return static
|
|
*/
|
|
public static function instance(DateTimeInterface $dt)
|
|
{
|
|
if ($dt instanceof static) {
|
|
return clone $dt;
|
|
}
|
|
|
|
return new static($dt->format('Y-m-d H:i:s.u'), $dt->getTimezone());
|
|
}
|
|
|
|
/**
|
|
* Create a ChronosInterface instance from a string. This is an alias for the
|
|
* constructor that allows better fluent syntax as it allows you to do
|
|
* ChronosInterface::parse('Monday next week')->fn() rather than
|
|
* (new Chronos('Monday next week'))->fn()
|
|
*
|
|
* @param \DateTimeInterface|string $time The strtotime compatible string to parse
|
|
* @param \DateTimeZone|string|null $tz The DateTimeZone object or timezone name.
|
|
* @return static
|
|
*/
|
|
public static function parse($time = 'now', $tz = null)
|
|
{
|
|
return new static($time, $tz);
|
|
}
|
|
|
|
/**
|
|
* Get a ChronosInterface instance for the current date and time
|
|
*
|
|
* @param \DateTimeZone|string|null $tz The DateTimeZone object or timezone name.
|
|
* @return static
|
|
*/
|
|
public static function now($tz = null)
|
|
{
|
|
return new static('now', $tz);
|
|
}
|
|
|
|
/**
|
|
* Create a ChronosInterface instance for today
|
|
*
|
|
* @param \DateTimeZone|string|null $tz The timezone to use.
|
|
* @return static
|
|
*/
|
|
public static function today($tz = null)
|
|
{
|
|
return new static('midnight', $tz);
|
|
}
|
|
|
|
/**
|
|
* Create a ChronosInterface instance for tomorrow
|
|
*
|
|
* @param \DateTimeZone|string|null $tz The DateTimeZone object or timezone name the new instance should use.
|
|
* @return static
|
|
*/
|
|
public static function tomorrow($tz = null)
|
|
{
|
|
return new static('tomorrow, midnight', $tz);
|
|
}
|
|
|
|
/**
|
|
* Create a ChronosInterface instance for yesterday
|
|
*
|
|
* @param \DateTimeZone|string|null $tz The DateTimeZone object or timezone name the new instance should use.
|
|
* @return static
|
|
*/
|
|
public static function yesterday($tz = null)
|
|
{
|
|
return new static('yesterday, midnight', $tz);
|
|
}
|
|
|
|
/**
|
|
* Create a ChronosInterface instance for the greatest supported date.
|
|
*
|
|
* @return \Cake\Chronos\ChronosInterface
|
|
*/
|
|
public static function maxValue()
|
|
{
|
|
return static::createFromTimestampUTC(PHP_INT_MAX);
|
|
}
|
|
|
|
/**
|
|
* Create a ChronosInterface instance for the lowest supported date.
|
|
*
|
|
* @return \Cake\Chronos\ChronosInterface
|
|
*/
|
|
public static function minValue()
|
|
{
|
|
$max = PHP_INT_SIZE === 4 ? PHP_INT_MAX : PHP_INT_MAX / 10;
|
|
|
|
return static::createFromTimestampUTC(~$max);
|
|
}
|
|
|
|
/**
|
|
* Create a new ChronosInterface instance from a specific date and time.
|
|
*
|
|
* If any of $year, $month or $day are set to null their now() values
|
|
* will be used.
|
|
*
|
|
* If $hour is null it will be set to its now() value and the default values
|
|
* for $minute and $second will be their now() values.
|
|
* If $hour is not null then the default values for $minute and $second
|
|
* will be 0.
|
|
*
|
|
* @param int|null $year The year to create an instance with.
|
|
* @param int|null $month The month to create an instance with.
|
|
* @param int|null $day The day to create an instance with.
|
|
* @param int|null $hour The hour to create an instance with.
|
|
* @param int|null $minute The minute to create an instance with.
|
|
* @param int|null $second The second to create an instance with.
|
|
* @param \DateTimeZone|string|null $tz The DateTimeZone object or timezone name the new instance should use.
|
|
* @return static
|
|
*/
|
|
public static function create($year = null, $month = null, $day = null, $hour = null, $minute = null, $second = null, $tz = null)
|
|
{
|
|
$year = ($year === null) ? date('Y') : $year;
|
|
$month = ($month === null) ? date('n') : $month;
|
|
$day = ($day === null) ? date('j') : $day;
|
|
|
|
if ($hour === null) {
|
|
$hour = date('G');
|
|
$minute = ($minute === null) ? date('i') : $minute;
|
|
$second = ($second === null) ? date('s') : $second;
|
|
} else {
|
|
$minute = ($minute === null) ? 0 : $minute;
|
|
$second = ($second === null) ? 0 : $second;
|
|
}
|
|
|
|
$instance = static::createFromFormat('Y-n-j G:i:s', sprintf('%s-%s-%s %s:%02s:%02s', 0, $month, $day, $hour, $minute, $second), $tz);
|
|
|
|
return $instance->addYears($year);
|
|
}
|
|
|
|
/**
|
|
* Create a ChronosInterface instance from just a date. The time portion is set to now.
|
|
*
|
|
* @param int $year The year to create an instance with.
|
|
* @param int $month The month to create an instance with.
|
|
* @param int $day The day to create an instance with.
|
|
* @param \DateTimeZone|string|null $tz The DateTimeZone object or timezone name the new instance should use.
|
|
* @return static
|
|
*/
|
|
public static function createFromDate($year = null, $month = null, $day = null, $tz = null)
|
|
{
|
|
return static::create($year, $month, $day, null, null, null, $tz);
|
|
}
|
|
|
|
/**
|
|
* Create a ChronosInterface instance from just a time. The date portion is set to today.
|
|
*
|
|
* @param int|null $hour The hour to create an instance with.
|
|
* @param int|null $minute The minute to create an instance with.
|
|
* @param int|null $second The second to create an instance with.
|
|
* @param \DateTimeZone|string|null $tz The DateTimeZone object or timezone name the new instance should use.
|
|
* @return static
|
|
*/
|
|
public static function createFromTime($hour = null, $minute = null, $second = null, $tz = null)
|
|
{
|
|
return static::create(null, null, null, $hour, $minute, $second, $tz);
|
|
}
|
|
|
|
/**
|
|
* Create a ChronosInterface instance from a specific format
|
|
*
|
|
* @param string $format The date() compatible format string.
|
|
* @param string $time The formatted date string to interpret.
|
|
* @param \DateTimeZone|string|null $tz The DateTimeZone object or timezone name the new instance should use.
|
|
* @return static
|
|
* @throws \InvalidArgumentException
|
|
*/
|
|
public static function createFromFormat($format, $time, $tz = null)
|
|
{
|
|
if ($tz !== null) {
|
|
$dt = parent::createFromFormat($format, $time, static::safeCreateDateTimeZone($tz));
|
|
} else {
|
|
$dt = parent::createFromFormat($format, $time);
|
|
}
|
|
|
|
$errors = parent::getLastErrors();
|
|
if ($dt == false) {
|
|
throw new InvalidArgumentException(implode(PHP_EOL, $errors['errors']));
|
|
}
|
|
|
|
$dt = static::instance($dt);
|
|
static::$_lastErrors = $errors;
|
|
|
|
return $dt;
|
|
}
|
|
|
|
/**
|
|
* Creates a ChronosInterface instance from an array of date and time values.
|
|
*
|
|
* The 'year', 'month' and 'day' values must all be set for a date. The time
|
|
* values all default to 0.
|
|
*
|
|
* The 'timezone' value can be any format supported by `\DateTimeZone`.
|
|
*
|
|
* Allowed values:
|
|
* - year
|
|
* - month
|
|
* - day
|
|
* - hour
|
|
* - minute
|
|
* - second
|
|
* - microsecond
|
|
* - meridian ('am' or 'pm')
|
|
* - timezone
|
|
*
|
|
* @param (int|string)[] $values Array of date and time values.
|
|
* @return static
|
|
*/
|
|
public static function createFromArray($values)
|
|
{
|
|
$values += ['hour' => 0, 'minute' => 0, 'second' => 0, 'microsecond' => 0, 'timezone' => null];
|
|
|
|
$formatted = '';
|
|
if (
|
|
isset($values['year'], $values['month'], $values['day']) &&
|
|
(
|
|
is_numeric($values['year']) &&
|
|
is_numeric($values['month']) &&
|
|
is_numeric($values['day'])
|
|
)
|
|
) {
|
|
$formatted .= sprintf('%04d-%02d-%02d ', $values['year'], $values['month'], $values['day']);
|
|
}
|
|
|
|
if (isset($values['meridian']) && (int)$values['hour'] === 12) {
|
|
$values['hour'] = 0;
|
|
}
|
|
if (isset($values['meridian'])) {
|
|
$values['hour'] = strtolower($values['meridian']) === 'am' ? $values['hour'] : $values['hour'] + 12;
|
|
}
|
|
$formatted .= sprintf(
|
|
'%02d:%02d:%02d.%06d',
|
|
$values['hour'],
|
|
$values['minute'],
|
|
$values['second'],
|
|
$values['microsecond']
|
|
);
|
|
|
|
return static::parse($formatted, $values['timezone']);
|
|
}
|
|
|
|
/**
|
|
* Create a ChronosInterface instance from a timestamp
|
|
*
|
|
* @param int $timestamp The timestamp to create an instance from.
|
|
* @param \DateTimeZone|string|null $tz The DateTimeZone object or timezone name the new instance should use.
|
|
* @return static
|
|
*/
|
|
public static function createFromTimestamp($timestamp, $tz = null)
|
|
{
|
|
return static::now($tz)->setTimestamp($timestamp);
|
|
}
|
|
|
|
/**
|
|
* Create a ChronosInterface instance from an UTC timestamp
|
|
*
|
|
* @param int $timestamp The UTC timestamp to create an instance from.
|
|
* @return static
|
|
*/
|
|
public static function createFromTimestampUTC($timestamp)
|
|
{
|
|
return new static('@' . $timestamp);
|
|
}
|
|
|
|
/**
|
|
* Creates a DateTimeZone from a string or a DateTimeZone
|
|
*
|
|
* @param \DateTimeZone|string|null $object The value to convert.
|
|
* @return \DateTimeZone
|
|
* @throws \InvalidArgumentException
|
|
*/
|
|
protected static function safeCreateDateTimeZone($object)
|
|
{
|
|
if ($object === null) {
|
|
return new DateTimeZone(date_default_timezone_get());
|
|
}
|
|
|
|
if ($object instanceof DateTimeZone) {
|
|
return $object;
|
|
}
|
|
|
|
return new DateTimeZone($object);
|
|
}
|
|
|
|
/**
|
|
* Returns any errors or warnings that were found during the parsing
|
|
* of the last object created by this class.
|
|
*
|
|
* @return array
|
|
*/
|
|
public static function getLastErrors()
|
|
{
|
|
if (empty(static::$_lastErrors)) {
|
|
return parent::getLastErrors();
|
|
}
|
|
|
|
return static::$_lastErrors;
|
|
}
|
|
}
|