213 lines
6.4 KiB
PHP
213 lines
6.4 KiB
PHP
<?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();
|