Repository: adafruit/Adafruit_CircuitPython_GPS

Issue:
Usage of float causes timestamp_utc to be imprecise
NMEA timestamp is written as HHMMSS.sss, which is stored as float in the module.

Later it is converted to int which is inaccurate:
See example:
```
>> int(184105.000)
184104
```

This is then math'ed into the fields in time_struct.

Propose storing the NMEA sentence as string instead, and grabbing the sections of the sting directly.

Comments:

Patch:
diff --git a/adafruit_gps.py b/adafruit_gps.py
index 10bc89c..a28a065 100644
--- a/adafruit_gps.py
+++ b/adafruit_gps.py
@@ -50,11 +50,11 @@ _ST_MAX = _RMC_4_1
 
 _SENTENCE_PARAMS = (
     # 0 - _GLL
-    "dcdcfcC",
+    "dcdcscC",
     # 1 - _RMC
-    "fcdcdcffiDCC",
+    "scdcdcffsDCC",
     # 2 - _GGA
-    "fdcdciiffsfsIS",
+    "sdcdciiffsfsIS",
     # 3 - _GSA
     "ciIIIIIIIIIIIIfff",
     # 4 - _GSA_4_11
@@ -68,7 +68,7 @@ _SENTENCE_PARAMS = (
     # 8 - _GSV19
     "iiiiiiIiiiIiiiIiiiI",
     # 9 - _RMC_4_1
-    "fcdcdcffiDCCC",
+    "scdcdcffsDCCC",
 )
 
 
@@ -394,9 +394,9 @@ class GPS:
         return (data_type, sentence[delimiter + 1 :])
 
     def _update_timestamp_utc(self, time_utc, date=None):
-        hours = time_utc // 10000
-        mins = (time_utc // 100) % 100
-        secs = time_utc % 100
+        hours = int(time_utc[0:2])
+        mins = int(time_utc[2:4])
+        secs = int(time_utc[4:6])
         if date is None:
             if self.timestamp_utc is None:
                 day, month, year = 0, 0, 0
@@ -405,9 +405,9 @@ class GPS:
                 month = self.timestamp_utc.tm_mon
                 year = self.timestamp_utc.tm_year
         else:
-            day = date // 10000
-            month = (date // 100) % 100
-            year = 2000 + date % 100
+            day = int(date[0:2])
+            month = int(date[2:4])
+            year = 2000 + int(date[4:6])
 
         self.timestamp_utc = time.struct_time(
             (year, month, day, hours, mins, secs, 0, 0, -1)
@@ -429,7 +429,7 @@ class GPS:
         self.longitude = _read_degrees(data, 2, "w")
 
         # UTC time of position
-        self._update_timestamp_utc(int(data[4]))
+        self._update_timestamp_utc(data[4])
 
         # Status Valid(A) or Invalid(V)
         self.isactivedata = data[5]
@@ -450,7 +450,7 @@ class GPS:
             return False  # Params didn't parse
 
         # UTC time of position and date
-        self._update_timestamp_utc(int(data[0]), data[8])
+        self._update_timestamp_utc(data[0], data[8])
 
         # Status Valid(A) or Invalid(V)
         self.isactivedata = data[1]
@@ -494,7 +494,7 @@ class GPS:
             return False  # Params didn't parse
 
         # UTC time of position
-        self._update_timestamp_utc(int(data[0]))
+        self._update_timestamp_utc(data[0])
 
         # Latitude
         self.latitude = _read_degrees(data, 1, "s")


Test patch:
diff --git a/tests/adafruit_gps_test.py b/tests/adafruit_gps_test.py
index 9e09c85..8a956f3 100644
--- a/tests/adafruit_gps_test.py
+++ b/tests/adafruit_gps_test.py
@@ -140,14 +140,14 @@ def test_GPS_update_timestamp_UTC_date_None():
     assert gps.datetime is None
     assert gps.timestamp_utc is None
     exp_struct = time.struct_time((0, 0, 0, 22, 14, 11, 0, 0, -1))
-    gps._update_timestamp_utc(time_utc=221411)
+    gps._update_timestamp_utc(time_utc="221411")
     assert gps.timestamp_utc == exp_struct
 
 
 def test_GPS_update_timestamp_UTC_date_not_None():
     gps = GPS(uart=UartMock())
     exp_struct = time.struct_time((2021, 10, 2, 22, 14, 11, 0, 0, -1))
-    gps._update_timestamp_utc(time_utc=221411, date=21021)
+    gps._update_timestamp_utc(time_utc="221411", date="021021")
     assert gps.timestamp_utc == exp_struct
 
 
@@ -157,7 +157,7 @@ def test_GPS_update_timestamp_timestamp_utc_was_not_none_new_date_none():
     gps.timestamp_utc = time.struct_time((2021, 10, 2, 22, 10, 11, 0, 0, -1))
     exp_struct = time.struct_time((2021, 10, 2, 22, 14, 11, 0, 0, -1))
     # update the timestamp
-    gps._update_timestamp_utc(time_utc=221411)
+    gps._update_timestamp_utc(time_utc="221411")
     assert gps.timestamp_utc == exp_struct