From dbef2e1eac71d7108477352eff58ddee59915c69 Mon Sep 17 00:00:00 2001 From: SEMU Admin <28569967+semuadmin@users.noreply.github.com> Date: Sat, 25 Apr 2026 09:14:56 +0100 Subject: [PATCH 1/3] add modwno argument to date utilities --- RELEASE_NOTES.md | 4 ++++ src/pynmeagps/_version.py | 2 +- src/pynmeagps/nmeahelpers.py | 9 +++++++-- tests/test_static.py | 13 ++++++++++++- 4 files changed, 24 insertions(+), 4 deletions(-) diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index 8bf2142..4b1a38b 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -1,5 +1,9 @@ # pynmeagps Release Notes +### RELEASE 1.1.4 + +1. Add `modwno` boolean argument to wnotow2utc and utc2wnotow helper functions - True => modular week number, False => continuous week number. The default is True (modular week no). + ### RELEASE 1.1.3 1. Update wnotow2utc, utc2wnotow and leapsecond helper functions to accommodate all GNSS time systems. wnotow2utc method also adds an 'autoroll' argument which, if True, will automatically roll forward modular GNSS week numbers to the latest date less than the current date - see API docs for details. diff --git a/src/pynmeagps/_version.py b/src/pynmeagps/_version.py index c6ef92b..b3528e0 100644 --- a/src/pynmeagps/_version.py +++ b/src/pynmeagps/_version.py @@ -8,4 +8,4 @@ :license: BSD 3-Clause """ -__version__ = "1.1.3" +__version__ = "1.1.4" diff --git a/src/pynmeagps/nmeahelpers.py b/src/pynmeagps/nmeahelpers.py index 051340e..ce985e4 100644 --- a/src/pynmeagps/nmeahelpers.py +++ b/src/pynmeagps/nmeahelpers.py @@ -734,6 +734,7 @@ def time2utc(times: str) -> datetime | str: def utc2wnotow( utc: datetime | NoneType = None, gnss: Literal["G", "E", "C", "J", "I"] = GPS, + modwno: bool = True, ) -> tuple[int, int, int]: """ Get Week number (wno), Time of Week (tow) in milliseconds @@ -748,6 +749,7 @@ def utc2wnotow( :param datetime | NoneType utc: UTC epoch :param Literal["G","E","C","J","I"] = GPS) gnss: \ GNSS time system (GPS) + :param bool modwno: True = modular wno, False = continuous wno :return: wno, tow, leapsecond :rtype: tuple[int, int, int] """ @@ -773,8 +775,9 @@ def utc2wnotow( ls = 0 if gnss == GLO else leapsecond(utc, gnss) ts = ((utc - ep0).total_seconds() + ls) * 1000 wno = floor((utc - ep0).days / 7) + wno = wno % rollover if modwno else wno tow = int(ts - wno * 604800000) - return wno % rollover, tow, ls + return wno, tow, ls def wnotow2utc( @@ -783,6 +786,7 @@ def wnotow2utc( ls: int | NoneType = None, gnss: Literal["G", "E", "C", "J", "I"] = GPS, autoroll: bool = False, + modwno: bool = True, ) -> datetime: """ Convert week number and seconds of week (expressed as @@ -815,6 +819,7 @@ def wnotow2utc( :param int | NoneType ls: leapsecond offset (will be derived if None) (None) :param Literal["G","E","C","J","I"] = GPS) gnss: GNSS time system (GPS) :param bool autoroll: automatic rollover (False) + :param bool modwno: True = modular wno, False = continuous wno :return: GNSS epoch as UTC datetime :rtype: datetime """ @@ -831,7 +836,7 @@ def wnotow2utc( else: ep0 = EPOCH0_GPS rollover = 1024 - wno %= rollover + wno = wno % rollover if modwno else wno tow %= 604800000 current = datetime.now(timezone.utc) i = 0 diff --git a/tests/test_static.py b/tests/test_static.py index 5781372..abae53c 100644 --- a/tests/test_static.py +++ b/tests/test_static.py @@ -631,11 +631,16 @@ def testmaxidx(self): # self.assertIsInstance(ls, int) def testwnotow2utcGPS(self): - res = wnotow2utc(2406, 516114123, None) + res = wnotow2utc(2406, 516114123, None, GPS,False, True) # print(res) self.assertEqual( res, datetime(1986, 11, 21, 23, 21, 50, 123000, tzinfo=timezone.utc) ) + res = wnotow2utc(2406, 516114123, None,GPS,False, False) + # print(res) + self.assertEqual( + res, datetime(2026, 2, 20, 23, 21, 36, 123000, tzinfo=timezone.utc) + ) utc = wnotow2utc(2406, 516114000) self.assertEqual( (utc.year, utc.month, utc.day, utc.hour, utc.minute, utc.second), @@ -657,11 +662,17 @@ def testwnotow2utcGAL(self): res = wnotow2utc(1390, 381600000, None, GAL, False) # print(res) self.assertEqual(str(res), "2026-04-16 09:59:42+00:00") + res = wnotow2utc(1390, 381600000, None, GAL, False, False) + # print(res) + self.assertEqual(str(res), "2026-04-16 09:59:42+00:00") def testwnotow2utcIRN(self): res = wnotow2utc(1390, 381600000, None, IRN, False) # print(res) self.assertEqual(str(res), "2006-08-31 09:59:46+00:00") + res = wnotow2utc(1390, 381600000, None, IRN, False, False) + # print(res) + self.assertEqual(str(res), "2026-04-16 09:59:42+00:00") def testleapsecondGPS(self): self.assertEqual(leapsecond(EPOCH0_GPS, "G"), 0) From 4d15f9e913d03f0fc747259b169cfbf16bc26f43 Mon Sep 17 00:00:00 2001 From: SEMU Admin <28569967+semuadmin@users.noreply.github.com> Date: Sat, 25 Apr 2026 09:36:30 +0100 Subject: [PATCH 2/3] update utc2wnotow --- src/pynmeagps/nmeahelpers.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/pynmeagps/nmeahelpers.py b/src/pynmeagps/nmeahelpers.py index ce985e4..8abfaf5 100644 --- a/src/pynmeagps/nmeahelpers.py +++ b/src/pynmeagps/nmeahelpers.py @@ -775,9 +775,9 @@ def utc2wnotow( ls = 0 if gnss == GLO else leapsecond(utc, gnss) ts = ((utc - ep0).total_seconds() + ls) * 1000 wno = floor((utc - ep0).days / 7) - wno = wno % rollover if modwno else wno + wnom = wno % rollover tow = int(ts - wno * 604800000) - return wno, tow, ls + return wnom if modwno else wno, tow, ls def wnotow2utc( From 9eb5a9bd1f539f81e4f8438e01d9340f422cd0d4 Mon Sep 17 00:00:00 2001 From: semuadmin <28569967+semuadmin@users.noreply.github.com> Date: Mon, 27 Apr 2026 07:56:37 +0100 Subject: [PATCH 3/3] enhance test coverage --- tests/test_static.py | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/tests/test_static.py b/tests/test_static.py index abae53c..e46c433 100644 --- a/tests/test_static.py +++ b/tests/test_static.py @@ -631,12 +631,12 @@ def testmaxidx(self): # self.assertIsInstance(ls, int) def testwnotow2utcGPS(self): - res = wnotow2utc(2406, 516114123, None, GPS,False, True) + res = wnotow2utc(2406, 516114123, None, GPS, False, True) # print(res) self.assertEqual( res, datetime(1986, 11, 21, 23, 21, 50, 123000, tzinfo=timezone.utc) ) - res = wnotow2utc(2406, 516114123, None,GPS,False, False) + res = wnotow2utc(2406, 516114123, None, GPS, False, False) # print(res) self.assertEqual( res, datetime(2026, 2, 20, 23, 21, 36, 123000, tzinfo=timezone.utc) @@ -652,12 +652,12 @@ def testwnotow2utcGPS(self): res = wnotow2utc(1390, 381600000, None, GPS, False) # print(res) self.assertEqual(str(res), "1987-01-15 09:59:56+00:00") - + def testwnotow2utcBDS(self): res = wnotow2utc(1390, 381600000, None, BDS, False) # print(res) self.assertEqual(str(res), "2032-08-26 09:59:56+00:00") - + def testwnotow2utcGAL(self): res = wnotow2utc(1390, 381600000, None, GAL, False) # print(res) @@ -665,7 +665,7 @@ def testwnotow2utcGAL(self): res = wnotow2utc(1390, 381600000, None, GAL, False, False) # print(res) self.assertEqual(str(res), "2026-04-16 09:59:42+00:00") - + def testwnotow2utcIRN(self): res = wnotow2utc(1390, 381600000, None, IRN, False) # print(res) @@ -712,6 +712,14 @@ def testtimeconv(self): wno2, tow2, ls = utc2wnotow(utc, gnss) self.assertEqual((wno, tow), (wno2, tow2)) + def testutc2wnotow(self): + + wno, tow, ls = utc2wnotow() + # print(wno, tow, ls) + wno, tow, ls = utc2wnotow(datetime(2026, 4, 1, 2, 3, 4)) + # print(wno, tow, ls) + self.assertEqual((wno, tow, ls), (364, 266602000, 18)) + if __name__ == "__main__": # import sys;sys.argv = ['', 'Test.testName']