mirror of
https://github.com/Lastorder-DC/rhymix.git
synced 2026-01-03 16:51:40 +09:00
247 lines
6.5 KiB
PHP
247 lines
6.5 KiB
PHP
<?php
|
|
|
|
namespace Rhymix\Framework;
|
|
|
|
/**
|
|
* The datetime class.
|
|
*/
|
|
class DateTime
|
|
{
|
|
/**
|
|
* Time zone objects and settings are cached here.
|
|
*/
|
|
protected static $_timezones = array();
|
|
|
|
/**
|
|
* Define the relative format constant.
|
|
*/
|
|
public const FORMAT_RELATIVE = 'relative';
|
|
|
|
/**
|
|
* Format a Unix timestamp using the internal timezone.
|
|
*
|
|
* @param string $format Format used in PHP date() function
|
|
* @param int $timestamp Unix timestamp (optional, default is now)
|
|
* @return string
|
|
*/
|
|
public static function formatTimestamp(string $format, ?int $timestamp = null): string
|
|
{
|
|
if ($format === self::FORMAT_RELATIVE)
|
|
{
|
|
return self::getRelativeTimestamp($timestamp ?? time());
|
|
}
|
|
|
|
$offset = Config::get('locale.internal_timezone') ?: date('Z', $timestamp ?? time());
|
|
return gmdate($format, ($timestamp ?? time()) + $offset);
|
|
}
|
|
|
|
/**
|
|
* Format a Unix timestamp for the current user's timezone.
|
|
*
|
|
* @param string $format Format used in PHP date() function
|
|
* @param int $timestamp Unix timestamp (optional, default is now)
|
|
* @return string
|
|
*/
|
|
public static function formatTimestampForCurrentUser(string $format, ?int $timestamp = null): string
|
|
{
|
|
if ($format === self::FORMAT_RELATIVE)
|
|
{
|
|
return self::getRelativeTimestamp($timestamp ?? time());
|
|
}
|
|
|
|
$timezone = self::getTimezoneForCurrentUser();
|
|
if (!isset(self::$_timezones[$timezone]))
|
|
{
|
|
self::$_timezones[$timezone] = new \DateTimeZone($timezone);
|
|
}
|
|
$datetime = new \DateTime();
|
|
$datetime->setTimestamp($timestamp ?? time());
|
|
$datetime->setTimezone(self::$_timezones[$timezone]);
|
|
return $datetime->format($format);
|
|
}
|
|
|
|
/**
|
|
* Get the current user's timezone.
|
|
*
|
|
* @return string
|
|
*/
|
|
public static function getTimezoneForCurrentUser(): string
|
|
{
|
|
if (isset($_SESSION['RHYMIX']['timezone']) && $_SESSION['RHYMIX']['timezone'])
|
|
{
|
|
return $_SESSION['RHYMIX']['timezone'];
|
|
}
|
|
elseif ($default = \Context::get('_default_timezone'))
|
|
{
|
|
return (string)$default;
|
|
}
|
|
elseif ($default = Config::get('locale.default_timezone'))
|
|
{
|
|
return (string)$default;
|
|
}
|
|
else
|
|
{
|
|
return @date_default_timezone_get();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Get the list of time zones supported on this server.
|
|
*
|
|
* @return array
|
|
*/
|
|
public static function getTimezoneList(): array
|
|
{
|
|
$result = array();
|
|
$tzlist = \DateTimeZone::listIdentifiers();
|
|
foreach ($tzlist as $tzid)
|
|
{
|
|
if (!preg_match('/^(?:A|Europe|Indian|Pacific)/', $tzid)) continue;
|
|
$name = str_replace('_', ' ', $tzid);
|
|
$datetime = new \DateTime('now', new \DateTimeZone($tzid));
|
|
$offset = $datetime->getOffset();
|
|
$offset = ($offset >= 0 ? '+' : '-') . sprintf('%02d', floor(abs($offset) / 3600)) . ':' . sprintf('%02d', (abs($offset) % 3600) / 60);
|
|
unset($datetime);
|
|
$result[$tzid] = "$name ($offset)";
|
|
}
|
|
asort($result);
|
|
$result['Etc/UTC'] = 'GMT/UTC (+00:00)';
|
|
return $result;
|
|
}
|
|
|
|
/**
|
|
* Get the absolute (UTC) offset of a timezone.
|
|
*
|
|
* @param string $timezone Timezone identifier, e.g. Asia/Seoul
|
|
* @param int $timestamp Unix timestamp (optional, default is now)
|
|
* @return int
|
|
*/
|
|
public static function getTimezoneOffset(string $timezone, ?int $timestamp = null): int
|
|
{
|
|
if (!isset(self::$_timezones[$timezone]))
|
|
{
|
|
self::$_timezones[$timezone] = new \DateTimeZone($timezone);
|
|
}
|
|
$datetime = new \DateTime();
|
|
$datetime->setTimestamp($timestamp ?? time());
|
|
$datetime->setTimezone(self::$_timezones[$timezone]);
|
|
return $datetime->getOffset();
|
|
}
|
|
|
|
/**
|
|
* Get the relative offset between a timezone and Rhymix's internal timezone.
|
|
*
|
|
* @param string $timezone Timezone identifier, e.g. Asia/Seoul
|
|
* @param int $timestamp Unix timestamp (optional, default is now)
|
|
* @return int
|
|
*/
|
|
public static function getTimezoneOffsetFromInternal(string $timezone, ?int $timestamp = null): int
|
|
{
|
|
return self::getTimezoneOffset($timezone, $timestamp ?? time()) - Config::get('locale.internal_timezone');
|
|
}
|
|
|
|
/**
|
|
* Get the absolute (UTC) offset of a timezone written in XE legacy format ('+0900').
|
|
*
|
|
* @param string $timezone
|
|
* @return int
|
|
*/
|
|
public static function getTimezoneOffsetByLegacyFormat(string $timezone): int
|
|
{
|
|
$multiplier = ($timezone[0] === '-') ? -60 : 60;
|
|
$timezone = preg_replace('/[^0-9]/', '', $timezone);
|
|
list($hours, $minutes) = str_split($timezone, 2);
|
|
return (((int)$hours * 60) + (int)$minutes) * $multiplier;
|
|
}
|
|
|
|
/**
|
|
* Get a PHP time zone by UTC offset.
|
|
*
|
|
* Time zones with both (a) fractional offsets and (b) daylight saving time
|
|
* (such as Iran's +03:30/+04:30) cannot be converted in this way.
|
|
* However, if Rhymix is installed for the first time in such a time zone,
|
|
* the internal time zone will be automatically set to UTC,
|
|
* so this should never be a problem in practice.
|
|
*
|
|
* @param int $offset
|
|
* @return string
|
|
*/
|
|
public static function getTimezoneNameByOffset(int $offset): string
|
|
{
|
|
switch ($offset)
|
|
{
|
|
case 0: return 'Etc/UTC';
|
|
case -34200: return 'Pacific/Marquesas'; // -09:30
|
|
case -16200: return 'America/Caracas'; // -04:30
|
|
case 16200: return 'Asia/Kabul'; // +04:30
|
|
case 19800: return 'Asia/Kolkata'; // +05:30
|
|
case 20700: return 'Asia/Kathmandu'; // +05:45
|
|
case 23400: return 'Asia/Rangoon'; // +06:30
|
|
case 30600: return 'Asia/Pyongyang'; // +08:30
|
|
case 31500: return 'Australia/Eucla'; // +08:45
|
|
case 34200: return 'Australia/Darwin'; // +09:30
|
|
default: return 'Etc/GMT' . ($offset > 0 ? '-' : '+') . intval(abs($offset / 3600));
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Get a relative timestamp (3 hours ago, etc.)
|
|
*
|
|
* @param int $timestamp
|
|
* @return string
|
|
*/
|
|
public static function getRelativeTimestamp(?int $timestamp = null): string
|
|
{
|
|
$diff = \RX_TIME - intval($timestamp ?? time());
|
|
$langs = lang('common.time_gap');
|
|
|
|
if ($diff < 3)
|
|
{
|
|
return $langs['now'];
|
|
}
|
|
if ($diff < 60)
|
|
{
|
|
return sprintf($langs['secs'], $diff);
|
|
}
|
|
if ($diff < 60 * 2)
|
|
{
|
|
return sprintf($langs['min'], 1);
|
|
}
|
|
if ($diff < 3600)
|
|
{
|
|
return sprintf($langs['mins'], $diff / 60);
|
|
}
|
|
if ($diff < 3600 * 2)
|
|
{
|
|
return sprintf($langs['hour'], 1);
|
|
}
|
|
if ($diff < 86400)
|
|
{
|
|
return sprintf($langs['hours'], $diff / 3600);
|
|
}
|
|
if ($diff < 86400 * 2)
|
|
{
|
|
return sprintf($langs['day'], 1);
|
|
}
|
|
if ($diff < 86400 * 32)
|
|
{
|
|
return sprintf($langs['days'], $diff / 86400);
|
|
}
|
|
if ($diff < 86400 * 60)
|
|
{
|
|
return sprintf($langs['month'], 1);
|
|
}
|
|
if ($diff < 86400 * 366)
|
|
{
|
|
return sprintf($langs['months'], $diff / (86400 * 30.5));
|
|
}
|
|
if ($diff < 86400 * 732)
|
|
{
|
|
return sprintf($langs['year'], 1);
|
|
}
|
|
else
|
|
{
|
|
return sprintf($langs['years'], $diff / (86400 * 365.25));
|
|
}
|
|
}
|
|
}
|