Fixed TimePlugin timezone issue

The existing time plugin had a hard coded PDT for pacific timezone,
when it wasn't.   This patch adds some real timezone conversion from
utc to the tz of the running aprsd server.   This will eventually allow
us to use either the tz of the running aprsd and/or the tz of the
calling callsign if we can just get the tz string from the location
beacon of the caller's callsign.
This commit is contained in:
Hemna 2021-01-19 11:19:53 -05:00
parent ca05676c98
commit 9f38fd179e
5 changed files with 51 additions and 20 deletions

View File

@ -2,6 +2,7 @@ import logging
import time
from aprsd import fuzzyclock, plugin
import pytz
LOG = logging.getLogger("APRSD")
@ -13,16 +14,34 @@ class TimePlugin(plugin.APRSDPluginBase):
command_regex = "^[tT]"
command_name = "time"
def _get_local_tz(self):
return pytz.timezone(time.strftime("%Z"))
def _get_utcnow(self):
return pytz.datetime.datetime.utcnow()
def command(self, fromcall, message, ack):
LOG.info("TIME COMMAND")
stm = time.localtime()
h = stm.tm_hour
m = stm.tm_min
cur_time = fuzzyclock.fuzzy(h, m, 1)
reply = "{} ({}:{} PDT) ({})".format(
# So we can mock this in unit tests
localzone = self._get_local_tz()
# This is inefficient for now, but this enables
# us to add the ability to provide time in the TZ
# of the caller, if we can get the TZ from their callsign location
# This also accounts for running aprsd in different timezones
utcnow = self._get_utcnow()
gmt_t = pytz.utc.localize(utcnow)
local_t = gmt_t.astimezone(localzone)
local_short_str = local_t.strftime("%H:%M %Z")
local_hour = local_t.strftime("%H")
local_min = local_t.strftime("%M")
cur_time = fuzzyclock.fuzzy(int(local_hour), int(local_min), 1)
reply = "{} ({}) ({})".format(
cur_time,
str(h),
str(m).rjust(2, "0"),
local_short_str,
message.rstrip(),
)
return reply

View File

@ -160,7 +160,7 @@ typing-extensions==3.7.4.3
# mypy
urllib3==1.26.2
# via requests
virtualenv==20.2.2
virtualenv==20.4.0
# via tox
webencodings==0.5.1
# via bleach

View File

@ -10,3 +10,4 @@ thesmuggler
aprslib
py3-validate-email
pre-commit
pytz

View File

@ -28,13 +28,13 @@ filelock==3.0.12
# via
# py3-validate-email
# virtualenv
identify==1.5.11
identify==1.5.13
# via pre-commit
idna==2.10
# via
# py3-validate-email
# requests
imapclient==2.1.0
imapclient==2.2.0
# via -r requirements.in
jinja2==2.11.2
# via click-completion
@ -50,6 +50,8 @@ pre-commit==2.9.3
# via -r requirements.in
py3-validate-email==0.2.12
# via -r requirements.in
pytz==2020.5
# via -r requirements.in
pyyaml==5.3.1
# via
# -r requirements.in
@ -70,5 +72,5 @@ toml==0.10.2
# via pre-commit
urllib3==1.26.2
# via requests
virtualenv==20.2.2
virtualenv==20.4.0
# via pre-commit

View File

@ -9,6 +9,7 @@ from aprsd.plugins import ping as ping_plugin
from aprsd.plugins import query as query_plugin
from aprsd.plugins import time as time_plugin
from aprsd.plugins import version as version_plugin
import pytz
class TestPlugin(unittest.TestCase):
@ -68,13 +69,21 @@ class TestPlugin(unittest.TestCase):
actual = query.run(self.fromcall, message, self.ack)
mock_restart.assert_called_once()
@mock.patch("time.localtime")
def test_time(self, mock_time):
@mock.patch("aprsd.plugins.time.TimePlugin._get_local_tz")
@mock.patch("aprsd.plugins.time.TimePlugin._get_utcnow")
def test_time(self, mock_utcnow, mock_localtz):
utcnow = pytz.datetime.datetime.utcnow()
mock_utcnow.return_value = utcnow
tz = pytz.timezone("US/Pacific")
mock_localtz.return_value = tz
gmt_t = pytz.utc.localize(utcnow)
local_t = gmt_t.astimezone(tz)
fake_time = mock.MagicMock()
h = fake_time.tm_hour = 16
m = fake_time.tm_min = 12
fake_time.tm_sec = 55
mock_time.return_value = fake_time
h = int(local_t.strftime("%H"))
m = int(local_t.strftime("%M"))
fake_time.tm_sec = 13
time = time_plugin.TimePlugin(self.config)
fromcall = "KFART"
@ -87,10 +96,10 @@ class TestPlugin(unittest.TestCase):
cur_time = fuzzy(h, m, 1)
message = "time"
expected = "{} ({}:{} PDT) ({})".format(
local_short_str = local_t.strftime("%H:%M %Z")
expected = "{} ({}) ({})".format(
cur_time,
str(h),
str(m).rjust(2, "0"),
local_short_str,
message.rstrip(),
)
actual = time.run(fromcall, message, ack)