Skip to content

Commit cda7883

Browse files
committed
add cache_seconds
1 parent fc0f07c commit cda7883

File tree

1 file changed

+19
-2
lines changed

1 file changed

+19
-2
lines changed

adafruit_ntp.py

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ def __init__(
4646
port: int = 123,
4747
tz_offset: float = 0,
4848
socket_timeout: int = 10,
49+
cache_seconds: int = 3600,
4950
) -> None:
5051
"""
5152
:param object socketpool: A socket provider such as CPython's `socket` module.
@@ -55,6 +56,8 @@ def __init__(
5556
CircuitPython. CPython will determine timezone automatically and adjust (so don't use
5657
this.) For example, Pacific daylight savings time is -7.
5758
:param int socket_timeout: UDP socket timeout, in seconds.
59+
:param int cache_seconds: how many seconds to use a cached result from NTP server
60+
(default 3600).
5861
"""
5962
self._pool = socketpool
6063
self._server = server
@@ -63,6 +66,7 @@ def __init__(
6366
self._packet = bytearray(PACKET_SIZE)
6467
self._tz_offset = int(tz_offset * 60 * 60)
6568
self._socket_timeout = socket_timeout
69+
self._cache_seconds = cache_seconds
6670

6771
# This is our estimated start time for the monotonic clock. We adjust it based on the ntp
6872
# responses.
@@ -74,7 +78,8 @@ def __init__(
7478
def datetime(self) -> time.struct_time:
7579
"""Current time from NTP server. Accessing this property causes the NTP time request,
7680
unless there has already been a recent request. Raises OSError exception if no response
77-
is received within socket_timeout seconds"""
81+
is received within socket_timeout seconds, ArithmeticError for substantially incorrect
82+
NTP results."""
7883
if time.monotonic_ns() > self.next_sync:
7984
if self._socket_address is None:
8085
self._socket_address = self._pool.getaddrinfo(self._server, self._port)[
@@ -92,8 +97,20 @@ def datetime(self) -> time.struct_time:
9297
# the packet.
9398
destination = time.monotonic_ns()
9499
poll = struct.unpack_from("!B", self._packet, offset=2)[0]
95-
self.next_sync = destination + (2**poll) * 1_000_000_000
100+
101+
cache_offset = max(2**poll, self._cache_seconds)
102+
self.next_sync = destination + cache_offset * 1_000_000_000
96103
seconds = struct.unpack_from("!I", self._packet, offset=PACKET_SIZE - 8)[0]
104+
105+
# value should always be larger; giving a small buffer to handle jitter.
106+
if (seconds + 5) < self._monotonic_start:
107+
failed_offset = (self._monotonic_start - seconds) / 1_000_000_000
108+
raise ArithmeticError(
109+
"need a time machine, ntp time is "
110+
+ str(failed_offset)
111+
+ "seconds in the past."
112+
)
113+
97114
self._monotonic_start = (
98115
seconds
99116
+ self._tz_offset

0 commit comments

Comments
 (0)