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.15
+version:               0.3.16
 synopsis:              GNSS Converters.
 description:           Haskell bindings for GNSS converters.
 homepage:              http://github.com/swift-nav/gnss-converters
@@ -101,6 +101,7 @@
                      , tasty-golden
                      , tasty-hunit
                      , text
+                     , time
                      , unordered-containers
   ghc-options:         -threaded -rtsopts -with-rtsopts=-N -Wall
   default-language:    Haskell2010
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
@@ -12,7 +12,14 @@
 -- SBP GPS Time helpers.
 
 module Data.RTCM3.SBP.Time
-  ( currentGpsTime
+  ( gpsLeapMillis
+  , hourMillis
+  , dayMillis
+  , weekMillis
+  , toWn
+  , toStartDate
+  , toTow
+  , currentGpsTime
   , rolloverTowGpsTime
   , rolloverEpochGpsTime
   ) where
@@ -77,14 +84,25 @@
     days  = diffDays (utctDay t) gpsEpoch
     weeks = days `div` 7
 
+-- | Find the start of the GPS week, which is Sunday.
+--
+toStartDate :: (Integer, Int, Int) -> (Integer, Int, Int)
+toStartDate (year, week, day)
+  | day == 7  = (year,   week,   7)
+  | week == 1 = (year-1, 52,     7)
+  | otherwise = (year,   week-1, 7)
+
+-- | Generate the start of the GPS week UTC time.
+--
+fromStartDate :: UTCTime -> UTCTime
+fromStartDate t = UTCTime (fromWeekDate year week day) 0
+  where
+    (year, week, day) = toStartDate $ toWeekDate $ utctDay t
+
 -- | Produce GPS time of week from a GPS UTC time.
 --
 toTow :: UTCTime -> Word32
-toTow t = floor since
-  where
-    (y, w, _d) = toWeekDate (utctDay t)
-    begin      = addDays (-1) $ fromWeekDate y w 1
-    since      = 1000 * diffUTCTime t (UTCTime begin 0)
+toTow t = floor $ 1000 * diffUTCTime t (fromStartDate t)
 
 -- | Get current GPS time.
 --
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
@@ -7,6 +7,8 @@
 
 import BasicPrelude
 import Data.RTCM3.SBP.Time
+import Data.Time
+import Data.Time.Calendar.WeekDate
 import SwiftNav.SBP
 import Test.Tasty
 import Test.Tasty.HUnit
@@ -30,8 +32,62 @@
         rolloverTowGpsTime 302400001 (GpsTimeNano 0 0 1961) @?= GpsTimeNano 302400001 0 1960
     ]
 
+testStartDate :: TestTree
+testStartDate =
+  testGroup "GPS week start date tests"
+    [ testCase "Sundays" $ do
+        toStartDate (2017, 34, 7) @?= (2017, 34, 7)
+        toStartDate (2016, 52, 7) @?= (2016, 52, 7)
+        toStartDate (2017,  1, 7) @?= (2017,  1, 7)
+    , testCase "Mondays" $ do
+        toStartDate (2017, 34, 1) @?= (2017, 33, 7)
+        toStartDate (2016, 52, 1) @?= (2016, 51, 7)
+        toStartDate (2017,  1, 1) @?= (2016, 52, 7)
+    , testCase "Saturdays" $ do
+        toStartDate (2017, 34, 6) @?= (2017, 33, 7)
+        toStartDate (2016, 52, 6) @?= (2016, 51, 7)
+        toStartDate (2017,  1, 6) @?= (2016, 52, 7)
+    ]
+
+testToWn :: TestTree
+testToWn =
+  testGroup "GPS week number tests"
+    [ testCase "Sundays" $ do
+        toWn (UTCTime (fromWeekDate 2017 34 7) 0) @?= 1964
+        toWn (UTCTime (fromWeekDate 2016 52 7) 0) @?= 1930
+        toWn (UTCTime (fromWeekDate 2017  1 7) 0) @?= 1931
+    , testCase "Mondays" $ do
+        toWn (UTCTime (fromWeekDate 2017 34 1) 0) @?= 1963
+        toWn (UTCTime (fromWeekDate 2016 52 1) 0) @?= 1929
+        toWn (UTCTime (fromWeekDate 2017  1 1) 0) @?= 1930
+    , testCase "Saturdays" $ do
+        toWn (UTCTime (fromWeekDate 2017 34 6) 0) @?= 1963
+        toWn (UTCTime (fromWeekDate 2016 52 6) 0) @?= 1929
+        toWn (UTCTime (fromWeekDate 2017  1 6) 0) @?= 1930
+    ]
+
+testToTow :: TestTree
+testToTow =
+  testGroup "GPS time of week tests"
+    [ testCase "Sundays" $ do
+        toTow (UTCTime (fromWeekDate 2017 34 7) 0) @?= 0
+        toTow (UTCTime (fromWeekDate 2016 52 7) 0) @?= 0
+        toTow (UTCTime (fromWeekDate 2017  1 7) 0) @?= 0
+    , testCase "Mondays" $ do
+        toTow (UTCTime (fromWeekDate 2017 34 1) 0) @?= fromIntegral dayMillis
+        toTow (UTCTime (fromWeekDate 2016 52 1) 0) @?= fromIntegral dayMillis
+        toTow (UTCTime (fromWeekDate 2017  1 1) 0) @?= fromIntegral dayMillis
+    , testCase "Saturdays" $ do
+        toTow (UTCTime (fromWeekDate 2017 34 6) 0) @?= 6 * fromIntegral dayMillis
+        toTow (UTCTime (fromWeekDate 2016 52 6) 0) @?= 6 * fromIntegral dayMillis
+        toTow (UTCTime (fromWeekDate 2017  1 6) 0) @?= 6 * fromIntegral dayMillis
+    ]
+
 tests :: TestTree
 tests =
   testGroup "RTCM3 to SBP time tests"
     [ testRolloverGpsTime
+    , testStartDate
+    , testToWn
+    , testToTow
     ]
