mirror of
https://github.com/zulip/zulip.git
synced 2025-10-25 09:03:57 +00:00
settings: Show UTC offsets in timezone dropdown.
This improves usability by helping users quickly recognize timezones with their offsets. Fixes #20988.
This commit is contained in:
@@ -3,6 +3,7 @@ import json
|
|||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
import zoneinfo
|
import zoneinfo
|
||||||
|
from datetime import datetime, timedelta
|
||||||
|
|
||||||
ZULIP_PATH = os.path.join(os.path.dirname(os.path.abspath(__file__)), "../../")
|
ZULIP_PATH = os.path.join(os.path.dirname(os.path.abspath(__file__)), "../../")
|
||||||
sys.path.insert(0, ZULIP_PATH)
|
sys.path.insert(0, ZULIP_PATH)
|
||||||
@@ -11,14 +12,35 @@ from zerver.lib.timezone import get_canonical_timezone_map
|
|||||||
|
|
||||||
OUT_PATH = os.path.join(ZULIP_PATH, "web", "generated", "timezones.json")
|
OUT_PATH = os.path.join(ZULIP_PATH, "web", "generated", "timezones.json")
|
||||||
|
|
||||||
|
|
||||||
|
def get_utc_offset(tz_name: str) -> str:
|
||||||
|
"""Get UTC offset for a timezone in the format UTC(+HH:MM)."""
|
||||||
|
try:
|
||||||
|
now = datetime.now(zoneinfo.ZoneInfo(tz_name))
|
||||||
|
offset: timedelta | None = now.utcoffset()
|
||||||
|
|
||||||
|
if offset is None:
|
||||||
|
return "UTC(+00:00)"
|
||||||
|
|
||||||
|
offset_seconds = offset.total_seconds()
|
||||||
|
hours, remainder = divmod(offset_seconds, 3600)
|
||||||
|
minutes = remainder // 60
|
||||||
|
if minutes == 0:
|
||||||
|
return f"UTC{int(hours):+d}"
|
||||||
|
return f"UTC{int(hours):+d}:{int(minutes):02d}"
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
print(f"Error processing {tz_name}: {e}")
|
||||||
|
return "UTC(?)"
|
||||||
|
|
||||||
|
|
||||||
|
timezones = sorted(
|
||||||
|
zoneinfo.available_timezones() - {"Factory", "localtime"} - set(get_canonical_timezone_map())
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
timezone_data = [{"name": tz, "utc_offset": get_utc_offset(tz)} for tz in timezones]
|
||||||
|
|
||||||
|
|
||||||
with open(OUT_PATH, "w") as f:
|
with open(OUT_PATH, "w") as f:
|
||||||
json.dump(
|
json.dump({"timezones": timezone_data}, f)
|
||||||
{
|
|
||||||
"timezones": sorted(
|
|
||||||
zoneinfo.available_timezones()
|
|
||||||
- {"Factory", "localtime"}
|
|
||||||
- set(get_canonical_timezone_map())
|
|
||||||
)
|
|
||||||
},
|
|
||||||
f,
|
|
||||||
)
|
|
||||||
|
|||||||
@@ -49,4 +49,4 @@ API_FEATURE_LEVEL = 371 # Last bumped for Zulip 10.0 release.
|
|||||||
# historical commits sharing the same major version, in which case a
|
# historical commits sharing the same major version, in which case a
|
||||||
# minor version bump suffices.
|
# minor version bump suffices.
|
||||||
|
|
||||||
PROVISION_VERSION = (321, 1) # bumped 2025-03-26 to generate static/generated/integrations files.
|
PROVISION_VERSION = (322, 0) # bumped 2025-03-26 for updated build_timezone_values.
|
||||||
|
|||||||
@@ -27,7 +27,8 @@
|
|||||||
{{/unless}}
|
{{/unless}}
|
||||||
|
|
||||||
{{#each timezones}}
|
{{#each timezones}}
|
||||||
<option value="{{ this }}">{{ this }}</option>
|
<option value="{{ this.name }}">{{ this.name }} ({{ this.utc_offset }})</option>
|
||||||
|
|
||||||
{{/each}}
|
{{/each}}
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Reference in New Issue
Block a user