22declare(strict_types=1);
27use
function date_default_timezone_set;
28use
function date_parse;
30use
function file_get_contents;
35use
function is_string;
36use
function json_decode;
37use
function parse_ini_file;
38use
function preg_match;
40use
function str_contains;
41use
function str_replace;
42use
function str_starts_with;
44use
function timezone_abbreviations_list;
45use
function timezone_name_from_abbr;
50 public static function get() :
string{
51 $tz = ini_get(
'date.timezone');
58 public static function init() :
void{
59 $timezone =
Utils::assumeNotFalse(ini_get(
"date.timezone"),
"date.timezone should always be set in ini");
65 if(!str_contains($timezone,
"/")){
66 $default_timezone = timezone_name_from_abbr($timezone);
67 if($default_timezone !==
false){
68 ini_set(
"date.timezone", $default_timezone);
69 date_default_timezone_set($default_timezone);
74 \GlobalLogger::get()->warning(
"Timezone \"$timezone\" could not be parsed as a valid timezone from php.ini, falling back to auto-detection");
76 date_default_timezone_set($timezone);
81 if(($timezone = self::detectSystemTimezone()) !==
false && date_default_timezone_set($timezone)){
84 ini_set(
"date.timezone", $timezone);
89 && is_array($ip_geolocation_data = json_decode($response->getBody(),
true))
90 && isset($ip_geolocation_data[
'status'])
91 && $ip_geolocation_data[
'status'] !==
'fail'
92 && is_string($ip_geolocation_data[
'timezone'])
93 && date_default_timezone_set($ip_geolocation_data[
'timezone'])
96 ini_set(
"date.timezone", $ip_geolocation_data[
'timezone']);
100 ini_set(
"date.timezone",
"UTC");
101 date_default_timezone_set(
"UTC");
102 \GlobalLogger::get()->warning(
"Timezone could not be automatically determined or was set to an invalid value. An incorrect timezone will result in incorrect timestamps on console logs. It has been set to \"UTC\" by default. You can change it on the php.ini file.");
105 public static function detectSystemTimezone() :
string|
false{
107 case Utils::OS_WINDOWS:
108 $regex =
'/(UTC)(\+*\-*\d*\d*\:*\d*\d*)/';
124 exec(
"wmic timezone get Caption", $output);
126 $string = trim(implode(
"\n", $output));
129 preg_match($regex, $string, $matches);
131 if(!isset($matches[2])){
135 $offset = $matches[2];
141 return self::parseOffset($offset);
142 case Utils::OS_LINUX:
144 $data = @file_get_contents(
'/etc/timezone');
150 $data = @parse_ini_file(
'/etc/sysconfig/clock');
151 if($data !==
false && isset($data[
'ZONE']) && is_string($data[
'ZONE'])){
152 return trim($data[
'ZONE']);
157 $offset = trim(exec(
'date +%:z'));
159 if($offset ==
"+00:00"){
163 return self::parseOffset($offset);
164 case Utils::OS_MACOS:
165 $filename = @readlink(
'/etc/localtime');
166 if($filename !==
false && str_starts_with($filename,
'/usr/share/zoneinfo/')){
167 $timezone = substr($filename, 20);
168 return trim($timezone);
180 private static function parseOffset(
string $offset) :
string|
false{
182 if(str_starts_with($offset,
'-')){
183 $negative_offset =
true;
184 $offset = str_replace(
'-',
'', $offset);
186 if(str_starts_with($offset,
'+')){
187 $negative_offset =
false;
188 $offset = str_replace(
'+',
'', $offset);
194 $parsed = date_parse($offset);
195 $offset = $parsed[
'hour'] * 3600 + $parsed[
'minute'] * 60 + $parsed[
'second'];
198 if($negative_offset ==
true){
199 $offset = -abs($offset);
205 foreach(timezone_abbreviations_list() as $zones){
206 foreach($zones as $timezone){
207 if($timezone[
'timezone_id'] !==
null && $timezone[
'offset'] == $offset){
208 return $timezone[
'timezone_id'];
static getURL(string $page, int $timeout=10, array $extraHeaders=[], &$err=null)
static assumeNotFalse(mixed $value, \Closure|string $context="This should never be false")
static getOS(bool $recalculate=false)