Geograpy: Fix formatting of negative non-integral offsets (and improve others)

This commit is contained in:
Valentin Lorentz 2022-04-04 22:06:19 +02:00
parent 088d0f54dd
commit 4f3d6fc39f
2 changed files with 73 additions and 19 deletions

View File

@ -110,6 +110,21 @@ class Geography(callbacks.Plugin):
_("Could not find the timezone of this location."), Raise=True
)
def _format_utc_offset(self, offset_seconds):
sign = "+" if offset_seconds >= 0 else "-"
# Make modulos work as expected
offset_seconds = abs(offset_seconds)
(offset_minutes, offset_seconds) = divmod(offset_seconds, 60)
(offset_hours, offset_minutes) = divmod(offset_minutes, 60)
offset = f"{offset_hours}:{offset_minutes:02}:{offset_seconds:02}"
# hide seconds and minutes if they are zero
offset = re.sub("(:00)+$", "", offset)
return f"UTC{sign}{offset}"
@wrap(["text"])
def timezone(self, irc, msg, args, query):
"""<location name to search>
@ -134,33 +149,28 @@ class Geography(callbacks.Plugin):
if timezone is None:
continue
offset = str(datetime.datetime.now(tz=timezone).utcoffset())
if not offset.startswith("-"):
offset = "+" + offset
# hide seconds and minutes if they are zero
offset = re.sub("(:00)+$", "", offset)
offset_seconds = int(
datetime.datetime.now(tz=timezone).utcoffset().total_seconds())
offset = self._format_utc_offset(offset_seconds)
# Extract a human-friendly name, depending on the type of
# the timezone object:
if hasattr(timezone, "key"):
# instance of zoneinfo.ZoneInfo
irc.reply(format("%s (currently UTC%s)", timezone.key, offset))
irc.reply(format("%s (currently %s)", timezone.key, offset))
return
elif hasattr(timezone, "zone"):
# instance of pytz.timezone
irc.reply(format("%s (currently UTC%s)", timezone.zone, offset))
irc.reply(format("%s (currently %s)", timezone.zone, offset))
return
else:
# probably datetime.timezone built from a constant offset
try:
offset = timezone.utcoffset(now).seconds
offset = int(timezone.utcoffset(now).total_seconds())
except NotImplementedError:
continue
hours = int(offset / 3600)
minutes = int(offset / 60 % 60)
irc.reply("UTC+%0.2i:%0.2i" % (hours, minutes))
irc.reply(self._format_utc_offset(offset))
return
irc.error(

View File

@ -68,41 +68,85 @@ class GeographyTimezoneTestCase(PluginTestCase):
@mock
def testTimezonePytz(self):
tz = pytz.timezone("Europe/Paris")
with patch.object(wikidata, "timezone_from_uri", return_value=tz):
self.assertRegexp(
"timezone Foo Bar", r"Europe/Paris \(currently UTC\+[12]\)"
)
tz = pytz.timezone("America/New_York")
with patch.object(wikidata, "timezone_from_uri", return_value=tz):
self.assertRegexp(
"timezone New York", r"America/New_York \(currently UTC-[45]\)"
)
tz = pytz.timezone("Canada/Newfoundland")
with patch.object(wikidata, "timezone_from_uri", return_value=tz):
self.assertRegexp(
"timezone Newfoundland",
r"Canada/Newfoundland \(currently UTC-[23]:30\)"
)
tz = pytz.timezone("Asia/Kolkata")
with patch.object(wikidata, "timezone_from_uri", return_value=tz):
self.assertRegexp(
"timezone Delhi", r"Asia/Kolkata \(currently UTC\+5:30\)"
)
@skipIf(not zoneinfo, "Python is older than 3.9")
@mock
def testTimezoneZoneinfo(self):
tz = zoneinfo.ZoneInfo("Europe/Paris")
with patch.object(wikidata, "timezone_from_uri", return_value=tz):
self.assertRegexp(
"timezone Foo Bar", r"Europe/Paris \(currently UTC\+[12]\)"
)
tz = zoneinfo.ZoneInfo("America/New_York")
with patch.object(wikidata, "timezone_from_uri", return_value=tz):
self.assertRegexp(
"timezone New York", r"America/New_York \(currently UTC-[45]\)"
)
tz = zoneinfo.ZoneInfo("Canada/Newfoundland")
with patch.object(wikidata, "timezone_from_uri", return_value=tz):
self.assertRegexp(
"timezone Newfoundland",
r"Canada/Newfoundland \(currently UTC-[23]:30\)"
)
tz = zoneinfo.ZoneInfo("Asia/Kolkata")
with patch.object(wikidata, "timezone_from_uri", return_value=tz):
self.assertRegexp(
"timezone Delhi", r"Asia/Kolkata \(currently UTC\+5:30\)"
)
@skipIf(not zoneinfo, "Python is older than 3.9")
@mock
def testTimezoneAbsolute(self):
tz = datetime.timezone(datetime.timedelta(hours=4))
with patch.object(wikidata, "timezone_from_uri", return_value=tz):
self.assertResponse("timezone Foo Bar", "UTC+04:00")
self.assertResponse("timezone Foo Bar", "UTC+4")
tz = datetime.timezone(datetime.timedelta(hours=4, minutes=30))
with patch.object(wikidata, "timezone_from_uri", return_value=tz):
self.assertResponse("timezone Foo Bar", "UTC+04:30")
self.assertResponse("timezone Foo Bar", "UTC+4:30")
tz = datetime.timezone(datetime.timedelta(hours=-4, minutes=30))
with patch.object(wikidata, "timezone_from_uri", return_value=tz):
self.assertResponse("timezone Foo Bar", "UTC-3:30")
@skipIf(not network, "Network test")
def testTimezoneIntegration(self):
self.assertRegexp(
"timezone Metz, France", r"Europe/Paris \(currently UTC\+[12]\)"
)
self.assertResponse("timezone Saint-Denis, La Réunion", "UTC+04:00")
self.assertResponse("timezone Saint-Denis, La Réunion", "UTC+4")
self.assertRegexp(
"timezone Delhi", r"Asia/Kolkata \(currently UTC\+5:30\)"
)
self.assertRegexp(
"timezone Newfoundland", r"UTC-[23]:30"
)
class GeographyLocaltimeTestCase(PluginTestCase):