diff --git a/gnss-converters.cabal b/gnss-converters.cabal
--- a/gnss-converters.cabal
+++ b/gnss-converters.cabal
@@ -1,5 +1,5 @@
 name: gnss-converters
-version: 0.3.20
+version: 0.3.21
 cabal-version: >=1.22
 build-type: Simple
 license: BSD3
@@ -37,7 +37,7 @@
         mtl >=2.2.1,
         resourcet >=1.1.9,
         rtcm >=0.2.8,
-        sbp >=2.2.16,
+        sbp >=2.3.0,
         time >=1.5.0.1,
         transformers-base >=0.4.4,
         vector >=0.11.0.0
@@ -100,7 +100,7 @@
         gnss-converters,
         lens >=4.13,
         rtcm >=0.2.8,
-        sbp >=2.2.16,
+        sbp >=2.3.0,
         tasty >=0.11.2.1,
         tasty-golden >=2.3.1.1,
         tasty-hunit >=0.9.2,
diff --git a/src/Data/RTCM3/SBP/Ephemerides.hs b/src/Data/RTCM3/SBP/Ephemerides.hs
--- a/src/Data/RTCM3/SBP/Ephemerides.hs
+++ b/src/Data/RTCM3/SBP/Ephemerides.hs
@@ -32,7 +32,7 @@
 toGpsTimeSec :: MonadStore e m => Word16 -> Word16 -> m GpsTimeSec
 toGpsTimeSec wn tow = do
   time <- view storeCurrentGpsTime
