diff --git a/GameEngine/Generator.php b/GameEngine/Generator.php index 25341ccb..2f54fe7d 100755 --- a/GameEngine/Generator.php +++ b/GameEngine/Generator.php @@ -136,45 +136,149 @@ class MyGenerator } /** - * Format timestamp into readable date/time + * Resolve a player's "timezone" preference (issue #198) to a DateTimeZone. + * + * The preference form exposes two kinds of values: + * - 8 named, DST-aware regions (Europe, UK, Turkey, Kolkata, Bangkok, + * New York, Chicago, New Zealand) stored as their legacy magic ids; + * - fixed UTC offsets (general zones): 0..11 => UTC+1..UTC+12, + * 12..22 => UTC-11..UTC-1, 23 => UTC. + * Falls back to the server's default timezone when the value is unknown. + * + * @param int|null $tz Stored timezone preference value (null = server time). + * @return DateTimeZone + */ + private function resolveUserTimeZone($tz) + { + if ($tz === null) { + return new DateTimeZone(date_default_timezone_get()); + } + + $tz = (int) $tz; + + $named = [ + 495 => 'Europe/Berlin', + 99 => 'Europe/London', + 492 => 'Europe/Istanbul', + 328 => 'Asia/Kolkata', + 345 => 'Asia/Bangkok', + 257 => 'America/New_York', + 189 => 'America/Chicago', + 474 => 'Pacific/Auckland', + ]; + + try { + if (isset($named[$tz])) { + return new DateTimeZone($named[$tz]); + } + + if ($tz === 23) { + $offset = 0; + } elseif ($tz >= 0 && $tz <= 11) { + $offset = $tz + 1; + } elseif ($tz >= 12 && $tz <= 22) { + $offset = $tz - 23; + } else { + $offset = 0; + } + + $sign = $offset >= 0 ? '+' : '-'; + return new DateTimeZone(sprintf('%s%02d:00', $sign, abs($offset))); + } catch (\Exception $e) { + return new DateTimeZone(date_default_timezone_get()); + } + } + + /** + * Format an absolute timestamp into a readable date/time, honouring the + * current player's time preference (issue #198): timezone conversion + + * date layout / 12h-24h clock derived from the "tformat" setting. + * + * tformat 0 => EU dd.mm.yy 24h (legacy default, unchanged) + * tformat 1 => US mm/dd/yy 12h + * tformat 2 => UK dd/mm/yy 12h + * tformat 3 => ISO yy/mm/dd 24h + * + * When no player session is available (e.g. admin / pre-login) it falls + * back to the server timezone and the EU layout, i.e. the previous output. + * The "today"/"yesterday" sentinels are kept verbatim (callers compare them). + * + * @param int $time Unix timestamp. + * @param int $pref Pass 9 to get the time-of-day string only. + * @return array|string [$day, $time] normally, or the time string when $pref == 9. */ public function procMtime($time, $pref = 3) { - $time = (int) $time; - $time += 0; // placeholder for timezone adjustments + global $session; - $today = date('d', time()) - 1; + $time = (int) $time; - if (date('Ymd', time()) == date('Ymd', $time)) { - $day = "today"; - } elseif ($today == date('d', $time)) { - $day = "yesterday"; - } else { - switch ($pref) { - case 1: - $day = date("m/j/y", $time); - break; - case 2: - $day = date("j/m/y", $time); - break; - case 3: - $day = date("j.m.y", $time); - break; - default: - $day = date("y/m/j", $time); - break; - } + $tzPref = (isset($session) && isset($session->userinfo['timezone'])) + ? $session->userinfo['timezone'] : null; + $tformat = (isset($session) && isset($session->userinfo['tformat'])) + ? (int) $session->userinfo['tformat'] : 0; + + $zone = $this->resolveUserTimeZone($tzPref); + + $dt = new DateTime('@' . $time); + $dt->setTimezone($zone); + $now = new DateTime('now', $zone); + + // date layout + clock (12h/24h) per the tformat preference + switch ($tformat) { + case 1: $dateFmt = "m/d/y"; $timeFmt = "h:i:s A"; break; + case 2: $dateFmt = "d/m/y"; $timeFmt = "h:i:s A"; break; + case 3: $dateFmt = "y/m/d"; $timeFmt = "H:i:s"; break; + default: $dateFmt = "j.m.y"; $timeFmt = "H:i:s"; break; // legacy EU output, unchanged } - $new = date("H:i:s", $time); - + // Time-only mode (9) feeds the live JS clock counters (unx.js ob()/rb()), + // which parse "H:i:s" by splitting on ":" — keep 24h here regardless of + // the 12h/24h tformat, while still honouring the timezone conversion. if ($pref == 9) { - return $new; + return $dt->format("H:i:s"); + } + + $new = $dt->format($timeFmt); + + $yesterday = (clone $now)->modify('-1 day'); + + if ($dt->format('Ymd') == $now->format('Ymd')) { + $day = "today"; + } elseif ($dt->format('Ymd') == $yesterday->format('Ymd')) { + $day = "yesterday"; + } else { + $day = $dt->format($dateFmt); } return [$day, $new]; } + /** + * Resolve the current player's timezone preference (issue #198), shared by + * the "local time" header clock helpers below. + */ + private function currentPlayerZone() + { + global $session; + + $tzPref = (isset($session) && isset($session->userinfo['timezone'])) + ? $session->userinfo['timezone'] : null; + + return $this->resolveUserTimeZone($tzPref); + } + + /** + * Current UTC offset (in seconds, DST-aware) of the player's timezone. + * Feeds the live "local time" clock in the page header (issue #198). + * + * @return int + */ + public function userTimeZoneOffset() + { + return (new DateTime('now', $this->currentPlayerZone()))->getOffset(); + } + /** * Convert map coordinates to base ID */ diff --git a/GameEngine/Lang/en.php b/GameEngine/Lang/en.php index 7d4dc61b..c7386ab3 100755 --- a/GameEngine/Lang/en.php +++ b/GameEngine/Lang/en.php @@ -152,6 +152,7 @@ tz_def('HI', 'HI'); tz_def('P_IN', 'in'); tz_def('MS', 'ms'); tz_def('SERVER_TIME', 'Server time:'); +tz_def('LOCAL_TIME', 'Local time:'); tz_def('REMAINING_GOLD', 'Remaining gold'); // HEADER && MENU && Messages && Reports diff --git a/GameEngine/Lang/fr.php b/GameEngine/Lang/fr.php index 31ce8fe8..b8560dd1 100644 --- a/GameEngine/Lang/fr.php +++ b/GameEngine/Lang/fr.php @@ -149,6 +149,7 @@ define('HI', 'Bonjour'); define('P_IN', 'dans'); define('MS', 'ms'); define('SERVER_TIME', 'Heure du serveur :'); +define('LOCAL_TIME', 'Heure locale :'); define('REMAINING_GOLD', 'Or restant'); // HEADER && MENU && Messages && Reports diff --git a/GameEngine/Lang/ro.php b/GameEngine/Lang/ro.php index 04e68b32..eedd5c0a 100644 --- a/GameEngine/Lang/ro.php +++ b/GameEngine/Lang/ro.php @@ -149,6 +149,7 @@ define('HI', 'Salut'); define('P_IN', 'în'); define('MS', 'ms'); define('SERVER_TIME', 'Ora serverului:'); +define('LOCAL_TIME', 'Ora locală:'); define('REMAINING_GOLD', 'Aur rămas'); // HEADER && MENU && Messages && Reports diff --git a/Templates/Alliance/attack-filtered.tpl b/Templates/Alliance/attack-filtered.tpl index b9a80c4b..c7ddf11d 100644 --- a/Templates/Alliance/attack-filtered.tpl +++ b/Templates/Alliance/attack-filtered.tpl @@ -140,7 +140,7 @@ if (!$sql || mysqli_num_rows($sql) == 0) { $outputList .= "
';
}
$date = $generator->procMtime($row['time']);
- echo '