Removed dodgy DateTimeInterface wrappers, use Carbon or the XDateTime utils instead.
This commit is contained in:
parent
81d0baedce
commit
d3c7b8f496
19 changed files with 255 additions and 1849 deletions
2
TODO.md
2
TODO.md
|
@ -13,8 +13,6 @@
|
|||
|
||||
- Add RSS/Atom feed construction utilities.
|
||||
|
||||
- Verify structure of the DateTime types.
|
||||
|
||||
## Low Prio
|
||||
|
||||
- Get guides working on phpdoc.
|
||||
|
|
2
VERSION
2
VERSION
|
@ -1 +1 @@
|
|||
0.2407.311946
|
||||
0.2407.312052
|
||||
|
|
|
@ -1,14 +1,15 @@
|
|||
<?php
|
||||
// DbMigrationManager.php
|
||||
// Created: 2023-01-07
|
||||
// Updated: 2023-01-07
|
||||
// Updated: 2024-07-31
|
||||
|
||||
namespace Index\Data\Migration;
|
||||
|
||||
use stdClass;
|
||||
use InvalidArgumentException;
|
||||
use DateTimeImmutable;
|
||||
use DateTimeInterface;
|
||||
use Index\DateTime;
|
||||
use Index\XDateTime;
|
||||
use Index\Data\IDbConnection;
|
||||
use Index\Data\IDbStatement;
|
||||
use Index\Data\DbType;
|
||||
|
@ -76,7 +77,8 @@ EOF;
|
|||
}
|
||||
|
||||
public function completeMigration(string $name, ?DateTimeInterface $dateTime = null): void {
|
||||
$dateTime = ($dateTime ?? DateTime::utcNow())->format(DateTimeInterface::ATOM);
|
||||
$dateTime = XDateTime::toISO8601String($dateTime);
|
||||
|
||||
$this->insertStmt->reset();
|
||||
$this->insertStmt->addParameter(1, $name, DbType::STRING);
|
||||
$this->insertStmt->addParameter(2, $dateTime, DbType::STRING);
|
||||
|
@ -88,8 +90,6 @@ EOF;
|
|||
}
|
||||
|
||||
public function createFileName(string $name, ?DateTimeInterface $dateTime = null): string {
|
||||
$dateTime ??= DateTime::utcNow();
|
||||
|
||||
if(empty($name))
|
||||
throw new InvalidArgumentException('$name may not be empty.');
|
||||
|
||||
|
@ -97,12 +97,12 @@ EOF;
|
|||
if(!preg_match('#^([a-z_]+)$#', $name))
|
||||
throw new InvalidArgumentException('$name may only contain alphabetical, spaces and _ characters.');
|
||||
|
||||
$dateTime ??= new DateTimeImmutable('now');
|
||||
|
||||
return $dateTime->format('Y_m_d_His_') . trim($name, '_');
|
||||
}
|
||||
|
||||
public function createClassName(string $name, ?DateTimeInterface $dateTime = null): string {
|
||||
$dateTime ??= DateTime::utcNow();
|
||||
|
||||
if(empty($name))
|
||||
throw new InvalidArgumentException('$name may not be empty.');
|
||||
|
||||
|
@ -110,6 +110,8 @@ EOF;
|
|||
if(!preg_match('#^([a-z_]+)$#', $name))
|
||||
throw new InvalidArgumentException('$name may only contain alphabetical, spaces and _ characters.');
|
||||
|
||||
$dateTime ??= new DateTimeImmutable('now');
|
||||
|
||||
$parts = explode('_', trim($name, '_'));
|
||||
$name = '';
|
||||
|
||||
|
@ -120,7 +122,7 @@ EOF;
|
|||
}
|
||||
|
||||
public function createNames(string $baseName, ?DateTimeInterface $dateTime = null): object {
|
||||
$dateTime ??= DateTime::utcNow();
|
||||
$dateTime ??= new DateTimeImmutable('now');
|
||||
|
||||
$names = new stdClass;
|
||||
$names->name = $this->createFileName($baseName, $dateTime);
|
||||
|
|
|
@ -1,11 +1,10 @@
|
|||
<?php
|
||||
// FsDbMigrationInfo.php
|
||||
// Created: 2023-01-07
|
||||
// Updated: 2023-01-07
|
||||
// Updated: 2024-07-31
|
||||
|
||||
namespace Index\Data\Migration;
|
||||
|
||||
use DateTime;
|
||||
use Index\Data\IDbConnection;
|
||||
|
||||
class FsDbMigrationInfo implements IDbMigrationInfo {
|
||||
|
|
659
src/DateTime.php
659
src/DateTime.php
|
@ -1,659 +0,0 @@
|
|||
<?php
|
||||
// DateTime.php
|
||||
// Created: 2021-06-11
|
||||
// Updated: 2024-01-04
|
||||
|
||||
namespace Index;
|
||||
|
||||
use DateInterval;
|
||||
use DateTimeImmutable;
|
||||
use DateTimeInterface;
|
||||
use DateTimeZone;
|
||||
use InvalidArgumentException;
|
||||
use JsonSerializable;
|
||||
use RuntimeException;
|
||||
use Stringable;
|
||||
|
||||
/**
|
||||
* Represents a date and time
|
||||
*/
|
||||
class DateTime extends DateTimeImmutable implements JsonSerializable, Stringable, IComparable, IEquatable {
|
||||
/**
|
||||
* Represents Sunday for getDayOfWeek.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
public const SUNDAY = 0;
|
||||
|
||||
/**
|
||||
* Represents Monday for getDayOfWeek.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
public const MONDAY = 1;
|
||||
|
||||
/**
|
||||
* Represents Tuesday for getDayOfWeek.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
public const TUESDAY = 2;
|
||||
|
||||
/**
|
||||
* Represents Wednesday for getDayOfWeek.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
public const WEDNESDAY = 3;
|
||||
|
||||
/**
|
||||
* Represents Thursday for getDayOfWeek.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
public const THURSDAY = 4;
|
||||
|
||||
/**
|
||||
* Represents Friday for getDayOfWeek.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
public const FRIDAY = 5;
|
||||
|
||||
/**
|
||||
* Represents Saturday for getDayOfWeek.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
public const SATURDAY = 6;
|
||||
|
||||
private const COMPARE = 'YmdHisu';
|
||||
|
||||
/**
|
||||
* Creates a new DateTime object.
|
||||
*
|
||||
* @see https://www.php.net/manual/en/datetime.formats.php
|
||||
* @param string $dateTime A date/time string.
|
||||
* @param DateTimeZone|null $timeZone An object representing the desired time zone.
|
||||
* @return DateTime A new DateTime instance.
|
||||
*/
|
||||
public function __construct(string $dateTime = 'now', DateTimeZone|null $timeZone = null) {
|
||||
parent::__construct($dateTime, $timeZone);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the date component of this instance.
|
||||
*
|
||||
* @return DateTime New instance with the same date but the time set to 00:00:00.
|
||||
*/
|
||||
public function getDate(): DateTime {
|
||||
return self::create($this->getYear(), $this->getMonth(), $this->getDay(), 0, 0, 0, 0, $this->getTimezone());
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the year component of this instance.
|
||||
*
|
||||
* @return int Year component.
|
||||
*/
|
||||
public function getYear(): int {
|
||||
return (int)$this->format('Y');
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the month component of this instance.
|
||||
*
|
||||
* @return int Month component, ranging from 1 to 12.
|
||||
*/
|
||||
public function getMonth(): int {
|
||||
return (int)$this->format('n');
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the day component of this instance.
|
||||
*
|
||||
* @return int Day component, ranging from 1 to 31.
|
||||
*/
|
||||
public function getDay(): int {
|
||||
return (int)$this->format('j');
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the day of the week represented by this instance.
|
||||
*
|
||||
* See the SUNDAY, MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY and SATURDAY constants for the possible return values of this function.
|
||||
*
|
||||
* @return int Integer between 0 and 6 representing the day of the week.
|
||||
*/
|
||||
public function getDayOfWeek(): int {
|
||||
return (int)$this->format('w');
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the day of the year represented by this instance.
|
||||
*
|
||||
* @return int Day of the year, ranging from 1-366.
|
||||
*/
|
||||
public function getDayOfYear(): int {
|
||||
return ((int)$this->format('z')) + 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the ISO8601 week number of this instance.
|
||||
*
|
||||
* @return int Integer representing the current week number.
|
||||
*/
|
||||
public function getWeek(): int {
|
||||
return (int)$this->format('W');
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the time of day for this instance.
|
||||
*
|
||||
* @return TimeSpan A TimeSpan representing the amount of time elapsed since midnight.
|
||||
*/
|
||||
public function getTimeOfDay(): TimeSpan {
|
||||
return TimeSpan::create(0, $this->getHour(), $this->getMinute(), $this->getSecond(), $this->getMicrosecond());
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the hour component of this instance.
|
||||
*
|
||||
* @return int Hour component, ranging from 0 to 23.
|
||||
*/
|
||||
public function getHour(): int {
|
||||
return (int)$this->format('G');
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the minute component of this instance.
|
||||
*
|
||||
* @return int Minute component, ranging from 0 to 59.
|
||||
*/
|
||||
public function getMinute(): int {
|
||||
return (int)$this->format('i');
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the second component of this instance.
|
||||
*
|
||||
* @return int Second component, ranging from 0 to 59.
|
||||
*/
|
||||
public function getSecond(): int {
|
||||
return (int)$this->format('s');
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the millisecond component of this instance.
|
||||
*
|
||||
* @return int Millisecond component, ranging from 0 to 999.
|
||||
*/
|
||||
public function getMillisecond(): int {
|
||||
return (int)$this->format('v');
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the microsecond component of this instance.
|
||||
*
|
||||
* @return int Microsecond component, ranging from 0 to 999999.
|
||||
*/
|
||||
public function getMicrosecond(): int {
|
||||
return (int)$this->format('u');
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the number of seconds that have elapsed since midnight January 1st, 1970 UTC for this instance.
|
||||
*
|
||||
* @return int Number of seconds.
|
||||
*/
|
||||
public function getUnixTimeSeconds(): int {
|
||||
return (int)$this->format('U');
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the number of milliseconds that have elapsed since midnight January 1st, 1970 UTC for this instance.
|
||||
*
|
||||
* @return float Number of milliseconds.
|
||||
*/
|
||||
public function getUnixTimeMilliseconds(): float {
|
||||
return (float)$this->format('Uv');
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets whether Daylight Savings is in effect during the time this instance represents.
|
||||
*
|
||||
* @return bool true if DST is in effect, false if not.
|
||||
*/
|
||||
public function isDaylightSavingTime(): bool {
|
||||
return $this->format('I') !== '0';
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets whether the year this instance represents is a leap year.
|
||||
*
|
||||
* @return bool true if the year is a leap year, false if not.
|
||||
*/
|
||||
public function isLeapYear(): bool {
|
||||
return $this->format('L') !== '0';
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets whether this DateTime uses UTC date/time.
|
||||
*
|
||||
* @return bool true if UTC, false if not.
|
||||
*/
|
||||
public function isUTC(): bool {
|
||||
return $this->getTimezone()->equals(TimeZoneInfo::utc());
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the time zone for this instance.
|
||||
*
|
||||
* @return TimeZoneInfo Time zone for this instance.
|
||||
*/
|
||||
public function getTimezone(): TimeZoneInfo {
|
||||
return TimeZoneInfo::cast(parent::getTimezone());
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a period of time to this date time object.
|
||||
*
|
||||
* @param DateInterval $timeSpan Time period to add to this DateTime.
|
||||
* @return DateTime A DateTime instance which is the sum of this instance and the provided period.
|
||||
*/
|
||||
public function add(DateInterval $timeSpan): DateTime {
|
||||
return self::cast(parent::add($timeSpan));
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a number of years to this instance.
|
||||
*
|
||||
* @param float $years Number of years to add.
|
||||
* @return DateTime New DateTime instance with the years added.
|
||||
*/
|
||||
public function addYears(float $years): DateTime {
|
||||
return $this->add(TimeSpan::fromDays(365 * $years));
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a number of months to this instance.
|
||||
*
|
||||
* @param float $months Number of months to add.
|
||||
* @return DateTime New DateTime instance with the months added.
|
||||
*/
|
||||
public function addMonths(float $months): DateTime {
|
||||
return $this->add(TimeSpan::fromDays(365 * 31 * $months));
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a number of days to this instance.
|
||||
*
|
||||
* @param float $days Number of days to add.
|
||||
* @return DateTime New DateTime instance with the days added.
|
||||
*/
|
||||
public function addDays(float $days): DateTime {
|
||||
return $this->add(TimeSpan::fromDays($days));
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a number of hours to this instance.
|
||||
*
|
||||
* @param float $hours Number of hours to add.
|
||||
* @return DateTime New DateTime instance with the hours added.
|
||||
*/
|
||||
public function addHours(float $hours): DateTime {
|
||||
return $this->add(TimeSpan::fromHours($hours));
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a number of minutes to this instance.
|
||||
*
|
||||
* @param float $minutes Number of minutes to add.
|
||||
* @return DateTime New DateTime instance with the minutes added.
|
||||
*/
|
||||
public function addMinutes(float $minutes): DateTime {
|
||||
return $this->add(TimeSpan::fromMinutes($minutes));
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a number of seconds to this instance.
|
||||
*
|
||||
* @param float $seconds Number of seconds to add.
|
||||
* @return DateTime New DateTime instance with the seconds added.
|
||||
*/
|
||||
public function addSeconds(float $seconds): DateTime {
|
||||
return $this->add(TimeSpan::fromSeconds($seconds));
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a number of milliseconds to this instance.
|
||||
*
|
||||
* @param float $millis Number of milliseconds to add.
|
||||
* @return DateTime New DateTime instance with the milliseconds added.
|
||||
*/
|
||||
public function addMilliseconds(float $millis): DateTime {
|
||||
return $this->add(TimeSpan::fromMilliseconds($millis));
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a number of microseconds to this instance.
|
||||
*
|
||||
* @param float $micros Number of microseconds to add.
|
||||
* @return DateTime New DateTime instance with the microseconds added.
|
||||
*/
|
||||
public function addMicroseconds(float $micros): DateTime {
|
||||
return $this->add(TimeSpan::fromMicroseconds($micros));
|
||||
}
|
||||
|
||||
/**
|
||||
* Subtracts a time period from this DateTime.
|
||||
*
|
||||
* @param DateInterval $timeSpan Time period to be subtracted.
|
||||
* @return DateTime A new DateTime instance which is this instance minus the given time period.
|
||||
*/
|
||||
public function subtract(DateInterval $timeSpan): DateTime {
|
||||
return self::cast(parent::sub($timeSpan));
|
||||
}
|
||||
|
||||
/**
|
||||
* Alias for difference, must exist because of the DateTimeImmutable inheritance but I don't like short names.
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
public function diff(DateTimeInterface $dateTime, bool $absolute = false): TimeSpan {
|
||||
return $this->difference($dateTime, $absolute);
|
||||
}
|
||||
|
||||
/**
|
||||
* Subtracts another Date/Time from this DateTime.
|
||||
*
|
||||
* @param DateTimeInterface $dateTime Date/time to subtract.
|
||||
* @return TimeSpan Difference between this DateTime and the provided one.
|
||||
*/
|
||||
public function difference(DateTimeInterface $dateTime, bool $absolute = false): TimeSpan {
|
||||
return TimeSpan::cast(parent::diff($dateTime, $absolute));
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies a modifier on this instance and returns the result as a new instance.
|
||||
*
|
||||
* @see https://www.php.net/manual/en/datetime.formats.php
|
||||
* @param string $modifier A date/time format.
|
||||
* @return DateTime The modified date/time.
|
||||
*/
|
||||
public function modify(string $modifier): DateTime {
|
||||
return self::cast(parent::modify($modifier));
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new DateTime with the given date component.
|
||||
*
|
||||
* @param int $year Desired year component.
|
||||
* @param int $month Desired month component.
|
||||
* @param int $day Desired day component.
|
||||
* @return DateTime A new DateTime instance with the given date component.
|
||||
*/
|
||||
public function setDate(int $year, int $month, int $day): DateTime {
|
||||
return self::cast(parent::setDate($year, $month, $day));
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new DateTime with the given ISO date for the date component.
|
||||
*
|
||||
* @param int $year Year of the date.
|
||||
* @param int $week Week of the date.
|
||||
* @param int $dayOfWeek Offset from the first of the week.
|
||||
* @return DateTime A new DateTime instance with the given date component.
|
||||
*/
|
||||
public function setISODate(int $year, int $week, int $dayOfWeek = 1): DateTime {
|
||||
return self::cast(parent::setISODate($year, $week, $dayOfWeek));
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new DateTime with the given time component.
|
||||
*
|
||||
* @param int $hour Desired hour component.
|
||||
* @param int $minute Desired minute component.
|
||||
* @param int $second Desired second component.
|
||||
* @param int $microsecond Desired microsecond component.
|
||||
* @return DateTime A new DateTime instance with the given time component.
|
||||
*/
|
||||
public function setTime(int $hour, int $minute, int $second = 0, int $microsecond = 0): DateTime {
|
||||
return self::cast(parent::setTime($hour, $minute, $second, $microsecond));
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new DateTime with the date and time components based on a Unix timestamp.
|
||||
*
|
||||
* @param int $timestamp Unix timestamp representing the date.
|
||||
* @return DateTime A new DateTime instance with the given date and time.
|
||||
*/
|
||||
public function setTimestamp(int $timestamp): DateTime {
|
||||
return self::cast(parent::setTimestamp($timestamp));
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new DateTime with the given time zone.
|
||||
*
|
||||
* @param DateTimeZone $timeZone An object representing the desired time zone.
|
||||
* @return DateTime A new DateTime with the given time zone.
|
||||
*/
|
||||
public function setTimezone(DateTimeZone $timeZone): DateTime {
|
||||
return self::cast(parent::setTimezone($timeZone));
|
||||
}
|
||||
|
||||
public function compare(mixed $other): int {
|
||||
if($other instanceof DateTimeInterface)
|
||||
return strcmp($this->format(self::COMPARE), $other->format(self::COMPARE));
|
||||
return -1;
|
||||
}
|
||||
|
||||
public function equals(mixed $other): bool {
|
||||
if($other instanceof DateTimeInterface)
|
||||
return $this->format(self::COMPARE) === $other->format(self::COMPARE);
|
||||
return false;
|
||||
}
|
||||
|
||||
public function isLessThan(DateTimeInterface $other): bool {
|
||||
return $this->compare($other) < 0;
|
||||
}
|
||||
|
||||
public function isLessThanOrEqual(DateTimeInterface $other): bool {
|
||||
return $this->compare($other) <= 0;
|
||||
}
|
||||
|
||||
public function isMoreThan(DateTimeInterface $other): bool {
|
||||
return $this->compare($other) > 0;
|
||||
}
|
||||
|
||||
public function isMoreThanOrEqual(DateTimeInterface $other): bool {
|
||||
return $this->compare($other) >= 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Formats this DateTime as an ISO8601 date/time string.
|
||||
*
|
||||
* @return string This object represented as an ISO8601 date/time string.
|
||||
*/
|
||||
public function toISO8601String(): string {
|
||||
return $this->format(DateTimeInterface::ATOM);
|
||||
}
|
||||
|
||||
/**
|
||||
* Formats this DateTime as a Cookie date/time string.
|
||||
*
|
||||
* @return string This object represented as a Cookie date/time string.
|
||||
*/
|
||||
public function toCookieString(): string {
|
||||
return $this->format(DateTimeInterface::COOKIE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Formats this DateTime as an RFC 822 date/time string.
|
||||
*
|
||||
* @return string This object represented as an RFC 822 date/time string.
|
||||
*/
|
||||
public function toRFC822String(): string {
|
||||
return $this->format(DateTimeInterface::RFC822);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a string representation of this object.
|
||||
*
|
||||
* @return string Representation of this object.
|
||||
*/
|
||||
public function __toString(): string {
|
||||
return $this->format(DateTimeInterface::ATOM);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the data which should be serialized as json.
|
||||
*
|
||||
* @see https://www.php.net/manual/en/jsonserializable.jsonserialize.php
|
||||
* @return mixed Data to be passed to json_encode.
|
||||
*/
|
||||
public function jsonSerialize(): mixed {
|
||||
return (string)$this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts this immutable \Index\DateTime type to a mutable \DateTime type.
|
||||
*
|
||||
* @return \DateTime A new mutable \DateTime instance.
|
||||
*/
|
||||
public function toNative(): \DateTime {
|
||||
return \DateTime::createFromImmutable($this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a DateTime object that is set to the current date and time, expressed in the provided time zone.
|
||||
*
|
||||
* @param DateTimeZone $timeZone Desired time zone, null for the current default time zone.
|
||||
* @return DateTime An instance representing now.
|
||||
*/
|
||||
public static function now(?DateTimeZone $timeZone = null): DateTime {
|
||||
return new DateTime('now', $timeZone);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a DateTime object that is set to the current date and time, expressed in UTC.
|
||||
*
|
||||
* @return DateTime An instance representing now in UTC.
|
||||
*/
|
||||
public static function utcNow(): DateTime {
|
||||
return self::now(TimeZoneInfo::utc());
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts Unix time seconds to a DateTime object.
|
||||
*
|
||||
* @param int $seconds Unix time seconds.
|
||||
* @return DateTime A DateTime instance representing the Unix time.
|
||||
*/
|
||||
public static function fromUnixTimeSeconds(int $seconds): DateTime {
|
||||
return new DateTime('@' . $seconds);
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts Unix time milliseconds to a DateTime object.
|
||||
*
|
||||
* @param float $millis Unix time milliseconds.
|
||||
* @return DateTime A DateTime instance representing the Unix time.
|
||||
*/
|
||||
public static function fromUnixTimeMilliseconds(float $millis): DateTime {
|
||||
return new DateTime('@' . ($millis / 1000));
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new DateTime instance with the given components.
|
||||
*
|
||||
* @param int $year Desired year component.
|
||||
* @param int $month Desired month component.
|
||||
* @param int $day Desired day component.
|
||||
* @param int $hour Desired hour component.
|
||||
* @param int $minute Desired minute component.
|
||||
* @param int $second Desired second component.
|
||||
* @param int $micros Desired microsecond component.
|
||||
* @param ?DateTimeZone $timeZone Desired time zone.
|
||||
*/
|
||||
public static function create(int $year, int $month = 1, int $day = 1, int $hour = 0, int $minute = 0, int $second = 0, int $micros = 0, ?DateTimeZone $timeZone = null): DateTime {
|
||||
if($year < 1 || $year > 9999)
|
||||
throw new InvalidArgumentException('$year may not be less than 1 or more than 9999.');
|
||||
if($month < 1 || $month > 12)
|
||||
throw new InvalidArgumentException('$month may not be less than 1 or more than 12.');
|
||||
if($day < 1 || $day > 31)
|
||||
throw new InvalidArgumentException('$day may not be less than 1 or more than 31.');
|
||||
if($hour < 0 || $hour > 23)
|
||||
throw new InvalidArgumentException('$hour may not be less than 0 or more than 23.');
|
||||
if($minute < 0 || $minute > 59)
|
||||
throw new InvalidArgumentException('$minute may not be less than 0 or more than 59.');
|
||||
if($second < 0 || $second > 59)
|
||||
throw new InvalidArgumentException('$second may not be less than 0 or more than 59.');
|
||||
if($micros < 0 || $micros > 999999)
|
||||
throw new InvalidArgumentException('$micros may not be less than 0 or more than 999999.');
|
||||
|
||||
return new DateTime(
|
||||
sprintf(
|
||||
'%04d-%02d-%02dT%02d:%02d:%02d.%06d',
|
||||
$year, $month, $day, $hour, $minute, $second, $micros
|
||||
),
|
||||
$timeZone
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses a time string and creates a DateTime using it.
|
||||
*
|
||||
* @see https://www.php.net/manual/en/datetime.createfromformat
|
||||
* @param string $format Format that the passed string should be in.
|
||||
* @param string $dateTime String representing the time.
|
||||
* @param ?DateTimeZone $timeZone Desired time zone.
|
||||
* @return DateTime|false A DateTime instance, or false on failure.
|
||||
*/
|
||||
public static function createFromFormat(string $format, string $dateTime, ?DateTimeZone $timeZone = null): DateTime|false {
|
||||
$instance = parent::createFromFormat($format, $dateTime, $timeZone);
|
||||
if($instance === false)
|
||||
return false;
|
||||
return self::cast($instance);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new DateTime instance from an interface implementation.
|
||||
*
|
||||
* @param DateTimeInterface $object Object that should be sourced.
|
||||
* @return DateTime A new DateTime instance.
|
||||
*/
|
||||
public static function createFromInterface(DateTimeInterface $object): DateTime {
|
||||
return self::cast($object);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new immutable DateTime instance from a mutable instance.
|
||||
*
|
||||
* @param \DateTime $object Mutable object that should be sourced.
|
||||
* @return DateTime New immutable DateTime representing the same value.
|
||||
*/
|
||||
#[\ReturnTypeWillChange]
|
||||
public static function createFromMutable(\DateTime $object): DateTime {
|
||||
return self::cast($object);
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
public static function __set_state(array $array): DateTime {
|
||||
return self::cast(parent::__set_state($array));
|
||||
}
|
||||
|
||||
/**
|
||||
* Makes sure a DateTimeInterface implementing object is a DateTime instance.
|
||||
*
|
||||
* @param DateTimeInterface $dateTime Input object.
|
||||
* @return DateTime If the input was a DateTime, the same instance will be returned.
|
||||
* If the input was something else, a new DateTime instance will be returned based on the input.
|
||||
*/
|
||||
public static function cast(DateTimeInterface $dateTime): DateTime {
|
||||
if($dateTime instanceof DateTime)
|
||||
return $dateTime;
|
||||
return new DateTime($dateTime->format('@U.u'), $dateTime->getTimezone());
|
||||
}
|
||||
}
|
|
@ -1,25 +1,31 @@
|
|||
<?php
|
||||
// DateHeader.php
|
||||
// Created: 2022-02-14
|
||||
// Updated: 2022-02-14
|
||||
// Updated: 2024-07-31
|
||||
|
||||
namespace Index\Http\Headers;
|
||||
|
||||
use Index\DateTime;
|
||||
use DateTimeImmutable;
|
||||
use DateTimeInterface;
|
||||
use RuntimeException;
|
||||
use Index\Http\HttpHeader;
|
||||
|
||||
class DateHeader {
|
||||
private DateTime $dateTime;
|
||||
private DateTimeImmutable $dateTime;
|
||||
|
||||
public function __construct(DateTime $dateTime) {
|
||||
public function __construct(DateTimeImmutable $dateTime) {
|
||||
$this->dateTime = $dateTime;
|
||||
}
|
||||
|
||||
public function getDateTime(): DateTime {
|
||||
public function getDateTime(): DateTimeImmutable {
|
||||
return $this->dateTime;
|
||||
}
|
||||
|
||||
public static function parse(HttpHeader $header): DateHeader {
|
||||
return new DateHeader(DateTime::createFromFormat(\DateTimeInterface::RFC7231, $header->getFirstLine()));
|
||||
$parsed = DateTimeImmutable::createFromFormat(DateTimeInterface::RFC7231, $header->getFirstLine());
|
||||
if($parsed === false)
|
||||
throw new RuntimeException('Failed to parse Date header.');
|
||||
|
||||
return new DateHeader($parsed);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,30 +1,36 @@
|
|||
<?php
|
||||
// IfModifiedSinceHeader.php
|
||||
// Created: 2022-02-14
|
||||
// Updated: 2022-02-14
|
||||
// Updated: 2024-07-31
|
||||
|
||||
namespace Index\Http\Headers;
|
||||
|
||||
use DateTimeImmutable;
|
||||
use DateTimeInterface;
|
||||
use Index\DateTime;
|
||||
use RuntimeException;
|
||||
use Index\XDateTime;
|
||||
use Index\Http\HttpHeader;
|
||||
|
||||
class IfModifiedSinceHeader {
|
||||
private DateTime $dateTime;
|
||||
private DateTimeImmutable $dateTime;
|
||||
|
||||
public function __construct(DateTime $dateTime) {
|
||||
public function __construct(DateTimeImmutable $dateTime) {
|
||||
$this->dateTime = $dateTime;
|
||||
}
|
||||
|
||||
public function getDateTime(): DateTime {
|
||||
public function getDateTime(): DateTimeImmutable {
|
||||
return $this->dateTime;
|
||||
}
|
||||
|
||||
public function isLessThanOrEqual(DateTimeInterface $dateTime): bool {
|
||||
return $this->dateTime->isLessThanOrEqual($dateTime);
|
||||
public function isLessThanOrEqual(DateTimeInterface $other): bool {
|
||||
return XDateTime::compare($this->dateTime, $other) <= 0;
|
||||
}
|
||||
|
||||
public static function parse(HttpHeader $header): IfModifiedSinceHeader {
|
||||
return new IfModifiedSinceHeader(DateTime::createFromFormat(\DateTimeInterface::RFC7231, $header->getFirstLine()));
|
||||
$parsed = DateTimeImmutable::createFromFormat(DateTimeInterface::RFC7231, $header->getFirstLine());
|
||||
if($parsed === false)
|
||||
throw new RuntimeException('Failed to parse If-Modified-Since header.');
|
||||
|
||||
return new IfModifiedSinceHeader($parsed);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,19 +1,21 @@
|
|||
<?php
|
||||
// IfRangeHeader.php
|
||||
// Created: 2022-02-14
|
||||
// Updated: 2022-02-27
|
||||
// Updated: 2024-07-31
|
||||
|
||||
namespace Index\Http\Headers;
|
||||
|
||||
use DateTimeImmutable;
|
||||
use DateTimeInterface;
|
||||
use Index\DateTime;
|
||||
use RuntimeException;
|
||||
use Index\XDateTime;
|
||||
use Index\Http\HttpHeader;
|
||||
|
||||
class IfRangeHeader {
|
||||
private ?string $tag;
|
||||
private ?DateTime $dateTime;
|
||||
private ?DateTimeImmutable $dateTime;
|
||||
|
||||
public function __construct(?string $tag, ?DateTime $dateTime) {
|
||||
public function __construct(?string $tag, ?DateTimeImmutable $dateTime) {
|
||||
$this->tag = $tag;
|
||||
$this->dateTime = $dateTime;
|
||||
}
|
||||
|
@ -30,7 +32,7 @@ class IfRangeHeader {
|
|||
return $this->dateTime !== null;
|
||||
}
|
||||
|
||||
public function getDateTime(): DateTime {
|
||||
public function getDateTime(): DateTimeImmutable {
|
||||
return $this->dateTime;
|
||||
}
|
||||
|
||||
|
@ -42,7 +44,7 @@ class IfRangeHeader {
|
|||
}
|
||||
|
||||
if($this->hasDateTime() && $other instanceof DateTimeInterface)
|
||||
return $this->dateTime->isLessThanOrEqual($other);
|
||||
return XDateTime::compare($this->dateTime, $other) <= 0;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
@ -50,8 +52,13 @@ class IfRangeHeader {
|
|||
public static function parse(HttpHeader $header): IfRangeHeader {
|
||||
$line = $header->getFirstLine();
|
||||
|
||||
if($line[0] !== '"' && !str_starts_with($line, 'W/"'))
|
||||
return new IfRangeHeader(null, DateTime::createFromFormat(\DateTimeInterface::RFC7231, $line));
|
||||
if($line[0] !== '"' && !str_starts_with($line, 'W/"')) {
|
||||
$parsed = DateTimeImmutable::createFromFormat(DateTimeInterface::RFC7231, $line);
|
||||
if($parsed === false)
|
||||
throw new RuntimeException('Failed to parse If-Range header.');
|
||||
|
||||
return new IfRangeHeader(null, $parsed);
|
||||
}
|
||||
|
||||
return new IfRangeHeader($line, null);
|
||||
}
|
||||
|
|
|
@ -1,30 +1,36 @@
|
|||
<?php
|
||||
// IfUnmodifiedSinceHeader.php
|
||||
// Created: 2022-02-14
|
||||
// Updated: 2022-02-14
|
||||
// Updated: 2024-07-31
|
||||
|
||||
namespace Index\Http\Headers;
|
||||
|
||||
use DateTimeImmutable;
|
||||
use DateTimeInterface;
|
||||
use Index\DateTime;
|
||||
use RuntimeException;
|
||||
use Index\XDateTime;
|
||||
use Index\Http\HttpHeader;
|
||||
|
||||
class IfUnmodifiedSinceHeader {
|
||||
private DateTime $dateTime;
|
||||
private DateTimeImmutable $dateTime;
|
||||
|
||||
public function __construct(DateTime $dateTime) {
|
||||
public function __construct(DateTimeImmutable $dateTime) {
|
||||
$this->dateTime = $dateTime;
|
||||
}
|
||||
|
||||
public function getDateTime(): DateTime {
|
||||
public function getDateTime(): DateTimeImmutable {
|
||||
return $this->dateTime;
|
||||
}
|
||||
|
||||
public function isMoreThan(DateTimeInterface $dateTime): bool {
|
||||
return $this->dateTime->isMoreThan($dateTime);
|
||||
public function isMoreThan(DateTimeInterface $other): bool {
|
||||
return XDateTime::compare($this->dateTime, $other) > 0;
|
||||
}
|
||||
|
||||
public static function parse(HttpHeader $header): IfUnmodifiedSinceHeader {
|
||||
return new IfUnmodifiedSinceHeader(DateTime::createFromFormat(\DateTimeInterface::RFC7231, $header->getFirstLine()));
|
||||
$parsed = DateTimeImmutable::createFromFormat(DateTimeInterface::RFC7231, $header->getFirstLine());
|
||||
if($parsed === false)
|
||||
throw new RuntimeException('Failed to parse If-Unmodified-Since header.');
|
||||
|
||||
return new IfUnmodifiedSinceHeader($parsed);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,25 +1,31 @@
|
|||
<?php
|
||||
// LastModifiedHeader.php
|
||||
// Created: 2022-02-14
|
||||
// Updated: 2022-02-14
|
||||
// Updated: 2024-07-31
|
||||
|
||||
namespace Index\Http\Headers;
|
||||
|
||||
use Index\DateTime;
|
||||
use DateTimeImmutable;
|
||||
use DateTimeInterface;
|
||||
use RuntimeException;
|
||||
use Index\Http\HttpHeader;
|
||||
|
||||
class LastModifiedHeader {
|
||||
private DateTime $dateTime;
|
||||
private DateTimeImmutable $dateTime;
|
||||
|
||||
public function __construct(DateTime $dateTime) {
|
||||
public function __construct(DateTimeImmutable $dateTime) {
|
||||
$this->dateTime = $dateTime;
|
||||
}
|
||||
|
||||
public function getDateTime(): DateTime {
|
||||
public function getDateTime(): DateTimeImmutable {
|
||||
return $this->dateTime;
|
||||
}
|
||||
|
||||
public static function parse(HttpHeader $header): LastModifiedHeader {
|
||||
return new LastModifiedHeader(DateTime::createFromFormat(\DateTimeInterface::RFC7231, $header->getFirstLine()));
|
||||
$parsed = DateTimeImmutable::createFromFormat(DateTimeInterface::RFC7231, $header->getFirstLine());
|
||||
if($parsed === false)
|
||||
throw new RuntimeException('Failed to parse Last-Modified header.');
|
||||
|
||||
return new LastModifiedHeader($parsed);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,11 +1,10 @@
|
|||
<?php
|
||||
// OriginHeader.php
|
||||
// Created: 2022-02-14
|
||||
// Updated: 2022-02-27
|
||||
// Updated: 2024-07-31
|
||||
|
||||
namespace Index\Http\Headers;
|
||||
|
||||
use Index\DateTime;
|
||||
use Index\Http\HttpHeader;
|
||||
|
||||
class OriginHeader {
|
||||
|
|
|
@ -1,14 +1,14 @@
|
|||
<?php
|
||||
// HttpResponseBuilder.php
|
||||
// Created: 2022-02-08
|
||||
// Updated: 2023-01-10
|
||||
// Updated: 2024-07-31
|
||||
|
||||
namespace Index\Http;
|
||||
|
||||
use DateTimeInterface;
|
||||
use Index\DateTime;
|
||||
use Index\UrlEncoding;
|
||||
use Index\MediaType;
|
||||
use Index\XDateTime;
|
||||
use Index\Performance\Timings;
|
||||
|
||||
class HttpResponseBuilder extends HttpMessageBuilder {
|
||||
|
@ -53,16 +53,8 @@ class HttpResponseBuilder extends HttpMessageBuilder {
|
|||
$cookie = rawurlencode($name) . '=' . rawurlencode($value)
|
||||
. '; SameSite=' . ($sameSiteStrict ? 'Strict' : 'Lax');
|
||||
|
||||
if($expires !== null) {
|
||||
if(!($expires instanceof DateTime)) {
|
||||
if(is_int($expires))
|
||||
$expires = DateTime::fromUnixTimeSeconds($expires);
|
||||
else
|
||||
$expires = DateTime::createFromInterface($expires);
|
||||
}
|
||||
|
||||
$cookie .= '; Expires=' . $expires->toCookieString();
|
||||
}
|
||||
if($expires !== null)
|
||||
$cookie .= '; Expires=' . XDateTime::toCookieString($expires);
|
||||
|
||||
if(!empty($domain))
|
||||
$cookie .= '; Domain=' . $domain;
|
||||
|
|
526
src/TimeSpan.php
526
src/TimeSpan.php
|
@ -1,526 +0,0 @@
|
|||
<?php
|
||||
// TimeSpan.php
|
||||
// Created: 2021-06-11
|
||||
// Updated: 2022-02-27
|
||||
|
||||
namespace Index;
|
||||
|
||||
use DateInterval;
|
||||
use JsonSerializable;
|
||||
use Stringable;
|
||||
|
||||
/**
|
||||
* Represents a duration of time.
|
||||
*/
|
||||
class TimeSpan extends DateInterval implements JsonSerializable, Stringable, IComparable, IEquatable {
|
||||
private const HOURS_IN_DAY = 24;
|
||||
private const MINS_IN_HOUR = 60;
|
||||
private const SECS_IN_MIN = 60;
|
||||
private const MILLIS_IN_SEC = 1000;
|
||||
private const MINS_IN_DAY = 1440;
|
||||
private const SECS_IN_HOUR = 3600;
|
||||
private const MILLIS_IN_MIN = 60000;
|
||||
private const SECS_IN_DAY = 86400;
|
||||
private const MICROS_IN_SEC = 1000000;
|
||||
private const MILLIS_IN_HOUR = 3600000;
|
||||
private const MICROS_IN_MIN = 60000000;
|
||||
private const MILLIS_IN_DAY = 86400000;
|
||||
private const MICROS_IN_HOUR = 3600000000;
|
||||
private const MICROS_IN_DAY = 86400000000;
|
||||
|
||||
private int $realDays = -1;
|
||||
|
||||
/**
|
||||
* Creates a new instance of TimeSpan.
|
||||
*
|
||||
* @param string $duration An ISO8601 duration string.
|
||||
* @return TimeSpan A TimeSpan instance representing the given duration.
|
||||
*/
|
||||
public function __construct(string $duration = 'PT0S') {
|
||||
parent::__construct($duration);
|
||||
$this->realDays = $this->days === false ? $this->calculateRealDays() : $this->days;
|
||||
}
|
||||
|
||||
private function calculateRealDays(): int {
|
||||
return ($this->y * 365)
|
||||
+ ($this->m * 31)
|
||||
+ $this->d;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the amount of days this TimeSpan represents.
|
||||
*
|
||||
* @return int Amount of days.
|
||||
*/
|
||||
public function getDays(): int {
|
||||
return $this->realDays;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the amount of hours this TimeSpan represents.
|
||||
*
|
||||
* @retunr int Amount of hours.
|
||||
*/
|
||||
public function getHours(): int {
|
||||
return $this->h;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the amount of minutes this TimeSpan represents.
|
||||
*
|
||||
* @return int Amount of minutes.
|
||||
*/
|
||||
public function getMinutes(): int {
|
||||
return $this->i;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the amount of seconds this TimeSpan represents.
|
||||
*
|
||||
* @return int Amount of seconds.
|
||||
*/
|
||||
public function getSeconds(): int {
|
||||
return $this->s;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the amount of milliseconds this TimeSpan represents.
|
||||
*
|
||||
* @return int Amount of milliseconds.
|
||||
*/
|
||||
public function getMilliseconds(): int {
|
||||
return (int)($this->f * 1000);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the amount of microseconds this TimeSpan represents.
|
||||
*
|
||||
* @return int Amount of microseconds.
|
||||
*/
|
||||
public function getMicroseconds(): int {
|
||||
return (int)($this->f * 1000000);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets whether this TimeSpan represents a negative amount of time.
|
||||
*
|
||||
* @return bool true if negative, false if positive.
|
||||
*/
|
||||
public function isNegative(): bool {
|
||||
return $this->invert !== 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Counts the total amount of days this TimeSpan contains.
|
||||
*
|
||||
* @return float Total amount of days.
|
||||
*/
|
||||
public function totalDays(): float {
|
||||
$days = $this->getDays();
|
||||
$days += $this->getHours() / self::HOURS_IN_DAY;
|
||||
$days += $this->getMinutes() / self::MINS_IN_DAY;
|
||||
$days += $this->getSeconds() / self::SECS_IN_DAY;
|
||||
$days += $this->getMicroseconds() / self::MICROS_IN_DAY;
|
||||
return $days;
|
||||
}
|
||||
|
||||
/**
|
||||
* Counts the total amount of hours this TimeSpan contains.
|
||||
*
|
||||
* @return float Total amount of hours.
|
||||
*/
|
||||
public function totalHours(): float {
|
||||
$hours = $this->getDays() * self::HOURS_IN_DAY;
|
||||
$hours += $this->getHours();
|
||||
$hours += $this->getMinutes() / self::MINS_IN_HOUR;
|
||||
$hours += $this->getSeconds() / self::SECS_IN_HOUR;
|
||||
$hours += $this->getMicroseconds() / self::MICROS_IN_HOUR;
|
||||
return $hours;
|
||||
}
|
||||
|
||||
/**
|
||||
* Counts the total amount of minutes this TimeSpan contains.
|
||||
*
|
||||
* @return float Total amount of minutes.
|
||||
*/
|
||||
public function totalMinutes(): float {
|
||||
$mins = $this->getDays() * self::MINS_IN_DAY;
|
||||
$mins += $this->getHours() * self::MINS_IN_HOUR;
|
||||
$mins += $this->getMinutes();
|
||||
$mins += $this->getSeconds() / self::SECS_IN_MIN;
|
||||
$mins += $this->getMicroseconds() / self::MICROS_IN_MIN;
|
||||
return $mins;
|
||||
}
|
||||
|
||||
/**
|
||||
* Counts the total amount of seconds this TimeSpan contains.
|
||||
*
|
||||
* @return float Total amount of seconds.
|
||||
*/
|
||||
public function totalSeconds(): float {
|
||||
$secs = $this->getDays() * self::SECS_IN_DAY;
|
||||
$secs += $this->getHours() * self::SECS_IN_HOUR;
|
||||
$secs += $this->getMinutes() * self::SECS_IN_MIN;
|
||||
$secs += $this->getSeconds();
|
||||
$secs += $this->getMicroseconds() * self::MICROS_IN_SEC;
|
||||
return $secs;
|
||||
}
|
||||
|
||||
/**
|
||||
* Counts the total amount of milliseconds this TimeSpan contains.
|
||||
*
|
||||
* @return float Total amount of milliseconds.
|
||||
*/
|
||||
public function totalMilliseconds(): float {
|
||||
$millis = $this->getDays() * self::MILLIS_IN_DAY;
|
||||
$millis += $this->getHours() * self::MILLIS_IN_HOUR;
|
||||
$millis += $this->getMinutes() * self::MILLIS_IN_MIN;
|
||||
$millis += $this->getSeconds() * self::MILLIS_IN_SEC;
|
||||
$millis += $this->getMilliseconds();
|
||||
return $millis;
|
||||
}
|
||||
|
||||
/**
|
||||
* Counts the total amount of microseconds this TimeSpan contains.
|
||||
*
|
||||
* @return float Total amount of microseconds.
|
||||
*/
|
||||
public function totalMicroseconds(): float {
|
||||
$micros = $this->getDays() * self::MICROS_IN_DAY;
|
||||
$micros += $this->getHours() * self::MICROS_IN_HOUR;
|
||||
$micros += $this->getMinutes() * self::MICROS_IN_MIN;
|
||||
$micros += $this->getSeconds() * self::MICROS_IN_SEC;
|
||||
$micros += $this->getMicroseconds();
|
||||
return $micros;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a new TimeSpan whose value is the sum of this instance and the provided instance.
|
||||
*
|
||||
* @param DateInterval $timeSpan Interval to add.
|
||||
* @return TimeSpan Instance that represents this instance plus the value of $timeSpan.
|
||||
*/
|
||||
public function add(DateInterval $timeSpan): TimeSpan {
|
||||
$timeSpan = self::cast($timeSpan);
|
||||
|
||||
$days1 = $this->totalDays();
|
||||
if($this->isNegative())
|
||||
$days1 *= -1;
|
||||
|
||||
$days2 = $timeSpan->totalDays();
|
||||
if($timeSpan->isNegative())
|
||||
$days2 *= -1;
|
||||
|
||||
return self::fromDays($days1 + $days2);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a new TimeSpan whose value is the difference of this instance and the provided instance.
|
||||
*
|
||||
* @param DateInterval $timeSpan Interval to subtract.
|
||||
* @return TimeSpan Instance that represents this instance minus the value of $timeSpan.
|
||||
*/
|
||||
public function subtract(DateInterval $timeSpan): TimeSpan {
|
||||
$timeSpan = self::cast($timeSpan);
|
||||
|
||||
$days1 = $this->totalDays();
|
||||
if($this->isNegative())
|
||||
$days1 *= -1;
|
||||
|
||||
$days2 = $timeSpan->totalDays();
|
||||
if($timeSpan->isNegative())
|
||||
$days2 *= -1;
|
||||
|
||||
return self::fromDays($days1 - $days2);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the result of a division of this instance and the provided instance.
|
||||
*
|
||||
* @param DateInterval $timeSpan Interval to be divided by.
|
||||
* @return float $timeSpan Number that represents this instance divided by the value of $timeSpan.
|
||||
*/
|
||||
public function divideTimeSpan(DateInterval $timeSpan): float {
|
||||
$timeSpan = self::cast($timeSpan);
|
||||
|
||||
$days1 = $this->totalDays();
|
||||
if($this->isNegative())
|
||||
$days1 *= -1;
|
||||
|
||||
$days2 = $timeSpan->totalDays();
|
||||
if($timeSpan->isNegative())
|
||||
$days2 *= -1;
|
||||
|
||||
if($days2 === 0.0)
|
||||
return 0.0;
|
||||
|
||||
return $days1 / $days2;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the result of a division of this instance and the provided divisor.
|
||||
*
|
||||
* @param float $divisor Value to divide by.
|
||||
* @return TimeSpan Instance that represents this instance divided by the value of $divisor.
|
||||
*/
|
||||
public function divideFloat(float $divisor): TimeSpan {
|
||||
$totalDays = $this->totalDays();
|
||||
if($this->isNegative())
|
||||
$totalDays *= -1;
|
||||
$totalDays /= $divisor;
|
||||
return self::fromDays($totalDays);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a new TimeSpan whose alue is the result of a multiplication of this oinstance and the provided factor.
|
||||
*
|
||||
* @param float $factor Value to multiply with.
|
||||
* @return TimeSpan Instance that represents this instance multiplied by the value of $factor.
|
||||
*/
|
||||
public function multiply(float $factor): TimeSpan {
|
||||
$totalDays = $this->totalDays();
|
||||
if($this->isNegative())
|
||||
$totalDays *= -1;
|
||||
$totalDays *= $factor;
|
||||
return self::fromDays($totalDays);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a new TimeSpan whose value is the negated value of this instance.
|
||||
*
|
||||
* @return TimeSpan Negated copy of this instance.
|
||||
*/
|
||||
public function negate(): TimeSpan {
|
||||
return self::create(
|
||||
$this->getDays(),
|
||||
$this->getHours(),
|
||||
$this->getMinutes(),
|
||||
$this->getSeconds(),
|
||||
$this->getMicroseconds(),
|
||||
!$this->isNegative()
|
||||
);
|
||||
}
|
||||
|
||||
public function compare(mixed $other): int {
|
||||
if(!($other instanceof DateInterval))
|
||||
return -1;
|
||||
$other = self::cast($other);
|
||||
|
||||
$diff = $this->getDays() <=> $other->getDays();
|
||||
if($diff) return $diff;
|
||||
|
||||
$diff = $this->getHours() <=> $other->getHours();
|
||||
if($diff) return $diff;
|
||||
|
||||
$diff = $this->getMinutes() <=> $other->getMinutes();
|
||||
if($diff) return $diff;
|
||||
|
||||
$diff = $this->getSeconds() <=> $other->getSeconds();
|
||||
if($diff) return $diff;
|
||||
|
||||
$diff = $this->getMicroseconds() <=> $other->getMicroseconds();
|
||||
if($diff) return $diff;
|
||||
|
||||
$diff = $this->isNegative() <=> $other->isNegative();
|
||||
if($diff) return $diff;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
public function equals(mixed $other): bool {
|
||||
if(!($other instanceof DateInterval))
|
||||
return false;
|
||||
$other = self::cast($other);
|
||||
return $this->getDays() === $other->getDays()
|
||||
&& $this->getHours() === $other->getHours()
|
||||
&& $this->getMinutes() === $other->getMinutes()
|
||||
&& $this->getSeconds() === $other->getSeconds()
|
||||
&& $this->getMicroseconds() === $other->getMicroseconds()
|
||||
&& $this->isNegative() === $other->isNegative();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the data which should be serialized as json.
|
||||
*
|
||||
* @see https://www.php.net/manual/en/jsonserializable.jsonserialize.php
|
||||
* @return mixed Data to be passed to json_encode.
|
||||
*/
|
||||
public function jsonSerialize(): mixed {
|
||||
return (string)$this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a string representation of this object.
|
||||
*
|
||||
* @return string Representation of this object.
|
||||
*/
|
||||
public function __toString(): string {
|
||||
$string = $this->isNegative() ? '-' : '';
|
||||
return sprintf(
|
||||
'%sP%dY%dM%dDT%dH%dM%d.%dS',
|
||||
$this->isNegative() ? '-' : '',
|
||||
$this->y,
|
||||
$this->m,
|
||||
$this->d,
|
||||
$this->getHours(),
|
||||
$this->getMinutes(),
|
||||
$this->getSeconds(),
|
||||
$this->getMicroseconds()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new TimeSpan instance that represents the specified number of days.
|
||||
*
|
||||
* @param float $days Number of days.
|
||||
* @return TimeSpan Instance representing the provided number of days.
|
||||
*/
|
||||
public static function fromDays(float $days): TimeSpan {
|
||||
$abs = abs($days);
|
||||
$round = (int)floor($abs);
|
||||
$hours = ($abs - $round) * self::HOURS_IN_DAY;
|
||||
$hoursRound = (int)floor($hours);
|
||||
$minutes = ($hours - $hoursRound) * self::MINS_IN_HOUR;
|
||||
$minsRound = (int)floor($minutes);
|
||||
$seconds = ($minutes - $minsRound) * self::SECS_IN_MIN;
|
||||
$secsRound = (int)floor($seconds);
|
||||
$micros = (int)floor(($seconds - $secsRound) * self::MICROS_IN_SEC);
|
||||
return self::create($round, $hoursRound, $minsRound, $secsRound, $micros, $days < 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new TimeSpan instance that represents the specified number of hours.
|
||||
*
|
||||
* @param float $hours Number of hours.
|
||||
* @return TimeSpan Instance representing the provided number of hours.
|
||||
*/
|
||||
public static function fromHours(float $hours): TimeSpan {
|
||||
$abs = abs($hours);
|
||||
$round = (int)floor($abs);
|
||||
$minutes = ($abs - $round) * self::MINS_IN_HOUR;
|
||||
$minsRound = (int)floor($minutes);
|
||||
$seconds = ($minutes - $minsRound) * self::SECS_IN_MIN;
|
||||
$secsRound = (int)floor($seconds);
|
||||
$micros = (int)floor(($seconds - $secsRound) * self::MICROS_IN_SEC);
|
||||
return self::create(0, $round, $minsRound, $secsRound, $micros, $hours < 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new TimeSpan instance that represents the specified number of minutes.
|
||||
*
|
||||
* @param float $minutes Number of minutes.
|
||||
* @return TimeSpan Instance representing the provided number of minutes.
|
||||
*/
|
||||
public static function fromMinutes(float $minutes): TimeSpan {
|
||||
$abs = abs($minutes);
|
||||
$round = (int)floor($abs);
|
||||
$seconds = ($abs - $round) * self::SECS_IN_MIN;
|
||||
$secsRound = (int)floor($seconds);
|
||||
$micros = (int)floor(($seconds - $secsRound) * self::MICROS_IN_SEC);
|
||||
return self::create(0, 0, $round, $secsRound, $micros, $minutes < 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new TimeSpan instance that represents the specified number of seconds.
|
||||
*
|
||||
* @param float $seconds Number of seconds.
|
||||
* @return TimeSpan Instance representing the provided number of seconds.
|
||||
*/
|
||||
public static function fromSeconds(float $seconds): TimeSpan {
|
||||
$abs = abs($seconds);
|
||||
$round = (int)floor($abs);
|
||||
$micros = (int)floor(($abs - $round) * self::MICROS_IN_SEC);
|
||||
return self::create(0, 0, 0, $round, $micros, $seconds < 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new TimeSpan instance that represents the specified number of milliseconds.
|
||||
*
|
||||
* @param float $millis Number of milliseconds.
|
||||
* @return TimeSpan Instance representing the provided number of milliseconds.
|
||||
*/
|
||||
public static function fromMilliseconds(float $millis): TimeSpan {
|
||||
return self::fromMicroseconds($millis * 1000);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new TimeSpan instance that represents the specified number of microseconds.
|
||||
*
|
||||
* @param float $micros Number of microseconds.
|
||||
* @return TimeSpan Instance representing the provided number of microseconds.
|
||||
*/
|
||||
public static function fromMicroseconds(float $micros): TimeSpan {
|
||||
return self::create(0, 0, 0, 0, (int)floor(abs($micros)), $micros < 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new TimeSpan using the given parameters.
|
||||
*
|
||||
* @param int $days Number of days.
|
||||
* @param int $hours Number of hours.
|
||||
* @param int $minutes Number of minutes.
|
||||
* @param int $seconds Number of seconds.
|
||||
* @param int $micros Number of microseconds.
|
||||
* @param bool $negative true for a negative TimeSpan, false for positive.
|
||||
* @return TimeSpan A new TimeSpan from the provided parameters.
|
||||
*/
|
||||
public static function create(int $days, int $hours, int $minutes, int $seconds, int $micros = 0, bool $negative = false): TimeSpan {
|
||||
$ts = new TimeSpan;
|
||||
$ts->realDays = $days = max(0, $days);
|
||||
$ts->h = max(0, min(23, $hours));
|
||||
$ts->i = max(0, min(59, $minutes));
|
||||
$ts->s = max(0, min(59, $seconds));
|
||||
$ts->f = $micros / self::MICROS_IN_SEC;
|
||||
$ts->invert = $negative ? 1 : 0;
|
||||
|
||||
// this may still be stupid
|
||||
if($days > 0) {
|
||||
$days /= 365;
|
||||
$ts->y = (int)$days;
|
||||
$days -= $ts->y;
|
||||
$days *= 12;
|
||||
$ts->m = (int)$days;
|
||||
$days -= $ts->m;
|
||||
$days *= 31;
|
||||
$ts->d = (int)$days;
|
||||
}
|
||||
|
||||
return $ts;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a TimeSpan from the relative parts of a string.
|
||||
*
|
||||
* Uses the same parser as strtotime and the DateTime constructor internally.
|
||||
*
|
||||
* @param string $dateTime A date with relative parts.
|
||||
* @return TimeSpan A TimeSpan representing the given
|
||||
*/
|
||||
public static function createFromDateString(string $dateTime): TimeSpan {
|
||||
return self::cast(parent::createFromDateString($dateTime));
|
||||
}
|
||||
|
||||
/**
|
||||
* Makes sure a DateInterval inheriting object is a TimeSpan instance.
|
||||
*
|
||||
* @param DateInterval $dateInterval Input object.
|
||||
* @return TimeSpan If the input was a TimeSpan, the same instance will be returned.
|
||||
* If the input was something else, a new TimeSpan instance will be returned based on the input.
|
||||
*/
|
||||
public static function cast(DateInterval $dateInterval): TimeSpan {
|
||||
if($dateInterval instanceof TimeSpan)
|
||||
return $dateInterval;
|
||||
|
||||
$timeSpan = new TimeSpan;
|
||||
$timeSpan->y = $dateInterval->y;
|
||||
$timeSpan->m = $dateInterval->m;
|
||||
$timeSpan->d = $dateInterval->d;
|
||||
$timeSpan->h = $dateInterval->h;
|
||||
$timeSpan->i = $dateInterval->i;
|
||||
$timeSpan->s = $dateInterval->s;
|
||||
$timeSpan->f = $dateInterval->f;
|
||||
$timeSpan->invert = $dateInterval->invert;
|
||||
$timeSpan->realDays = $timeSpan->calculateRealDays();
|
||||
return $timeSpan;
|
||||
}
|
||||
}
|
|
@ -1,213 +0,0 @@
|
|||
<?php
|
||||
// TimeZoneInfo.php
|
||||
// Created: 2021-06-12
|
||||
// Updated: 2022-02-27
|
||||
|
||||
namespace Index;
|
||||
|
||||
use DateTimeInterface;
|
||||
use DateTimeZone;
|
||||
use JsonSerializable;
|
||||
use RuntimeException;
|
||||
use Stringable;
|
||||
|
||||
/**
|
||||
* Represents a time zone.
|
||||
*/
|
||||
class TimeZoneInfo extends DateTimeZone implements JsonSerializable, Stringable, IComparable, IEquatable {
|
||||
private array|null $location = null;
|
||||
|
||||
private static bool $constructed = false;
|
||||
private static TimeZoneInfo $utc;
|
||||
|
||||
/**
|
||||
* Constructs a new TimeZoneInfo object.
|
||||
*
|
||||
* @param string $timeZone Time zone identifier.,
|
||||
* @return TimeZoneInfo New instance of TimeZoneInfo.
|
||||
*/
|
||||
public function __construct(string $timeZone) {
|
||||
parent::__construct($timeZone);
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
public static function construct(): void {
|
||||
if(self::$constructed)
|
||||
throw new RuntimeException('Static constructor was already called.');
|
||||
self::$constructed = true;
|
||||
self::$utc = new TimeZoneInfo('UTC');
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a TimeZoneInfo instance representing the UTC (+00:00) time zone.
|
||||
*
|
||||
* @return TimeZoneInfo Instance representing UTC.
|
||||
*/
|
||||
public static function utc(): TimeZoneInfo {
|
||||
return self::$utc;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the current default time zone.
|
||||
*
|
||||
* Uses date_default_timezone_get internally.
|
||||
*
|
||||
* @return TimeZoneInfo Instance representing the default time zone.
|
||||
*/
|
||||
public static function default(): TimeZoneInfo {
|
||||
return new TimeZoneInfo(date_default_timezone_get());
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the current default time zone.
|
||||
*
|
||||
* Uses date_default_timezone_set internally.
|
||||
*
|
||||
* @param DateTimeZone|string $timeZone Desired default time zone.
|
||||
* @throws RuntimeException If an invalid time zone was supplied.
|
||||
*/
|
||||
public static function setDefault(DateTimeZone|string $timeZone): void {
|
||||
if($timeZone instanceof DateTimeZone)
|
||||
$timeZone = $timeZone->getName();
|
||||
|
||||
if(!date_default_timezone_set($timeZone))
|
||||
throw new RuntimeException('Invalid default time zone specified.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets location info for a time zone.
|
||||
*
|
||||
* It makes more sense to use getCountryCode, getLatitude, getLongitude and getComments, if you can.
|
||||
*
|
||||
* @return array Location information.
|
||||
*/
|
||||
public function getLocation(): array {
|
||||
if($this->location === null)
|
||||
$this->location = parent::getLocation();
|
||||
return $this->location;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the country code of the country which this time zone falls in.
|
||||
*
|
||||
* @return string Country code for this time zone.
|
||||
*/
|
||||
public function getCountryCode(): string {
|
||||
return $this->getLocation()['country_code'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the latitude of this time zone.
|
||||
*
|
||||
* @return float Latitude of this time zone.
|
||||
*/
|
||||
public function getLatitude(): float {
|
||||
return $this->getLocation()['latitude'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the longitude of this time zone.
|
||||
*
|
||||
* @return float Longitude of this time zone.
|
||||
*/
|
||||
public function getLongitude(): float {
|
||||
return $this->getLocation()['longitude'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets location comments for this time zone.
|
||||
*
|
||||
* @return string Location comments.
|
||||
*/
|
||||
public function getComments(): string {
|
||||
return $this->getLocation()['comments'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the offset of this timezone relative to a given date/time instance.
|
||||
*
|
||||
* @param DateTimeInterface|null $dateTime Date/time to use as a base, null for UTC Now.
|
||||
* @return int Offset relative to given date/time.
|
||||
*/
|
||||
public function getOffset(DateTimeInterface|null $dateTime = null): int {
|
||||
return parent::getOffset($dateTime ?? new DateTime('now', self::$utc));
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a string representation of this object.
|
||||
*
|
||||
* @return string Representation of this object.
|
||||
*/
|
||||
public function __toString(): string {
|
||||
$offset = $this->getOffset();
|
||||
return sprintf(
|
||||
'(UTC%s%s) %s',
|
||||
$offset < 0 ? '-' : '+',
|
||||
date('H:i', abs($offset)),
|
||||
$this->getName()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the data which should be serialized as json.
|
||||
*
|
||||
* @see https://www.php.net/manual/en/jsonserializable.jsonserialize.php
|
||||
* @return mixed Data to be passed to json_encode.
|
||||
*/
|
||||
public function jsonSerialize(): mixed {
|
||||
return $this->getName();
|
||||
}
|
||||
|
||||
public function compare(mixed $other): int {
|
||||
if(!($other instanceof DateTimeZone))
|
||||
return -1;
|
||||
$other = self::cast($other);
|
||||
|
||||
$diff = $this->getOffset() <=> $other->getOffset();
|
||||
if($diff) return $diff;
|
||||
|
||||
return strcmp($this->getName(), $other->getName());
|
||||
}
|
||||
|
||||
public function equals(mixed $other): bool {
|
||||
if(!($other instanceof DateTimeZone))
|
||||
return false;
|
||||
return $this->getName() === $other->getName()
|
||||
|| $this->getOffset() === self::cast($other)->getOffset();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a list of all time zones.
|
||||
*
|
||||
* @param bool $ordered true if the list should be ordered, false if not.
|
||||
* @param int $timeZoneGroup ID of a group to filter the generated list.
|
||||
* @param string|null $countryCode Country to filter the generated list by.
|
||||
* @return array Array containing the time zones.
|
||||
*/
|
||||
public static function all(bool $ordered = false, int $timeZoneGroup = DateTimeZone::ALL, string|null $countryCode = null): array {
|
||||
$timeZones = self::listIdentifiers($timeZoneGroup, $countryCode === null ? null : $countryCode);
|
||||
$timeZones = XArray::select($timeZones, fn($id) => new TimeZoneInfo($id));
|
||||
|
||||
if($ordered)
|
||||
$timeZones = XArray::sort($timeZones, fn($a, $b) => $a->compare($b));
|
||||
|
||||
return $timeZones;
|
||||
}
|
||||
|
||||
/**
|
||||
* Makes sure a DateTimeZone inheriting object is a TimeZoneInfo instance.
|
||||
*
|
||||
* @param DateTimeZone $timeZone Input object.
|
||||
* @return TimeZoneInfo If the input was a TimeZoneInfo, the same instance will be returned.
|
||||
* If the input was something else, a new TimeZoneInfo instance will be returned based on the input.
|
||||
*/
|
||||
public static function cast(DateTimeZone $timeZone): TimeZoneInfo {
|
||||
if($timeZone instanceof TimeZoneInfo)
|
||||
return $timeZone;
|
||||
return new TimeZoneInfo($timeZone->getName());
|
||||
}
|
||||
}
|
||||
|
||||
TimeZoneInfo::construct();
|
103
src/XDateTime.php
Normal file
103
src/XDateTime.php
Normal file
|
@ -0,0 +1,103 @@
|
|||
<?php
|
||||
// XDateTime.php
|
||||
// Created: 2024-07-31
|
||||
// Updated: 2024-07-31
|
||||
|
||||
namespace Index;
|
||||
|
||||
use DateTimeImmutable;
|
||||
use DateTimeInterface;
|
||||
use DateTimeZone;
|
||||
|
||||
final class XDateTime {
|
||||
private const COMPARE_FORMAT = 'YmdHisu';
|
||||
|
||||
public static function now(): DateTimeInterface {
|
||||
return new DateTimeImmutable('now');
|
||||
}
|
||||
|
||||
private static function toCompareFormat(DateTimeInterface|string|int $dt): string {
|
||||
if($dt instanceof DateTimeInterface)
|
||||
return $dt->format(self::COMPARE_FORMAT);
|
||||
|
||||
if(is_string($dt))
|
||||
$dt = strtotime($dt);
|
||||
|
||||
return gmdate(self::COMPARE_FORMAT, $dt);
|
||||
}
|
||||
|
||||
public static function compare(
|
||||
DateTimeInterface|string|int $dt1,
|
||||
DateTimeInterface|string|int $dt2
|
||||
): int {
|
||||
return strcmp(
|
||||
self::toCompareFormat($dt1),
|
||||
self::toCompareFormat($dt2)
|
||||
);
|
||||
}
|
||||
|
||||
public static function compareTimeZone(
|
||||
DateTimeZone|string $tz1,
|
||||
DateTimeZone|string $tz2
|
||||
): int {
|
||||
if(is_string($tz1))
|
||||
$tz1 = new DateTimeZone($tz1);
|
||||
if(is_string($tz2))
|
||||
$tz2 = new DateTimeZone($tz2);
|
||||
|
||||
$now = self::now();
|
||||
$diff = $tz1->getOffset($now) <=> $tz2->getOffset($now);
|
||||
if($diff) return $diff;
|
||||
|
||||
return strcmp(
|
||||
$tz1->getName(),
|
||||
$tz2->getName()
|
||||
);
|
||||
}
|
||||
|
||||
public static function timeZoneListName(DateTimeZone $dtz): string {
|
||||
$offset = $dtz->getOffset(self::now());
|
||||
return sprintf(
|
||||
'(UTC%s%s) %s',
|
||||
$offset < 0 ? '-' : '+',
|
||||
date('H:i', abs($offset)),
|
||||
$dtz->getName()
|
||||
);
|
||||
}
|
||||
|
||||
public static function listTimeZones(bool $sort = false, int $group = DateTimeZone::ALL, string|null $countryCode = null): array {
|
||||
$list = DateTimeZone::listIdentifiers($group, $countryCode);
|
||||
$list = XArray::select($list, fn($id) => new DateTimeZone($id));
|
||||
|
||||
if($sort)
|
||||
$list = XArray::sort($list, self::compareTimeZone(...));
|
||||
|
||||
return $list;
|
||||
}
|
||||
|
||||
public static function format(DateTimeInterface|string|int|null $dt, string $format): string {
|
||||
if($dt === null) {
|
||||
$dt = time();
|
||||
} else {
|
||||
if($dt instanceof DateTimeInterface)
|
||||
return $dt->format($format);
|
||||
|
||||
if(is_string($dt))
|
||||
$dt = strtotime($dt);
|
||||
}
|
||||
|
||||
return gmdate($format, $dt);
|
||||
}
|
||||
|
||||
public static function toISO8601String(DateTimeInterface|string|int|null $dt): string {
|
||||
return self::format($dt, DateTimeInterface::ATOM);
|
||||
}
|
||||
|
||||
public static function toCookieString(DateTimeInterface|string|int|null $dt): string {
|
||||
return self::format($dt, DateTimeInterface::COOKIE);
|
||||
}
|
||||
|
||||
public static function toRFC822String(DateTimeInterface|string|int|null $dt): string {
|
||||
return self::format($dt, DateTimeInterface::RFC822);
|
||||
}
|
||||
}
|
|
@ -1,386 +0,0 @@
|
|||
<?php
|
||||
// DateTimeTest.php
|
||||
// Created: 2021-06-14
|
||||
// Updated: 2024-07-31
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use PHPUnit\Framework\Attributes\CoversClass;
|
||||
use Index\DateTime;
|
||||
use Index\TimeSpan;
|
||||
use Index\TimeZoneInfo;
|
||||
|
||||
#[CoversClass(DateTime::class)]
|
||||
#[CoversClass(TimeSpan::class)]
|
||||
#[CoversClass(TimeZoneInfo::class)]
|
||||
final class DateTimeTest extends TestCase {
|
||||
public function testAttributes(): void {
|
||||
$index = new DateTime('2021-06-14T21:07:14.359324 CEST');
|
||||
$this->assertEquals($index->getYear(), 2021);
|
||||
$this->assertEquals($index->getMonth(), 6);
|
||||
$this->assertEquals($index->getDay(), 14);
|
||||
$this->assertEquals($index->getHour(), 21);
|
||||
$this->assertEquals($index->getMinute(), 7);
|
||||
$this->assertEquals($index->getSecond(), 14);
|
||||
$this->assertEquals($index->getMillisecond(), 359);
|
||||
$this->assertEquals($index->getMicrosecond(), 359324);
|
||||
$this->assertEquals($index->getDayOfWeek(), DateTime::MONDAY);
|
||||
$this->assertEquals($index->getDayOfYear(), 165);
|
||||
$this->assertEquals($index->getWeek(), 24);
|
||||
$this->assertTrue($index->isDaylightSavingTime());
|
||||
$this->assertFalse($index->isLeapYear());
|
||||
$this->assertFalse($index->isUTC());
|
||||
|
||||
$indexDate = $index->getDate();
|
||||
$this->assertEquals($indexDate->getYear(), 2021);
|
||||
$this->assertEquals($indexDate->getMonth(), 6);
|
||||
$this->assertEquals($indexDate->getDay(), 14);
|
||||
$this->assertEquals($indexDate->getHour(), 0);
|
||||
$this->assertEquals($indexDate->getMinute(), 0);
|
||||
$this->assertEquals($indexDate->getSecond(), 0);
|
||||
$this->assertEquals($indexDate->getMillisecond(), 0);
|
||||
$this->assertEquals($indexDate->getMicrosecond(), 0);
|
||||
$this->assertEquals($indexDate->getDayOfWeek(), DateTime::MONDAY);
|
||||
$this->assertEquals($indexDate->getDayOfYear(), 165);
|
||||
$this->assertEquals($indexDate->getWeek(), 24);
|
||||
|
||||
$indexTime = $index->getTimeOfDay();
|
||||
$this->assertEquals($indexTime->getHours(), 21);
|
||||
$this->assertEquals($indexTime->getMinutes(), 7);
|
||||
$this->assertEquals($indexTime->getSeconds(), 14);
|
||||
$this->assertEquals($indexTime->getMilliseconds(), 359);
|
||||
$this->assertEquals($indexTime->getMicroseconds(), 359324);
|
||||
}
|
||||
|
||||
public function testTimeZone(): void {
|
||||
$index1 = DateTime::utcNow();
|
||||
$index2 = DateTime::now(new TimeZoneInfo('Australia/Melbourne'));
|
||||
$this->assertEquals($index1->getUnixTimeSeconds(), $index2->getUnixTimeSeconds());
|
||||
}
|
||||
|
||||
public function testSetters(): void {
|
||||
$index = new DateTime('2021-06-14T21:07:14.359324 CEST');
|
||||
$this->assertEquals($index->getYear(), 2021);
|
||||
$this->assertEquals($index->getMonth(), 6);
|
||||
$this->assertEquals($index->getDay(), 14);
|
||||
$this->assertEquals($index->getHour(), 21);
|
||||
$this->assertEquals($index->getMinute(), 7);
|
||||
$this->assertEquals($index->getSecond(), 14);
|
||||
$this->assertEquals($index->getMillisecond(), 359);
|
||||
$this->assertEquals($index->getMicrosecond(), 359324);
|
||||
|
||||
$index = $index->setDate(2005, 3, 9);
|
||||
$this->assertEquals($index->getYear(), 2005);
|
||||
$this->assertEquals($index->getMonth(), 3);
|
||||
$this->assertEquals($index->getDay(), 9);
|
||||
$this->assertEquals($index->getHour(), 21);
|
||||
$this->assertEquals($index->getMinute(), 7);
|
||||
$this->assertEquals($index->getSecond(), 14);
|
||||
$this->assertEquals($index->getMillisecond(), 359);
|
||||
$this->assertEquals($index->getMicrosecond(), 359324);
|
||||
|
||||
$index = $index->setISODate(2011, 20, 5);
|
||||
$this->assertEquals($index->getYear(), 2011);
|
||||
$this->assertEquals($index->getMonth(), 5);
|
||||
$this->assertEquals($index->getDay(), 20);
|
||||
$this->assertEquals($index->getHour(), 21);
|
||||
$this->assertEquals($index->getMinute(), 7);
|
||||
$this->assertEquals($index->getSecond(), 14);
|
||||
$this->assertEquals($index->getMillisecond(), 359);
|
||||
$this->assertEquals($index->getMicrosecond(), 359324);
|
||||
|
||||
$index = $index->setTime(10, 46, 50, 987654);
|
||||
$this->assertEquals($index->getYear(), 2011);
|
||||
$this->assertEquals($index->getMonth(), 5);
|
||||
$this->assertEquals($index->getDay(), 20);
|
||||
$this->assertEquals($index->getHour(), 10);
|
||||
$this->assertEquals($index->getMinute(), 46);
|
||||
$this->assertEquals($index->getSecond(), 50);
|
||||
$this->assertEquals($index->getMillisecond(), 987);
|
||||
$this->assertEquals($index->getMicrosecond(), 987654);
|
||||
|
||||
$index = $index->setTimestamp(1623702634);
|
||||
$this->assertEquals($index->getYear(), 2021);
|
||||
$this->assertEquals($index->getMonth(), 6);
|
||||
$this->assertEquals($index->getDay(), 14);
|
||||
$this->assertEquals($index->getHour(), 22);
|
||||
$this->assertEquals($index->getMinute(), 30);
|
||||
$this->assertEquals($index->getSecond(), 34);
|
||||
$this->assertEquals($index->getMillisecond(), 0);
|
||||
$this->assertEquals($index->getMicrosecond(), 0);
|
||||
$this->assertFalse($index->isUTC());
|
||||
}
|
||||
|
||||
public function testUnixTimestamp(): void {
|
||||
$index = DateTime::fromUnixTimeSeconds(1623696039);
|
||||
$this->assertEquals($index->getYear(), 2021);
|
||||
$this->assertEquals($index->getMonth(), 6);
|
||||
$this->assertEquals($index->getDay(), 14);
|
||||
$this->assertEquals($index->getHour(), 18);
|
||||
$this->assertEquals($index->getMinute(), 40);
|
||||
$this->assertEquals($index->getSecond(), 39);
|
||||
$this->assertEquals($index->getMillisecond(), 0);
|
||||
$this->assertEquals($index->getMicrosecond(), 0);
|
||||
$this->assertEquals($index->getUnixTimeSeconds(), 1623696039);
|
||||
$this->assertEquals($index->getUnixTimeMilliseconds(), 1623696039000);
|
||||
$this->assertTrue($index->isUTC());
|
||||
|
||||
$index = DateTime::fromUnixTimeMilliseconds(1623696422656);
|
||||
$this->assertEquals($index->getYear(), 2021);
|
||||
$this->assertEquals($index->getMonth(), 6);
|
||||
$this->assertEquals($index->getDay(), 14);
|
||||
$this->assertEquals($index->getHour(), 18);
|
||||
$this->assertEquals($index->getMinute(), 47);
|
||||
$this->assertEquals($index->getSecond(), 2);
|
||||
$this->assertEquals($index->getMillisecond(), 656);
|
||||
$this->assertEquals($index->getMicrosecond(), 656000);
|
||||
$this->assertEquals($index->getUnixTimeSeconds(), 1623696422);
|
||||
$this->assertEquals($index->getUnixTimeMilliseconds(), 1623696422656);
|
||||
$this->assertTrue($index->isUTC());
|
||||
}
|
||||
|
||||
// verify the results of this at some point
|
||||
public function testAdding(): void {
|
||||
$index = new DateTime('2021-06-14T21:07:14.359324Z');
|
||||
|
||||
// Confirm initial state
|
||||
$this->assertEquals($index->getYear(), 2021);
|
||||
$this->assertEquals($index->getMonth(), 6);
|
||||
$this->assertEquals($index->getDay(), 14);
|
||||
$this->assertEquals($index->getHour(), 21);
|
||||
$this->assertEquals($index->getMinute(), 7);
|
||||
$this->assertEquals($index->getSecond(), 14);
|
||||
$this->assertEquals($index->getMillisecond(), 359);
|
||||
$this->assertEquals($index->getMicrosecond(), 359324);
|
||||
|
||||
// Add
|
||||
$index = $index->add(TimeSpan::create(1, 0, 10, 0));
|
||||
$this->assertEquals($index->getDay(), 15);
|
||||
$this->assertEquals($index->getMinute(), 17);
|
||||
|
||||
// Add years
|
||||
$index = $index->addYears(1);
|
||||
$this->assertEquals($index->getYear(), 2022);
|
||||
$this->assertEquals($index->getMonth(), 6);
|
||||
$index = $index->addYears(1.5);
|
||||
$this->assertEquals($index->getYear(), 2023);
|
||||
$this->assertEquals($index->getMonth(), 12);
|
||||
|
||||
// Add months
|
||||
$index = $index->addMonths(1);
|
||||
$this->assertEquals($index->getMonth(), 12);
|
||||
$this->assertEquals($index->getDay(), 16);
|
||||
$index = $index->addMonths(1.5);
|
||||
$this->assertEquals($index->getMonth(), 6);
|
||||
$this->assertEquals($index->getDay(), 15);
|
||||
|
||||
// Add days
|
||||
$index = $index->addDays(1);
|
||||
$this->assertEquals($index->getDay(), 16);
|
||||
$this->assertEquals($index->getHour(), 21);
|
||||
$index = $index->addDays(1.5);
|
||||
$this->assertEquals($index->getDay(), 18);
|
||||
$this->assertEquals($index->getHour(), 9);
|
||||
|
||||
// Add hours
|
||||
$index = $index->addHours(1);
|
||||
$this->assertEquals($index->getHour(), 10);
|
||||
$this->assertEquals($index->getMinute(), 17);
|
||||
$index = $index->addHours(1.5);
|
||||
$this->assertEquals($index->getHour(), 11);
|
||||
$this->assertEquals($index->getMinute(), 47);
|
||||
|
||||
// Add minutes
|
||||
$index = $index->addMinutes(1);
|
||||
$this->assertEquals($index->getMinute(), 48);
|
||||
$this->assertEquals($index->getSecond(), 14);
|
||||
$index = $index->addMinutes(1.5);
|
||||
$this->assertEquals($index->getMinute(), 49);
|
||||
$this->assertEquals($index->getSecond(), 44);
|
||||
|
||||
// Add seconds
|
||||
$index = $index->addSeconds(1);
|
||||
$this->assertEquals($index->getSecond(), 45);
|
||||
$this->assertEquals($index->getMillisecond(), 359);
|
||||
$this->assertEquals($index->getMicrosecond(), 359324);
|
||||
$index = $index->addSeconds(1.5);
|
||||
$this->assertEquals($index->getSecond(), 46);
|
||||
$this->assertEquals($index->getMillisecond(), 859);
|
||||
$this->assertEquals($index->getMicrosecond(), 859324);
|
||||
|
||||
// Add milliseconds
|
||||
$index = $index->addMilliseconds(1);
|
||||
$this->assertEquals($index->getMillisecond(), 860);
|
||||
$this->assertEquals($index->getMicrosecond(), 860324);
|
||||
$index = $index->addMilliseconds(1.5);
|
||||
$this->assertEquals($index->getMillisecond(), 861);
|
||||
$this->assertEquals($index->getMicrosecond(), 861824);
|
||||
|
||||
// Add microseconds
|
||||
$index = $index->addMicroseconds(1);
|
||||
$this->assertEquals($index->getMicrosecond(), 861825);
|
||||
$index = $index->addMicroseconds(1.5);
|
||||
$this->assertEquals($index->getMicrosecond(), 861826);
|
||||
}
|
||||
|
||||
public function testSubtract(): void {
|
||||
$index = new DateTime('2021-06-14T21:07:14.359324Z');
|
||||
|
||||
// Confirm initial state
|
||||
$this->assertEquals($index->getYear(), 2021);
|
||||
$this->assertEquals($index->getMonth(), 6);
|
||||
$this->assertEquals($index->getDay(), 14);
|
||||
$this->assertEquals($index->getHour(), 21);
|
||||
$this->assertEquals($index->getMinute(), 7);
|
||||
$this->assertEquals($index->getSecond(), 14);
|
||||
$this->assertEquals($index->getMillisecond(), 359);
|
||||
$this->assertEquals($index->getMicrosecond(), 359324);
|
||||
|
||||
// Subtract
|
||||
$index = $index->subtract(TimeSpan::fromDays(400.12));
|
||||
$this->assertEquals($index->getYear(), 2020);
|
||||
$this->assertEquals($index->getMonth(), 5);
|
||||
$this->assertEquals($index->getDay(), 10);
|
||||
$this->assertEquals($index->getHour(), 18);
|
||||
$this->assertEquals($index->getMinute(), 14);
|
||||
$this->assertEquals($index->getSecond(), 26);
|
||||
$this->assertEquals($index->getMillisecond(), 359);
|
||||
$this->assertEquals($index->getMicrosecond(), 359324);
|
||||
}
|
||||
|
||||
public function testDifference(): void {
|
||||
$index1 = new DateTime('2021-06-14T21:07:14Z');
|
||||
$index2 = DateTime::create(2013, 1, 27, 23, 14, 44, 0, new TimeZoneInfo('Europe/Amsterdam'));
|
||||
$diff = $index1->difference($index2);
|
||||
|
||||
$this->assertEquals($diff->getDays(), 3061);
|
||||
$this->assertEquals($diff->getHours(), 22);
|
||||
$this->assertEquals($diff->getMinutes(), 52);
|
||||
$this->assertEquals($diff->getSeconds(), 30);
|
||||
$this->assertTrue($diff->isNegative());
|
||||
|
||||
$this->assertEquals($diff->totalDays(), 3061.953125);
|
||||
$this->assertEquals($diff->totalHours(), 73486.875);
|
||||
$this->assertEquals($diff->totalMinutes(), 4409212.5);
|
||||
$this->assertEquals($diff->totalSeconds(), 264552750);
|
||||
$this->assertEquals($diff->totalMilliseconds(), 264552750000);
|
||||
$this->assertEquals($diff->totalMicroseconds(), 264552750000000);
|
||||
|
||||
$negated = $diff->negate();
|
||||
$this->assertEquals($negated->getDays(), 3061);
|
||||
$this->assertEquals($negated->getHours(), 22);
|
||||
$this->assertEquals($negated->getMinutes(), 52);
|
||||
$this->assertEquals($negated->getSeconds(), 30);
|
||||
$this->assertFalse($negated->isNegative());
|
||||
}
|
||||
|
||||
public function testModify(): void {
|
||||
$index = new DateTime('2021-06-14T21:07:14Z');
|
||||
$this->assertEquals($index->getMonth(), 6);
|
||||
|
||||
$index = $index->modify('+1 month');
|
||||
$this->assertEquals($index->getMonth(), 7);
|
||||
}
|
||||
|
||||
public function testCreate(): void {
|
||||
$index = DateTime::create(2013, 1, 27, 23, 14, 44, 0, new TimeZoneInfo('Europe/Amsterdam'));
|
||||
$this->assertEquals($index->getYear(), 2013);
|
||||
$this->assertEquals($index->getMonth(), 1);
|
||||
$this->assertEquals($index->getDay(), 27);
|
||||
$this->assertEquals($index->getHour(), 23);
|
||||
$this->assertEquals($index->getMinute(), 14);
|
||||
$this->assertEquals($index->getSecond(), 44);
|
||||
|
||||
$index = $index->setTimezone(new TimeZoneInfo('UTC'));
|
||||
$this->assertEquals($index->getHour(), 22);
|
||||
|
||||
$index = $index->setTimezone(new TimeZoneInfo('Asia/Tokyo'));
|
||||
$this->assertEquals($index->getDay(), 28);
|
||||
$this->assertEquals($index->getHour(), 7);
|
||||
|
||||
$index = $index->setTimezone(new TimeZoneInfo('America/New_York'));
|
||||
$this->assertEquals($index->getDay(), 27);
|
||||
$this->assertEquals($index->getHour(), 17);
|
||||
|
||||
$index = DateTime::createFromFormat('Y-m-d H:i:s', '2012-05-20 10:14:28');
|
||||
$this->assertEquals($index->format('Y-m-d H:i:s'), '2012-05-20 10:14:28');
|
||||
|
||||
$this->assertFalse(DateTime::createFromFormat('Y-m-d H:i:s', 'mewow'));
|
||||
|
||||
$mutable = new \DateTime('2021-06-14T20:20:46Z');
|
||||
|
||||
$index = DateTime::createFromInterface($mutable);
|
||||
$this->assertEquals($index->getUnixTimeMilliseconds(), (float)$mutable->format('Uv'));
|
||||
$this->assertEquals($index->getTimezone()->getName(), '+00:00');
|
||||
|
||||
$index = DateTime::createFromMutable($mutable);
|
||||
$this->assertEquals($index->getUnixTimeMilliseconds(), (float)$mutable->format('Uv'));
|
||||
}
|
||||
|
||||
public function testToString(): void {
|
||||
$dateTime = DateTime::create(2013, 1, 27, 23, 14, 44, 0, new TimeZoneInfo('Europe/Amsterdam'));
|
||||
$this->assertEquals((string)$dateTime, '2013-01-27T23:14:44+01:00');
|
||||
$this->assertEquals(json_encode($dateTime), '"2013-01-27T23:14:44+01:00"');
|
||||
$this->assertEquals((string)$dateTime->toISO8601String(), '2013-01-27T23:14:44+01:00');
|
||||
$this->assertEquals((string)$dateTime->toCookieString(), 'Sunday, 27-Jan-2013 23:14:44 CET');
|
||||
$this->assertEquals((string)$dateTime->toRFC822String(), 'Sun, 27 Jan 13 23:14:44 +0100');
|
||||
|
||||
$dateTime = $dateTime->setTimezone(TimeZoneInfo::utc());
|
||||
$this->assertEquals((string)$dateTime, '2013-01-27T22:14:44+00:00');
|
||||
$this->assertEquals(json_encode($dateTime), '"2013-01-27T22:14:44+00:00"');
|
||||
$this->assertEquals((string)$dateTime->toISO8601String(), '2013-01-27T22:14:44+00:00');
|
||||
$this->assertEquals((string)$dateTime->toCookieString(), 'Sunday, 27-Jan-2013 22:14:44 UTC');
|
||||
$this->assertEquals((string)$dateTime->toRFC822String(), 'Sun, 27 Jan 13 22:14:44 +0000');
|
||||
}
|
||||
|
||||
public function testCompare(): void {
|
||||
$index1 = new DateTime('2021-06-14T21:07:14Z');
|
||||
$index2 = DateTime::create(2013, 1, 27, 23, 14, 44, 0, new TimeZoneInfo('Europe/Amsterdam'));
|
||||
|
||||
$this->assertGreaterThan(0, $index1->compare($index2));
|
||||
$this->assertLessThan(0, $index2->compare($index1));
|
||||
$this->assertEquals(0, $index1->compare($index1));
|
||||
}
|
||||
|
||||
public function testEquals(): void {
|
||||
$index1 = new DateTime('2021-06-14T21:07:14Z');
|
||||
$index2 = DateTime::create(2013, 1, 27, 23, 14, 44, 0, new TimeZoneInfo('Europe/Amsterdam'));
|
||||
|
||||
$this->assertFalse($index1->equals($index2));
|
||||
$this->assertFalse($index2->equals($index1));
|
||||
$this->assertTrue($index1->equals($index1));
|
||||
}
|
||||
|
||||
public function testCasting(): void {
|
||||
$nativeDT = new \DateTime;
|
||||
$this->assertInstanceOf(DateTime::class, $nativeDTCast = DateTime::cast($nativeDT));
|
||||
$this->assertNotSame($nativeDT, $nativeDTCast);
|
||||
|
||||
$indexDT = new DateTime;
|
||||
$this->assertInstanceOf(DateTime::class, $indexDTCast = DateTime::cast($indexDT));
|
||||
$this->assertSame($indexDT, $indexDTCast);
|
||||
}
|
||||
|
||||
public function testTimeZoneOrder(): void {
|
||||
$all = TimeZoneInfo::all(true);
|
||||
$lastOffset = null;
|
||||
$lastString = null;
|
||||
|
||||
foreach($all as $timeZone) {
|
||||
$offset = $timeZone->getOffset();
|
||||
$string = $timeZone->getName();
|
||||
|
||||
if($lastOffset !== null) {
|
||||
$diff = $lastOffset <=> $offset;
|
||||
$this->assertLessThanOrEqual(0, $diff);
|
||||
|
||||
if($diff === 0)
|
||||
$this->assertLessThanOrEqual(0, $lastString <=> $string);
|
||||
}
|
||||
|
||||
$lastOffset = $offset;
|
||||
$lastString = $string;
|
||||
}
|
||||
}
|
||||
}
|
66
tests/XDateTimeTest.php
Normal file
66
tests/XDateTimeTest.php
Normal file
|
@ -0,0 +1,66 @@
|
|||
<?php
|
||||
// XDateTimeTest.php
|
||||
// Created: 2021-06-14
|
||||
// Updated: 2024-07-31
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use PHPUnit\Framework\Attributes\CoversClass;
|
||||
use Index\XDateTime;
|
||||
|
||||
#[CoversClass(XDateTime::class)]
|
||||
final class XDateTimeTest extends TestCase {
|
||||
public function testToString(): void {
|
||||
$dateTime = new DateTime('2013-01-27T23:14:44', new DateTimeZone('Europe/Amsterdam'));
|
||||
$this->assertEquals(XDateTime::toISO8601String($dateTime), '2013-01-27T23:14:44+01:00');
|
||||
$this->assertEquals(XDateTime::toCookieString($dateTime), 'Sunday, 27-Jan-2013 23:14:44 CET');
|
||||
$this->assertEquals(XDateTime::toRFC822String($dateTime), 'Sun, 27 Jan 13 23:14:44 +0100');
|
||||
|
||||
$dateTime = $dateTime->setTimezone(new DateTimeZone('UTC'));
|
||||
$this->assertEquals(XDateTime::toISO8601String($dateTime), '2013-01-27T22:14:44+00:00');
|
||||
$this->assertEquals(XDateTime::toCookieString($dateTime), 'Sunday, 27-Jan-2013 22:14:44 UTC');
|
||||
$this->assertEquals(XDateTime::toRFC822String($dateTime), 'Sun, 27 Jan 13 22:14:44 +0000');
|
||||
|
||||
$this->assertEquals(XDateTime::toISO8601String(1359324884), '2013-01-27T22:14:44+00:00');
|
||||
$this->assertEquals(XDateTime::toCookieString(1359324884), 'Sunday, 27-Jan-2013 22:14:44 GMT');
|
||||
$this->assertEquals(XDateTime::toRFC822String(1359324884), 'Sun, 27 Jan 13 22:14:44 +0000');
|
||||
|
||||
$this->assertEquals(XDateTime::toISO8601String('January 27th 2013 22:14:44 UTC'), '2013-01-27T22:14:44+00:00');
|
||||
$this->assertEquals(XDateTime::toCookieString('January 27th 2013 22:14:44 UTC'), 'Sunday, 27-Jan-2013 22:14:44 GMT');
|
||||
$this->assertEquals(XDateTime::toRFC822String('January 27th 2013 22:14:44 UTC'), 'Sun, 27 Jan 13 22:14:44 +0000');
|
||||
}
|
||||
|
||||
public function testCompare(): void {
|
||||
$dt1 = '2021-06-14T21:07:14Z';
|
||||
$dt2 = new DateTimeImmutable('2013-01-27T23:14:44', new DateTimeZone('Europe/Amsterdam'));
|
||||
|
||||
$this->assertGreaterThan(0, XDateTime::compare($dt1, $dt2));
|
||||
$this->assertLessThan(0, XDateTime::compare($dt2, $dt1));
|
||||
$this->assertEquals(0, XDateTime::compare($dt1, $dt1));
|
||||
$this->assertEquals(0, XDateTime::compare($dt2, $dt2));
|
||||
}
|
||||
|
||||
public function testTimeZoneOrder(): void {
|
||||
$timeZones = XDateTime::listTimeZones(true);
|
||||
$lastOffset = null;
|
||||
$lastString = null;
|
||||
|
||||
$now = XDateTime::now();
|
||||
foreach($timeZones as $timeZone) {
|
||||
$offset = $timeZone->getOffset($now);
|
||||
$string = $timeZone->getName();
|
||||
|
||||
if($lastOffset !== null) {
|
||||
$diff = $lastOffset <=> $offset;
|
||||
$this->assertLessThanOrEqual(0, $diff);
|
||||
|
||||
if($diff === 0)
|
||||
$this->assertLessThanOrEqual(0, $lastString <=> $string);
|
||||
}
|
||||
|
||||
$lastOffset = $offset;
|
||||
$lastString = $string;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -56,7 +56,7 @@ $files = array_merge($sources, $tests);
|
|||
|
||||
$topDir = dirname(__DIR__) . DIRECTORY_SEPARATOR;
|
||||
|
||||
$now = date('Y-m-d');
|
||||
$now = gmdate('Y-m-d');
|
||||
|
||||
foreach($files as $file) {
|
||||
echo 'Scanning ' . str_replace($topDir, '', $file) . '...' . PHP_EOL;
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
date_default_timezone_set('utc');
|
||||
|
||||
$version = date('0.ym.jHi');
|
||||
$version = gmdate('0.ym.jHi');
|
||||
|
||||
echo 'Updating VERSION file to ' . $version . PHP_EOL;
|
||||
|
||||
|
|
Loading…
Reference in a new issue