{-# LANGUAGE CPP #-}
{-# LANGUAGE DeriveDataTypeable #-}
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE ViewPatterns #-}
#include "thyme.h"
#if HLINT
#include "cabal_macros.h"
#endif
#define TAIUTCDAT @<http://maia.usno.navy.mil/ser7/tai-utc.dat tai-utc.dat>@
module Data.Thyme.Clock.TAI
( AbsoluteTime
, taiEpoch
, TAIUTCMap (..)
, TAIUTCRow (..)
, absoluteTime
, absoluteTime'
, utcDayLength
, parseTAIUTCRow
, makeTAIUTCMap
, parseTAIUTCDAT
, addAbsoluteTime
, diffAbsoluteTime
, utcToTAITime
, taiToUTCTime
) where
import Prelude
#if !MIN_VERSION_base(4,8,0)
import Control.Applicative
#endif
import Control.DeepSeq
import Control.Lens
import Control.Monad
import Data.AffineSpace
import Data.Attoparsec.ByteString.Char8 ((<?>))
import qualified Data.Attoparsec.ByteString.Char8 as P
import qualified Data.ByteString as S
import Data.Data
import Data.Hashable
import Data.Ix
import Data.Map.Strict (Map)
import qualified Data.Map.Strict as Map
import Data.Thyme.Calendar
import Data.Thyme.Clock.Internal
import Data.Thyme.Format.Internal (indexOf)
import Data.Thyme.Internal.Micro
import Data.Thyme.LocalTime
#if __GLASGOW_HASKELL__ == 704
import qualified Data.Vector.Generic
import qualified Data.Vector.Generic.Mutable
#endif
import Data.Vector.Unboxed.Deriving
import Data.VectorSpace
import GHC.Generics (Generic)
import System.Random (Random)
import Test.QuickCheck
newtype AbsoluteTime = AbsoluteTime DiffTime deriving (INSTANCES_MICRO)
derivingUnbox "AbsoluteTime" [t| AbsoluteTime -> DiffTime |]
[| \ (AbsoluteTime a) -> a |] [| AbsoluteTime |]
instance Show AbsoluteTime where
{-# INLINEABLE showsPrec #-}
showsPrec :: Year -> AbsoluteTime -> ShowS
showsPrec Year
p AbsoluteTime
tai = Year -> LocalTime -> ShowS
forall a. Show a => Year -> a -> ShowS
showsPrec Year
p LocalTime
lt ShowS -> ShowS -> ShowS
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Char] -> ShowS
forall a. [a] -> [a] -> [a]
(++) [Char]
" TAI" where
lt :: LocalTime
lt = AbsoluteTime
tai AbsoluteTime
-> Getting LocalTime AbsoluteTime LocalTime -> LocalTime
forall s a. s -> Getting a s a -> a
^. AnIso UTCTime UTCTime AbsoluteTime AbsoluteTime
-> Iso AbsoluteTime AbsoluteTime UTCTime UTCTime
forall s t a b. AnIso s t a b -> Iso b a t s
from (TAIUTCMap -> Iso' UTCTime AbsoluteTime
absoluteTime (TAIUTCMap -> Iso' UTCTime AbsoluteTime)
-> TAIUTCMap -> Iso' UTCTime AbsoluteTime
forall a b. (a -> b) -> a -> b
$ Map UTCTime TAIUTCRow -> Map AbsoluteTime TAIUTCRow -> TAIUTCMap
TAIUTCMap Map UTCTime TAIUTCRow
forall a. Monoid a => a
mempty Map AbsoluteTime TAIUTCRow
forall a. Monoid a => a
mempty) Overloaded
(->) (Const LocalTime) AbsoluteTime AbsoluteTime UTCTime UTCTime
-> ((LocalTime -> Const LocalTime LocalTime)
-> UTCTime -> Const LocalTime UTCTime)
-> Getting LocalTime AbsoluteTime LocalTime
forall b c a. (b -> c) -> (a -> b) -> a -> c
. TimeZone -> Iso' UTCTime LocalTime
utcLocalTime TimeZone
utc
{-# INLINE taiEpoch #-}
taiEpoch :: AbsoluteTime
taiEpoch :: AbsoluteTime
taiEpoch = DiffTime -> AbsoluteTime
AbsoluteTime DiffTime
forall v. AdditiveGroup v => v
zeroV
instance AffineSpace AbsoluteTime where
type Diff AbsoluteTime = DiffTime
{-# INLINE (.-.) #-}
.-. :: AbsoluteTime -> AbsoluteTime -> Diff AbsoluteTime
(.-.) = \ (AbsoluteTime DiffTime
a) (AbsoluteTime DiffTime
b) -> DiffTime
a DiffTime -> DiffTime -> DiffTime
forall v. AdditiveGroup v => v -> v -> v
^-^ DiffTime
b
{-# INLINE (.+^) #-}
.+^ :: AbsoluteTime -> Diff AbsoluteTime -> AbsoluteTime
(.+^) = \ (AbsoluteTime DiffTime
a) Diff AbsoluteTime
d -> DiffTime -> AbsoluteTime
AbsoluteTime (DiffTime
a DiffTime -> DiffTime -> DiffTime
forall v. AdditiveGroup v => v -> v -> v
^+^ Diff AbsoluteTime
DiffTime
d)
data TAIUTCMap = TAIUTCMap (Map UTCTime TAIUTCRow) (Map AbsoluteTime TAIUTCRow)
deriving (INSTANCES_USUAL, Show)
data TAIUTCRow = TAIUTCRow !DiffTime !UTCTime !Rational
deriving (INSTANCES_USUAL, Show)
{-# INLINE lookupLE #-}
lookupLE :: (Ord k) => k -> Map k TAIUTCRow -> TAIUTCRow
lookupLE :: forall k. Ord k => k -> Map k TAIUTCRow -> TAIUTCRow
lookupLE k
k = TAIUTCRow
-> ((k, TAIUTCRow) -> TAIUTCRow)
-> Maybe (k, TAIUTCRow)
-> TAIUTCRow
forall b a. b -> (a -> b) -> Maybe a -> b
maybe (DiffTime -> UTCTime -> Rational -> TAIUTCRow
TAIUTCRow DiffTime
forall v. AdditiveGroup v => v
zeroV (NominalDiffTime -> UTCTime
UTCRep NominalDiffTime
forall v. AdditiveGroup v => v
zeroV) Rational
0) (k, TAIUTCRow) -> TAIUTCRow
forall a b. (a, b) -> b
snd (Maybe (k, TAIUTCRow) -> TAIUTCRow)
-> (Map k TAIUTCRow -> Maybe (k, TAIUTCRow))
-> Map k TAIUTCRow
-> TAIUTCRow
forall b c a. (b -> c) -> (a -> b) -> a -> c
. k -> Map k TAIUTCRow -> Maybe (k, TAIUTCRow)
forall k v. Ord k => k -> Map k v -> Maybe (k, v)
Map.lookupLE k
k
{-# INLINE unwrap #-}
unwrap :: TAIUTCRow -> (Micro, Micro, Rational)
unwrap :: TAIUTCRow -> (Micro, Micro, Rational)
unwrap (TAIUTCRow (DiffTime Micro
a) (UTCRep (NominalDiffTime Micro
b)) Rational
c) = (Micro
a, Micro
b, Rational
c)
{-# INLINE absoluteTime #-}
absoluteTime :: TAIUTCMap -> Iso' UTCTime AbsoluteTime
absoluteTime :: TAIUTCMap -> Iso' UTCTime AbsoluteTime
absoluteTime (TAIUTCMap Map UTCTime TAIUTCRow
utcMap Map AbsoluteTime TAIUTCRow
taiMap) = (UTCTime -> AbsoluteTime)
-> (AbsoluteTime -> UTCTime) -> Iso' UTCTime AbsoluteTime
forall s a b t. (s -> a) -> (b -> t) -> Iso s t a b
iso UTCTime -> AbsoluteTime
toTAI AbsoluteTime -> UTCTime
toUTC where
{-# INLINEABLE toTAI #-}
toTAI :: UTCTime -> AbsoluteTime
toTAI :: UTCTime -> AbsoluteTime
toTAI utime :: UTCTime
utime@(UTCRep (NominalDiffTime Micro
uts)) = DiffTime -> AbsoluteTime
AbsoluteTime (DiffTime -> AbsoluteTime)
-> (Micro -> DiffTime) -> Micro -> AbsoluteTime
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Micro -> DiffTime
DiffTime (Micro -> AbsoluteTime) -> Micro -> AbsoluteTime
forall a b. (a -> b) -> a -> b
$
Micro
uts Micro -> Micro -> Micro
forall v. AdditiveGroup v => v -> v -> v
^+^ Micro
a Micro -> Micro -> Micro
forall v. AdditiveGroup v => v -> v -> v
^+^ (Micro
uts Micro -> Micro -> Micro
forall v. AdditiveGroup v => v -> v -> v
^-^ Micro
b) Micro -> Rational -> Micro
forall v s. (VectorSpace v, s ~ Scalar v) => v -> s -> v
^* Rational
c where
(Micro
a, Micro
b, Rational
c) = TAIUTCRow -> (Micro, Micro, Rational)
unwrap (TAIUTCRow -> (Micro, Micro, Rational))
-> TAIUTCRow -> (Micro, Micro, Rational)
forall a b. (a -> b) -> a -> b
$ UTCTime -> Map UTCTime TAIUTCRow -> TAIUTCRow
forall k. Ord k => k -> Map k TAIUTCRow -> TAIUTCRow
lookupLE UTCTime
utime Map UTCTime TAIUTCRow
utcMap
{-# INLINEABLE toUTC #-}
toUTC :: AbsoluteTime -> UTCTime
toUTC :: AbsoluteTime -> UTCTime
toUTC atime :: AbsoluteTime
atime@(AbsoluteTime (DiffTime Micro
ats)) = NominalDiffTime -> UTCTime
UTCRep (NominalDiffTime -> UTCTime)
-> (Micro -> NominalDiffTime) -> Micro -> UTCTime
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Micro -> NominalDiffTime
NominalDiffTime (Micro -> UTCTime) -> Micro -> UTCTime
forall a b. (a -> b) -> a -> b
$
(Micro
ats Micro -> Micro -> Micro
forall v. AdditiveGroup v => v -> v -> v
^-^ Micro
a Micro -> Micro -> Micro
forall v. AdditiveGroup v => v -> v -> v
^+^ Micro
b Micro -> Rational -> Micro
forall v s. (VectorSpace v, s ~ Scalar v) => v -> s -> v
^* Rational
c) Micro -> Rational -> Micro
forall v s.
(VectorSpace v, s ~ Scalar v, Fractional s) =>
v -> s -> v
^/ (Rational
1 Rational -> Rational -> Rational
forall a. Num a => a -> a -> a
+ Rational
c) where
(Micro
a, Micro
b, Rational
c) = TAIUTCRow -> (Micro, Micro, Rational)
unwrap (TAIUTCRow -> (Micro, Micro, Rational))
-> TAIUTCRow -> (Micro, Micro, Rational)
forall a b. (a -> b) -> a -> b
$ AbsoluteTime -> Map AbsoluteTime TAIUTCRow -> TAIUTCRow
forall k. Ord k => k -> Map k TAIUTCRow -> TAIUTCRow
lookupLE AbsoluteTime
atime Map AbsoluteTime TAIUTCRow
taiMap
{-# INLINE absoluteTime' #-}
absoluteTime' :: TAIUTCMap -> Iso' UTCView AbsoluteTime
absoluteTime' :: TAIUTCMap -> Iso' UTCView AbsoluteTime
absoluteTime' (TAIUTCMap Map UTCTime TAIUTCRow
utcMap Map AbsoluteTime TAIUTCRow
taiMap) = (UTCView -> AbsoluteTime)
-> (AbsoluteTime -> UTCView) -> Iso' UTCView AbsoluteTime
forall s a b t. (s -> a) -> (b -> t) -> Iso s t a b
iso UTCView -> AbsoluteTime
toTAI AbsoluteTime -> UTCView
toUTC where
{-# INLINEABLE toTAI #-}
toTAI :: UTCView -> AbsoluteTime
toTAI :: UTCView -> AbsoluteTime
toTAI uview :: UTCView
uview@(UTCView Day
day DiffTime
_) = DiffTime -> AbsoluteTime
AbsoluteTime (DiffTime -> AbsoluteTime)
-> (Micro -> DiffTime) -> Micro -> AbsoluteTime
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Micro -> DiffTime
DiffTime (Micro -> AbsoluteTime) -> Micro -> AbsoluteTime
forall a b. (a -> b) -> a -> b
$
Micro
uts Micro -> Micro -> Micro
forall v. AdditiveGroup v => v -> v -> v
^+^ Micro
a Micro -> Micro -> Micro
forall v. AdditiveGroup v => v -> v -> v
^+^ (Micro
uts Micro -> Micro -> Micro
forall v. AdditiveGroup v => v -> v -> v
^-^ Micro
b) Micro -> Rational -> Micro
forall v s. (VectorSpace v, s ~ Scalar v) => v -> s -> v
^* Rational
c where
(Micro
a, Micro
b, Rational
c) = TAIUTCRow -> (Micro, Micro, Rational)
unwrap (TAIUTCRow -> (Micro, Micro, Rational))
-> TAIUTCRow -> (Micro, Micro, Rational)
forall a b. (a -> b) -> a -> b
$ UTCTime -> Map UTCTime TAIUTCRow -> TAIUTCRow
forall k. Ord k => k -> Map k TAIUTCRow -> TAIUTCRow
lookupLE (Overloaded Reviewed Identity UTCTime UTCTime UTCView UTCView
Iso' UTCTime UTCView
utcTime Overloaded Reviewed Identity UTCTime UTCTime UTCView UTCView
-> UTCView -> UTCTime
forall s t a b. AReview s t a b -> b -> t
# Day -> DiffTime -> UTCView
UTCView Day
day DiffTime
forall v. AdditiveGroup v => v
zeroV) Map UTCTime TAIUTCRow
utcMap
UTCRep (NominalDiffTime Micro
uts) = Overloaded Reviewed Identity UTCTime UTCTime UTCView UTCView
Iso' UTCTime UTCView
utcTime Overloaded Reviewed Identity UTCTime UTCTime UTCView UTCView
-> UTCView -> UTCTime
forall s t a b. AReview s t a b -> b -> t
# UTCView
uview
{-# INLINEABLE toUTC #-}
toUTC :: AbsoluteTime -> UTCView
toUTC :: AbsoluteTime -> UTCView
toUTC atime :: AbsoluteTime
atime@(AbsoluteTime (DiffTime Micro
ats)) = UTCView -> UTCView
fixup (UTCTime
utime UTCTime -> Getting UTCView UTCTime UTCView -> UTCView
forall s a. s -> Getting a s a -> a
^. Getting UTCView UTCTime UTCView
Iso' UTCTime UTCView
utcTime) where
row :: TAIUTCRow
row@(TAIUTCRow -> (Micro, Micro, Rational)
unwrap -> (Micro
a, Micro
b, Rational
c)) = AbsoluteTime -> Map AbsoluteTime TAIUTCRow -> TAIUTCRow
forall k. Ord k => k -> Map k TAIUTCRow -> TAIUTCRow
lookupLE AbsoluteTime
atime Map AbsoluteTime TAIUTCRow
taiMap
utime :: UTCTime
utime = NominalDiffTime -> UTCTime
UTCRep (NominalDiffTime -> UTCTime)
-> (Micro -> NominalDiffTime) -> Micro -> UTCTime
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Micro -> NominalDiffTime
NominalDiffTime (Micro -> UTCTime) -> Micro -> UTCTime
forall a b. (a -> b) -> a -> b
$ (Micro
ats Micro -> Micro -> Micro
forall v. AdditiveGroup v => v -> v -> v
^-^ Micro
a Micro -> Micro -> Micro
forall v. AdditiveGroup v => v -> v -> v
^+^ Micro
b Micro -> Rational -> Micro
forall v s. (VectorSpace v, s ~ Scalar v) => v -> s -> v
^* Rational
c) Micro -> Rational -> Micro
forall v s.
(VectorSpace v, s ~ Scalar v, Fractional s) =>
v -> s -> v
^/ (Rational
1 Rational -> Rational -> Rational
forall a. Num a => a -> a -> a
+ Rational
c)
fixup :: UTCView -> UTCView
fixup uview :: UTCView
uview@(UTCView Day
day DiffTime
dt) = if UTCTime -> Map UTCTime TAIUTCRow -> TAIUTCRow
forall k. Ord k => k -> Map k TAIUTCRow -> TAIUTCRow
lookupLE UTCTime
utime Map UTCTime TAIUTCRow
utcMap TAIUTCRow -> TAIUTCRow -> Bool
forall a. Eq a => a -> a -> Bool
== TAIUTCRow
row
then UTCView
uview else Day -> DiffTime -> UTCView
UTCView (Day
day Day -> Diff Day -> Day
forall p. AffineSpace p => p -> Diff p -> p
.-^ Year
Diff Day
1) (Rational -> DiffTime
forall t. TimeDiff t => Rational -> t
fromSeconds' Rational
86400 DiffTime -> DiffTime -> DiffTime
forall v. AdditiveGroup v => v -> v -> v
^+^ DiffTime
dt)
utcDayLength :: TAIUTCMap -> Day -> DiffTime
utcDayLength :: TAIUTCMap -> Day -> DiffTime
utcDayLength TAIUTCMap
tum Day
day = Day -> AbsoluteTime
diff (Day
day Day -> Diff Day -> Day
forall p. AffineSpace p => p -> Diff p -> p
.+^ Year
Diff Day
1) AbsoluteTime -> AbsoluteTime -> Diff AbsoluteTime
forall p. AffineSpace p => p -> p -> Diff p
.-. Day -> AbsoluteTime
diff Day
day where
diff :: Day -> AbsoluteTime
diff Day
d = Day -> DiffTime -> UTCView
UTCView Day
d DiffTime
forall v. AdditiveGroup v => v
zeroV UTCView
-> Getting AbsoluteTime UTCView AbsoluteTime -> AbsoluteTime
forall s a. s -> Getting a s a -> a
^. AnIso UTCTime UTCTime UTCView UTCView
-> Iso UTCView UTCView UTCTime UTCTime
forall s t a b. AnIso s t a b -> Iso b a t s
from AnIso UTCTime UTCTime UTCView UTCView
Iso' UTCTime UTCView
utcTime Overloaded
(->) (Const AbsoluteTime) UTCView UTCView UTCTime UTCTime
-> ((AbsoluteTime -> Const AbsoluteTime AbsoluteTime)
-> UTCTime -> Const AbsoluteTime UTCTime)
-> Getting AbsoluteTime UTCView AbsoluteTime
forall b c a. (b -> c) -> (a -> b) -> a -> c
. TAIUTCMap -> Iso' UTCTime AbsoluteTime
absoluteTime TAIUTCMap
tum
parseTAIUTCRow :: P.Parser (UTCTime, TAIUTCRow)
parseTAIUTCRow :: Parser (UTCTime, TAIUTCRow)
parseTAIUTCRow = do
Year
y <- Parser ()
P.skipSpace Parser () -> Parser ByteString Year -> Parser ByteString Year
forall a b.
Parser ByteString a -> Parser ByteString b -> Parser ByteString b
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
*> Parser ByteString Year
forall a. Integral a => Parser a
P.decimal Parser ByteString Year -> [Char] -> Parser ByteString Year
forall i a. Parser i a -> [Char] -> Parser i a
<?> [Char]
"Year"
let months :: [[Char]]
months = [ [Char]
"JAN", [Char]
"FEB", [Char]
"MAR", [Char]
"APR", [Char]
"MAY", [Char]
"JUN"
, [Char]
"JUL", [Char]
"AUG", [Char]
"SEP", [Char]
"OCT", [Char]
"NOV", [Char]
"DEC" ]
Year
m <- Year -> Year -> Year
forall a. Num a => a -> a -> a
(+) Year
1 (Year -> Year) -> Parser () -> Parser ByteString (Year -> Year)
forall a b. a -> Parser ByteString b -> Parser ByteString a
forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ Parser ()
P.skipSpace Parser ByteString (Year -> Year)
-> Parser ByteString Year -> Parser ByteString Year
forall a b.
Parser ByteString (a -> b)
-> Parser ByteString a -> Parser ByteString b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> [[Char]] -> Parser ByteString Year
indexOf [[Char]]
months Parser ByteString Year -> [Char] -> Parser ByteString Year
forall i a. Parser i a -> [Char] -> Parser i a
<?> [Char]
"Month"
Year
d <- Parser ()
P.skipSpace Parser () -> Parser ByteString Year -> Parser ByteString Year
forall a b.
Parser ByteString a -> Parser ByteString b -> Parser ByteString b
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
*> Parser ByteString Year
forall a. Integral a => Parser a
P.decimal Parser ByteString Year -> [Char] -> Parser ByteString Year
forall i a. Parser i a -> [Char] -> Parser i a
<?> [Char]
"DayOfMonth"
[ByteString] -> Parser ()
forall {t :: * -> *}.
(Foldable t, Show (t ByteString)) =>
t ByteString -> Parser ()
tokens [ByteString
"=", ByteString
"JD"]
Year
since <- Year -> Year -> Year
forall a. Num a => a -> a -> a
subtract Year
2400000 (Year -> Year) -> Parser ByteString Year -> Parser ByteString Year
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Parser ByteString Year
forall a. Integral a => Parser a
P.decimal
Parser ByteString Year
-> Parser ByteString ByteString -> Parser ByteString Year
forall a b.
Parser ByteString a -> Parser ByteString b -> Parser ByteString a
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
<* ByteString -> Parser ByteString ByteString
P.string ByteString
".5" Parser ByteString Year -> [Char] -> Parser ByteString Year
forall i a. Parser i a -> [Char] -> Parser i a
<?> [Char]
"Julian Date .5"
let ymd :: YearMonthDay
ymd = Year -> Year -> Year -> YearMonthDay
YearMonthDay Year
y Year
m Year
d
Bool -> Parser () -> Parser ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
unless (Overloaded Reviewed Identity Day Day YearMonthDay YearMonthDay
Iso' Day YearMonthDay
gregorian Overloaded Reviewed Identity Day Day YearMonthDay YearMonthDay
-> YearMonthDay -> Day
forall s t a b. AReview s t a b -> b -> t
# YearMonthDay
ymd Day -> Day -> Bool
forall a. Eq a => a -> a -> Bool
== Year -> Day
ModifiedJulianDay Year
since) (Parser () -> Parser ()) -> Parser () -> Parser ()
forall a b. (a -> b) -> a -> b
$ do
[Char] -> Parser ()
forall a. [Char] -> Parser ByteString a
forall (m :: * -> *) a. MonadFail m => [Char] -> m a
fail ([Char] -> Parser ()) -> [Char] -> Parser ()
forall a b. (a -> b) -> a -> b
$ YearMonthDay -> [Char]
forall a. Show a => a -> [Char]
show YearMonthDay
ymd [Char] -> ShowS
forall a. [a] -> [a] -> [a]
++ [Char]
" ≠ MJD " [Char] -> ShowS
forall a. [a] -> [a] -> [a]
++ Year -> [Char]
forall a. Show a => a -> [Char]
show Year
since
[Char] -> ShowS
forall a. [a] -> [a] -> [a]
++ [Char]
" ≡ " [Char] -> ShowS
forall a. [a] -> [a] -> [a]
++ Day -> [Char]
forall a. Show a => a -> [Char]
show (Year -> Day
ModifiedJulianDay Year
since)
[ByteString] -> Parser ()
forall {t :: * -> *}.
(Foldable t, Show (t ByteString)) =>
t ByteString -> Parser ()
tokens [ByteString
"TAI", ByteString
"-", ByteString
"UTC", ByteString
"="]
Rational
a <- Parser Rational
forall a. Fractional a => Parser a
P.rational Parser Rational -> [Char] -> Parser Rational
forall i a. Parser i a -> [Char] -> Parser i a
<?> [Char]
"Additive"
[ByteString] -> Parser ()
forall {t :: * -> *}.
(Foldable t, Show (t ByteString)) =>
t ByteString -> Parser ()
tokens [ByteString
"S", ByteString
"+", ByteString
"(", ByteString
"MJD", ByteString
"-"]
Year
b <- Parser ByteString Year
forall a. Integral a => Parser a
P.decimal Parser ByteString Year
-> Parser ByteString Char -> Parser ByteString Year
forall a b.
Parser ByteString a -> Parser ByteString b -> Parser ByteString a
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
<* Char -> Parser ByteString Char
P.char Char
'.' Parser ByteString Year -> [Char] -> Parser ByteString Year
forall i a. Parser i a -> [Char] -> Parser i a
<?> [Char]
"Base"
[ByteString] -> Parser ()
forall {t :: * -> *}.
(Foldable t, Show (t ByteString)) =>
t ByteString -> Parser ()
tokens [ByteString
")", ByteString
"X"]
Rational
c <- (Rational -> Rational -> Rational
forall a. Fractional a => a -> a -> a
/ NominalDiffTime -> Rational
forall t. TimeDiff t => t -> Rational
toSeconds' NominalDiffTime
posixDayLength) (Rational -> Rational) -> Parser Rational -> Parser Rational
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Parser Rational
forall a. Fractional a => Parser a
P.rational
Parser Rational -> Parser () -> Parser Rational
forall a b.
Parser ByteString a -> Parser ByteString b -> Parser ByteString a
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
<* Parser ()
P.skipSpace Parser Rational -> Parser ByteString ByteString -> Parser Rational
forall a b.
Parser ByteString a -> Parser ByteString b -> Parser ByteString a
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
<* ByteString -> Parser ByteString ByteString
P.string ByteString
"S" Parser Rational -> [Char] -> Parser Rational
forall i a. Parser i a -> [Char] -> Parser i a
<?> [Char]
"Coefficient"
(UTCTime, TAIUTCRow) -> Parser (UTCTime, TAIUTCRow)
forall a. a -> Parser ByteString a
forall (m :: * -> *) a. Monad m => a -> m a
return (Year -> UTCTime
mjdToUTC Year
since, DiffTime -> UTCTime -> Rational -> TAIUTCRow
TAIUTCRow (Rational -> DiffTime
forall t. TimeDiff t => Rational -> t
fromSeconds' Rational
a) (Year -> UTCTime
mjdToUTC Year
b) Rational
c)
where
tokens :: t ByteString -> Parser ()
tokens t ByteString
ts = (ByteString -> Parser () -> Parser ())
-> Parser () -> t ByteString -> Parser ()
forall a b. (a -> b -> b) -> b -> t a -> b
forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
foldr (\ ByteString
tok Parser ()
a -> Parser ()
P.skipSpace Parser ()
-> Parser ByteString ByteString -> Parser ByteString ByteString
forall a b.
Parser ByteString a -> Parser ByteString b -> Parser ByteString b
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> ByteString -> Parser ByteString ByteString
P.string ByteString
tok Parser ByteString ByteString -> Parser () -> Parser ()
forall a b.
Parser ByteString a -> Parser ByteString b -> Parser ByteString b
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> Parser ()
a)
Parser ()
P.skipSpace t ByteString
ts Parser () -> [Char] -> Parser ()
forall i a. Parser i a -> [Char] -> Parser i a
<?> ([Char]
"tokens " [Char] -> ShowS
forall a. [a] -> [a] -> [a]
++ t ByteString -> [Char]
forall a. Show a => a -> [Char]
show t ByteString
ts)
mjdToUTC :: Year -> UTCTime
mjdToUTC Year
mjd = Overloaded Reviewed Identity UTCTime UTCTime UTCView UTCView
Iso' UTCTime UTCView
utcTime Overloaded Reviewed Identity UTCTime UTCTime UTCView UTCView
-> UTCView -> UTCTime
forall s t a b. AReview s t a b -> b -> t
# Day -> DiffTime -> UTCView
UTCView (Year -> Day
ModifiedJulianDay Year
mjd) DiffTime
forall v. AdditiveGroup v => v
zeroV
makeTAIUTCMap :: [(UTCTime, TAIUTCRow)] -> TAIUTCMap
makeTAIUTCMap :: [(UTCTime, TAIUTCRow)] -> TAIUTCMap
makeTAIUTCMap [(UTCTime, TAIUTCRow)]
rows = Map UTCTime TAIUTCRow -> Map AbsoluteTime TAIUTCRow -> TAIUTCMap
TAIUTCMap ([(UTCTime, TAIUTCRow)] -> Map UTCTime TAIUTCRow
forall k a. Ord k => [(k, a)] -> Map k a
Map.fromList [(UTCTime, TAIUTCRow)]
rows)
([(AbsoluteTime, TAIUTCRow)] -> Map AbsoluteTime TAIUTCRow
forall k a. Ord k => [(k, a)] -> Map k a
Map.fromList ([(AbsoluteTime, TAIUTCRow)] -> Map AbsoluteTime TAIUTCRow)
-> [(AbsoluteTime, TAIUTCRow)] -> Map AbsoluteTime TAIUTCRow
forall a b. (a -> b) -> a -> b
$ (UTCTime, TAIUTCRow) -> (AbsoluteTime, TAIUTCRow)
invert ((UTCTime, TAIUTCRow) -> (AbsoluteTime, TAIUTCRow))
-> [(UTCTime, TAIUTCRow)] -> [(AbsoluteTime, TAIUTCRow)]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [(UTCTime, TAIUTCRow)]
rows) where
invert :: (UTCTime, TAIUTCRow) -> (AbsoluteTime, TAIUTCRow)
invert (UTCTime
since, TAIUTCRow
entry) = (UTCTime
since UTCTime
-> ((AbsoluteTime -> Const AbsoluteTime AbsoluteTime)
-> UTCTime -> Const AbsoluteTime UTCTime)
-> AbsoluteTime
forall s a. s -> Getting a s a -> a
^. TAIUTCMap -> Iso' UTCTime AbsoluteTime
absoluteTime TAIUTCMap
single, TAIUTCRow
entry) where
single :: TAIUTCMap
single = Map UTCTime TAIUTCRow -> Map AbsoluteTime TAIUTCRow -> TAIUTCMap
TAIUTCMap (UTCTime -> TAIUTCRow -> Map UTCTime TAIUTCRow
forall k a. k -> a -> Map k a
Map.singleton UTCTime
since TAIUTCRow
entry) Map AbsoluteTime TAIUTCRow
forall a. Monoid a => a
mempty
parseTAIUTCDAT :: S.ByteString -> Either String TAIUTCMap
parseTAIUTCDAT :: ByteString -> Either [Char] TAIUTCMap
parseTAIUTCDAT = Parser TAIUTCMap -> ByteString -> Either [Char] TAIUTCMap
forall a. Parser a -> ByteString -> Either [Char] a
P.parseOnly (Parser TAIUTCMap -> ByteString -> Either [Char] TAIUTCMap)
-> Parser TAIUTCMap -> ByteString -> Either [Char] TAIUTCMap
forall a b. (a -> b) -> a -> b
$ [(UTCTime, TAIUTCRow)] -> TAIUTCMap
makeTAIUTCMap ([(UTCTime, TAIUTCRow)] -> TAIUTCMap)
-> Parser ByteString [(UTCTime, TAIUTCRow)] -> Parser TAIUTCMap
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Parser (UTCTime, TAIUTCRow)
-> Parser () -> Parser ByteString [(UTCTime, TAIUTCRow)]
forall (f :: * -> *) a b. Alternative f => f a -> f b -> f [a]
P.manyTill
(Parser (UTCTime, TAIUTCRow)
parseTAIUTCRow Parser (UTCTime, TAIUTCRow)
-> Parser () -> Parser (UTCTime, TAIUTCRow)
forall a b.
Parser ByteString a -> Parser ByteString b -> Parser ByteString a
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
<* Parser ()
P.endOfLine) Parser ()
forall t. Chunk t => Parser t ()
P.endOfInput
{-# INLINE addAbsoluteTime #-}
addAbsoluteTime :: DiffTime -> AbsoluteTime -> AbsoluteTime
addAbsoluteTime :: DiffTime -> AbsoluteTime -> AbsoluteTime
addAbsoluteTime = (AbsoluteTime -> DiffTime -> AbsoluteTime)
-> DiffTime -> AbsoluteTime -> AbsoluteTime
forall a b c. (a -> b -> c) -> b -> a -> c
flip AbsoluteTime -> Diff AbsoluteTime -> AbsoluteTime
AbsoluteTime -> DiffTime -> AbsoluteTime
forall p. AffineSpace p => p -> Diff p -> p
(.+^)
{-# INLINE diffAbsoluteTime #-}
diffAbsoluteTime :: AbsoluteTime -> AbsoluteTime -> DiffTime
diffAbsoluteTime :: AbsoluteTime -> AbsoluteTime -> DiffTime
diffAbsoluteTime = AbsoluteTime -> AbsoluteTime -> Diff AbsoluteTime
AbsoluteTime -> AbsoluteTime -> DiffTime
forall p. AffineSpace p => p -> p -> Diff p
(.-.)
{-# INLINE utcToTAITime #-}
utcToTAITime :: TAIUTCMap -> UTCTime -> AbsoluteTime
utcToTAITime :: TAIUTCMap -> UTCTime -> AbsoluteTime
utcToTAITime TAIUTCMap
m = ((AbsoluteTime -> Const AbsoluteTime AbsoluteTime)
-> UTCTime -> Const AbsoluteTime UTCTime)
-> UTCTime -> AbsoluteTime
forall a s. Getting a s a -> s -> a
view (TAIUTCMap -> Iso' UTCTime AbsoluteTime
absoluteTime TAIUTCMap
m)
{-# INLINE taiToUTCTime #-}
taiToUTCTime :: TAIUTCMap -> AbsoluteTime -> UTCTime
taiToUTCTime :: TAIUTCMap -> AbsoluteTime -> UTCTime
taiToUTCTime TAIUTCMap
m = AReview UTCTime UTCTime AbsoluteTime AbsoluteTime
-> AbsoluteTime -> UTCTime
forall s t a b. AReview s t a b -> b -> t
review (TAIUTCMap -> Iso' UTCTime AbsoluteTime
absoluteTime TAIUTCMap
m)