53 public static function get() :
string{
54 $tz = ini_get(
'date.timezone');
61 public static function init() :
void{
62 $timezone =
Utils::assumeNotFalse(ini_get(
"date.timezone"),
"date.timezone should always be set in ini");
68 if(!str_contains($timezone,
"/")){
69 $default_timezone = timezone_name_from_abbr($timezone);
70 if($default_timezone !==
false){
71 ini_set(
"date.timezone", $default_timezone);
72 date_default_timezone_set($default_timezone);
77 \GlobalLogger::get()->warning(
"Timezone \"$timezone\" could not be parsed as a valid timezone from php.ini, falling back to auto-detection");
79 date_default_timezone_set($timezone);
84 if(($timezone = self::detectSystemTimezone()) !==
false && date_default_timezone_set($timezone)){
87 ini_set(
"date.timezone", $timezone);
92 && is_array($ip_geolocation_data = json_decode($response->getBody(),
true))
93 && isset($ip_geolocation_data[
'status'])
94 && $ip_geolocation_data[
'status'] !==
'fail'
95 && is_string($ip_geolocation_data[
'timezone'])
96 && date_default_timezone_set($ip_geolocation_data[
'timezone'])
99 ini_set(
"date.timezone", $ip_geolocation_data[
'timezone']);
103 ini_set(
"date.timezone",
"UTC");
104 date_default_timezone_set(
"UTC");
105 \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.");
108 public static function detectSystemTimezone() :
string|
false{
110 case Utils::OS_WINDOWS:
111 $keyPath =
'HKLM\\SYSTEM\\CurrentControlSet\\Control\\TimeZoneInformation';
146 exec(
"reg query " . escapeshellarg($keyPath), $output);
148 foreach($output as $line){
149 if(preg_match(
'/ActiveTimeBias\s+REG_DWORD\s+0x([0-9a-fA-F]+)/', $line, $matches) > 0){
150 $offsetMinutes = Binary::signInt((
int) hexdec(trim($matches[1])));
152 if($offsetMinutes === 0){
156 $sign = $offsetMinutes <= 0 ?
'+' :
'-';
157 $absMinutes = abs($offsetMinutes);
158 $hours = floor($absMinutes / 60);
159 $minutes = $absMinutes % 60;
168 return self::parseOffset($offset);
172 case Utils::OS_LINUX:
174 $data = @file_get_contents(
'/etc/timezone');
180 $data = @parse_ini_file(
'/etc/sysconfig/clock');
181 if($data !==
false && isset($data[
'ZONE']) && is_string($data[
'ZONE'])){
182 return trim($data[
'ZONE']);
187 $offset = trim(exec(
'date +%:z'));
189 if($offset ===
"+00:00"){
193 return self::parseOffset($offset);
194 case Utils::OS_MACOS:
195 $filename = @readlink(
'/etc/localtime');
196 if($filename !==
false && str_starts_with($filename,
'/usr/share/zoneinfo/')){
197 $timezone = substr($filename, 20);
198 return trim($timezone);
210 private static function parseOffset(
string $offset) :
string|
false{
212 if(str_starts_with($offset,
'-')){
213 $negative_offset =
true;
214 $offset = str_replace(
'-',
'', $offset);
216 if(str_starts_with($offset,
'+')){
217 $negative_offset =
false;
218 $offset = str_replace(
'+',
'', $offset);
224 $parsed = date_parse($offset);
225 $offset = $parsed[
'hour'] * 3600 + $parsed[
'minute'] * 60 + $parsed[
'second'];
228 if($negative_offset){
229 $offset = -abs($offset);
235 foreach(timezone_abbreviations_list() as $zones){
236 foreach($zones as $timezone){
237 if($timezone[
'timezone_id'] !==
null && $timezone[
'offset'] === $offset){
238 return $timezone[
'timezone_id'];