-  wn'  <- view gpsTimeNano_wn <$> liftIO time
+  wn'  <- view gpsTime_wn <$> liftIO time
   pure GpsTimeSec
     { _gpsTimeSec_tow = 16 * fromIntegral tow
     , _gpsTimeSec_wn  = wn' `shiftR` 10 `shiftL` 10 + wn
@@ -80,9 +80,9 @@
 toGpsEphemerisCommonContent m = do
   toe <- toGpsTimeSec (m ^. msg1019_ephemeris ^. gpsEphemeris_wn) (m ^. msg1019_ephemeris ^. gpsEphemeris_toe)
   pure EphemerisCommonContent
-    { _ephemerisCommonContent_sid = GnssSignal16
-      { _gnssSignal16_sat  = m ^. msg1019_header ^. gpsEphemerisHeader_sat
-      , _gnssSignal16_code = 0 -- there is an L2P status flag in msg 1019, but I don't think that applies
+    { _ephemerisCommonContent_sid = GnssSignal
+      { _gnssSignal_sat  = m ^. msg1019_header ^. gpsEphemerisHeader_sat
+      , _gnssSignal_code = 0 -- there is an L2P status flag in msg 1019, but I don't think that applies
       }
     , _ephemerisCommonContent_toe          = toe
     , _ephemerisCommonContent_ura          = uriToUra (fromIntegral $ m ^. msg1019_ephemeris ^. gpsEphemeris_svHealth)
diff --git a/src/Data/RTCM3/SBP/Observations.hs b/src/Data/RTCM3/SBP/Observations.hs
--- a/src/Data/RTCM3/SBP/Observations.hs
+++ b/src/Data/RTCM3/SBP/Observations.hs
@@ -39,8 +39,8 @@
 
 -- | Update and convert stored and incoming GPS times.
 --
-toGpsTimeNano :: MonadStore e m => Word16 -> (GpsTimeNano -> GpsTimeNano) -> m (GpsTimeNano, GpsTimeNano)
-toGpsTimeNano station rollover = do
+toGpsTime :: MonadStore e m => Word16 -> (GpsTime -> GpsTime) -> m (GpsTime, GpsTime)
+toGpsTime station rollover = do
   timeMap <- view storeGpsTimeMap
   modifyIORefM timeMap $ \timeMap' -> do
     time <- view storeCurrentGpsTime
@@ -151,31 +151,31 @@
 
 -- | Map GPS L1 signal.
 --
-gpsL1Signal :: Word8 -> Bool -> GnssSignal16
+gpsL1Signal :: Word8 -> Bool -> GnssSignal
 gpsL1Signal sat code
-  | code      = GnssSignal16 sat 5
-  | otherwise = GnssSignal16 sat 0
+  | code      = GnssSignal sat 5
+  | otherwise = GnssSignal sat 0
 
 -- | Map GPS L2 signal.
 --
-gpsL2Signal :: Word8 -> Word8 -> GnssSignal16
+gpsL2Signal :: Word8 -> Word8 -> GnssSignal
 gpsL2Signal sat code
-  | code == 0 = GnssSignal16 sat 1
-  | otherwise = GnssSignal16 sat 6
+  | code == 0 = GnssSignal sat 1
+  | otherwise = GnssSignal sat 6
 
 -- | Map GLONASS L1 signal.
 --
-glonassL1Signal :: Word8 -> Bool -> Maybe GnssSignal16
+glonassL1Signal :: Word8 -> Bool -> Maybe GnssSignal
 glonassL1Signal sat code
-  | code      = Just $ GnssSignal16 sat 3
-  | otherwise = Just $ GnssSignal16 sat 3
+  | code      = Just $ GnssSignal sat 3
+  | otherwise = Just $ GnssSignal sat 3
 
 -- | Map GLONASS L2 signal.
 --
-glonassL2Signal :: Word8 -> Word8 -> Maybe GnssSignal16
+glonassL2Signal :: Word8 -> Word8 -> Maybe GnssSignal
 glonassL2Signal sat code
-  | code == 0 = Just $ GnssSignal16 sat 4
-  | otherwise = Just $ GnssSignal16 sat 4
+  | code == 0 = Just $ GnssSignal sat 4
+  | otherwise = Just $ GnssSignal sat 4
 
 -- | Max GPS satellite number.
 --
@@ -304,38 +304,38 @@
 -- | FromObservations produces GPS time, SBP packed observations, and sender from RTCMv3 observation messages.
 --
 class FromObservations a where
-  gpsTimeNano       :: MonadStore e m => a -> m (GpsTimeNano, GpsTimeNano)
+  gpsTime           :: MonadStore e m => a -> m (GpsTime, GpsTime)
   packedObsContents :: a -> [PackedObsContent]
   sender            :: a -> Word16
   synchronous       :: a -> Bool
 
 instance FromObservations Msg1002 where
-  gpsTimeNano m     = toGpsTimeNano (m ^. msg1002_header . gpsObservationHeader_station) $ rolloverTowGpsTime (m ^. msg1002_header . gpsObservationHeader_tow)
+  gpsTime m         = toGpsTime (m ^. msg1002_header . gpsObservationHeader_station) $ rolloverTowGpsTime (m ^. msg1002_header . gpsObservationHeader_tow)
   packedObsContents = toPackedObsContent . view msg1002_observations
   sender            = toSender . view (msg1002_header . gpsObservationHeader_station)
   synchronous       = view (msg1002_header . gpsObservationHeader_synchronous)
 
 instance FromObservations Msg1004 where
-  gpsTimeNano m     = toGpsTimeNano (m ^. msg1004_header . gpsObservationHeader_station) $ rolloverTowGpsTime (m ^. msg1004_header . gpsObservationHeader_tow)
+  gpsTime m         = toGpsTime (m ^. msg1004_header . gpsObservationHeader_station) $ rolloverTowGpsTime (m ^. msg1004_header . gpsObservationHeader_tow)
   packedObsContents = toPackedObsContent . view msg1004_observations
   sender            = toSender . view (msg1004_header . gpsObservationHeader_station)
   synchronous       = view (msg1004_header . gpsObservationHeader_synchronous)
 
 instance FromObservations Msg1010 where
-  gpsTimeNano m     = toGpsTimeNano (m ^. msg1010_header . glonassObservationHeader_station) $ rolloverEpochGpsTime (m ^. msg1010_header . glonassObservationHeader_epoch)
+  gpsTime m         = toGpsTime (m ^. msg1010_header . glonassObservationHeader_station) $ rolloverEpochGpsTime (m ^. msg1010_header . glonassObservationHeader_epoch)
   packedObsContents = toPackedObsContent . view msg1010_observations
   sender            = toSender . view (msg1010_header . glonassObservationHeader_station)
   synchronous       = view (msg1010_header . glonassObservationHeader_synchronous)
 
 instance FromObservations Msg1012 where
-  gpsTimeNano m     = toGpsTimeNano (m ^. msg1012_header . glonassObservationHeader_station) $ rolloverEpochGpsTime (m ^. msg1012_header . glonassObservationHeader_epoch)
+  gpsTime m         = toGpsTime (m ^. msg1012_header . glonassObservationHeader_station) $ rolloverEpochGpsTime (m ^. msg1012_header . glonassObservationHeader_epoch)
   packedObsContents = toPackedObsContent . view msg1012_observations
   sender            = toSender . view (msg1012_header . glonassObservationHeader_station)
   synchronous       = view (msg1012_header . glonassObservationHeader_synchronous)
 
 -- | Convert RTCMv3 observation(s) to SBP observations in chunks.
 --
-toMsgObs :: Applicative f => GpsTimeNano -> [PackedObsContent] -> Word16 -> f [SBPMsg]
+toMsgObs :: Applicative f => GpsTime -> [PackedObsContent] -> Word16 -> f [SBPMsg]
 toMsgObs t obs s = do
   let chunks = chunksOf maxObs obs
   ifor chunks $ \i obs' -> do
@@ -352,7 +352,7 @@
 --
 converter :: (MonadStore e m, FromObservations a) => a -> Conduit i m [SBPMsg]
 converter m = do
-  (t, t') <- gpsTimeNano m
+  (t, t')      <- gpsTime m
   observations <- view storeObservations
   obs          <- liftIO $ readIORef observations
   when (t' /= t) $
diff --git a/src/Data/RTCM3/SBP/Time.hs b/src/Data/RTCM3/SBP/Time.hs
--- a/src/Data/RTCM3/SBP/Time.hs
+++ b/src/Data/RTCM3/SBP/Time.hs
@@ -106,36 +106,36 @@
 
 -- | Get current GPS time.
 --
-currentGpsTime :: MonadIO m => m GpsTimeNano
+currentGpsTime :: MonadIO m => m GpsTime
 currentGpsTime = do
   t <- liftIO $ addUTCTime (fromIntegral gpsLeapSeconds) <$> getCurrentTime
-  pure $ GpsTimeNano (toTow t) 0 (toWn t)
+  pure $ GpsTime (toTow t) 0 (toWn t)
 
 -- | Update GPS time based on GPS time of week, handling week rollover.
 --
-rolloverTowGpsTime :: Word32 -> GpsTimeNano -> GpsTimeNano
-rolloverTowGpsTime tow t = t & gpsTimeNano_tow .~ tow & rollover
+rolloverTowGpsTime :: Word32 -> GpsTime -> GpsTime
+rolloverTowGpsTime tow t = t & gpsTime_tow .~ tow & rollover
   where
     rollover
-      | increment = gpsTimeNano_wn +~ 1
-      | decrement = gpsTimeNano_wn +~ -1
-      | otherwise = gpsTimeNano_wn +~ 0
+      | increment = gpsTime_wn +~ 1
+      | decrement = gpsTime_wn +~ -1
+      | otherwise = gpsTime_wn +~ 0
     new       = fromIntegral tow
-    old       = fromIntegral (t ^. gpsTimeNano_tow)
+    old       = fromIntegral (t ^. gpsTime_tow)
     increment = old > new && old - new > weekMillis `div` 2
     decrement = new > old && new - old > weekMillis `div` 2
 
 -- | Update GPS time based on GLONASS epoch, handling week rollover.
 --
-rolloverEpochGpsTime :: Word32 -> GpsTimeNano -> GpsTimeNano
+rolloverEpochGpsTime :: Word32 -> GpsTime -> GpsTime
 rolloverEpochGpsTime epoch t = rolloverTowGpsTime tow t
   where
     epoch' = fromIntegral epoch - 3 * hourMillis + gpsLeapMillis
     epoch''
       | epoch' < 0 = epoch' + dayMillis
       | otherwise  = epoch'
-    dow = fromIntegral (t ^. gpsTimeNano_tow) `div` dayMillis
-    tod = fromIntegral (t ^. gpsTimeNano_tow) - dow * dayMillis
+    dow = fromIntegral (t ^. gpsTime_tow) `div` dayMillis
+    tod = fromIntegral (t ^. gpsTime_tow) - dow * dayMillis
     dow'
       | increment = dow + 1 `mod` 7
       | decrement = dow - 1 `mod` 7
diff --git a/src/Data/RTCM3/SBP/Types.hs b/src/Data/RTCM3/SBP/Types.hs
--- a/src/Data/RTCM3/SBP/Types.hs
+++ b/src/Data/RTCM3/SBP/Types.hs
@@ -31,10 +31,10 @@
 import Data.Word
 import SwiftNav.SBP
 
-type GpsTimeNanoMap = HashMap Word16 GpsTimeNano
+type GpsTimeMap = HashMap Word16 GpsTime
 
-instance Ord GpsTimeNano where
-  compare (GpsTimeNano tow _ns wn) (GpsTimeNano tow' _ns' wn')
+instance Ord GpsTime where
+  compare (GpsTime tow _ns wn) (GpsTime tow' _ns' wn')
     | wn > wn'   = GT
     | wn < wn'   = LT
     | tow > tow' = GT
@@ -68,8 +68,8 @@
   {-# INLINE liftBase #-}
 
 data Store = Store
-  { _storeCurrentGpsTime :: IO GpsTimeNano
-  , _storeGpsTimeMap     :: IORef GpsTimeNanoMap
+  { _storeCurrentGpsTime :: IO GpsTime
+  , _storeGpsTimeMap     :: IORef GpsTimeMap
   , _storeObservations   :: IORef (Vector PackedObsContent)
   }
 
diff --git a/test/Test/Data/RTCM3/SBP.hs b/test/Test/Data/RTCM3/SBP.hs
--- a/test/Test/Data/RTCM3/SBP.hs
+++ b/test/Test/Data/RTCM3/SBP.hs
@@ -21,8 +21,8 @@
 import Test.Tasty
 import Test.Tasty.Golden
 
-testGpsTime :: Applicative f => Word32 -> Word16 -> f GpsTimeNano
-testGpsTime tow wn = pure $ GpsTimeNano tow 0 wn
+testGpsTime :: Applicative f => Word32 -> Word16 -> f GpsTime
+testGpsTime tow wn = pure $ GpsTime tow 0 wn
 
 encodeLine :: ToJSON a => a -> ByteString
 encodeLine v = toStrict $ encodePretty' defConfig { confCompare = compare } v <> "\n"
diff --git a/test/Test/Data/RTCM3/SBP/Time.hs b/test/Test/Data/RTCM3/SBP/Time.hs
--- a/test/Test/Data/RTCM3/SBP/Time.hs
+++ b/test/Test/Data/RTCM3/SBP/Time.hs
@@ -17,19 +17,19 @@
 testRolloverGpsTime =
   testGroup "Rollover GPS time tests"
     [ testCase "No rollover" $ do
-        rolloverTowGpsTime 0 (GpsTimeNano 0 0 1960) @?= GpsTimeNano 0 0 1960
-        rolloverTowGpsTime 302400000 (GpsTimeNano 302400000 0 1960) @?= GpsTimeNano 302400000 0 1960
-        rolloverTowGpsTime 604800000 (GpsTimeNano 604800000 0 1960) @?= GpsTimeNano 604800000 0 1960
-        rolloverTowGpsTime 0 (GpsTimeNano 302400000 0 1960) @?= GpsTimeNano 0 0 1960
-        rolloverTowGpsTime 302400000 (GpsTimeNano 604800000 0 1960) @?= GpsTimeNano 302400000 0 1960
+        rolloverTowGpsTime 0 (GpsTime 0 0 1960) @?= GpsTime 0 0 1960
+        rolloverTowGpsTime 302400000 (GpsTime 302400000 0 1960) @?= GpsTime 302400000 0 1960
+        rolloverTowGpsTime 604800000 (GpsTime 604800000 0 1960) @?= GpsTime 604800000 0 1960
+        rolloverTowGpsTime 0 (GpsTime 302400000 0 1960) @?= GpsTime 0 0 1960
+        rolloverTowGpsTime 302400000 (GpsTime 604800000 0 1960) @?= GpsTime 302400000 0 1960
     , testCase "Positive rollover" $ do
-        rolloverTowGpsTime 0 (GpsTimeNano 302400001 0 1960) @?= GpsTimeNano 0 0 1961
-        rolloverTowGpsTime 0 (GpsTimeNano 604800000 0 1960) @?= GpsTimeNano 0 0 1961
-        rolloverTowGpsTime 302399999 (GpsTimeNano 604800000 0 1960) @?= GpsTimeNano 302399999 0 1961
+        rolloverTowGpsTime 0 (GpsTime 302400001 0 1960) @?= GpsTime 0 0 1961
+        rolloverTowGpsTime 0 (GpsTime 604800000 0 1960) @?= GpsTime 0 0 1961
+        rolloverTowGpsTime 302399999 (GpsTime 604800000 0 1960) @?= GpsTime 302399999 0 1961
     , testCase "Negative rollover" $ do
-        rolloverTowGpsTime 604800000 (GpsTimeNano 0 0 1961) @?= GpsTimeNano 604800000 0 1960
-        rolloverTowGpsTime 604800000 (GpsTimeNano 302399999 0 1961) @?= GpsTimeNano 604800000 0 1960
-        rolloverTowGpsTime 302400001 (GpsTimeNano 0 0 1961) @?= GpsTimeNano 302400001 0 1960
+        rolloverTowGpsTime 604800000 (GpsTime 0 0 1961) @?= GpsTime 604800000 0 1960
+        rolloverTowGpsTime 604800000 (GpsTime 302399999 0 1961) @?= GpsTime 604800000 0 1960
+        rolloverTowGpsTime 302400001 (GpsTime 0 0 1961) @?= GpsTime 302400001 0 1960
     ]
 
 testStartDate :: TestTree
