diff options
author | Andrew Cady <d@cryptonomic.net> | 2022-09-15 13:03:47 -0400 |
---|---|---|
committer | Andrew Cady <d@cryptonomic.net> | 2022-09-15 13:03:47 -0400 |
commit | 79957e34c8c8e0f3682884a5888b12a6f336f735 (patch) | |
tree | 263fcc5b44b7a10e3db4a4bc9f525f814b39c062 | |
parent | 8b7f519c3ca5a132f21f6afbf8149ad3981d71a0 (diff) |
switch away from UTCTime
-rwxr-xr-x | countdown.hs | 87 |
1 files changed, 51 insertions, 36 deletions
diff --git a/countdown.hs b/countdown.hs index 08ca2e2..4d43224 100755 --- a/countdown.hs +++ b/countdown.hs | |||
@@ -74,37 +74,39 @@ lengthOfDay = 24 * 60 * 60 | |||
74 | ageOfUniverse :: NominalDiffTime | 74 | ageOfUniverse :: NominalDiffTime |
75 | ageOfUniverse = fromIntegral ageOfUniverseInYears * lengthOfYear | 75 | ageOfUniverse = fromIntegral ageOfUniverseInYears * lengthOfYear |
76 | 76 | ||
77 | data CustomEvent = TimeChanged UTCTime deriving Show | 77 | data CustomEvent = TimeChanged ZonedTime deriving Show |
78 | 78 | ||
79 | data St = | 79 | data St = |
80 | St { _stLastBrickEvent :: Maybe (BrickEvent () CustomEvent) | 80 | St { _stLastBrickEvent :: Maybe (BrickEvent () CustomEvent) |
81 | , _stClockTime :: UTCTime | 81 | , _stClockTime :: LocalTime |
82 | , _stDisplayTime :: UTCTime | 82 | , _stDisplayTime :: LocalTime |
83 | , _stNextEvent :: Maybe UTCTime | 83 | , _stNextEvent :: Maybe UTCTime |
84 | } | 84 | } |
85 | 85 | ||
86 | makeLenses ''St | 86 | makeLenses ''St |
87 | 87 | ||
88 | yearNumber :: ZonedTime -> Integer | 88 | yearNumber :: LocalTime -> Integer |
89 | yearNumber (ZonedTime t _) = y | 89 | yearNumber (LocalTime t _) = y |
90 | where | 90 | where |
91 | (y, _, _) = toGregorian . localDay $ t | 91 | (y, _, _) = toGregorian t |
92 | 92 | ||
93 | yearStart :: ZonedTime -> ZonedTime | 93 | yearStart :: LocalTime -> LocalTime |
94 | yearStart (ZonedTime t z) = (ZonedTime t' z) | 94 | yearStart (LocalTime d _) = LocalTime d' t' |
95 | where | 95 | where |
96 | t' = LocalTime (fromGregorian y 1 1) (TimeOfDay 0 0 0) | 96 | d' = fromGregorian y 1 1 |
97 | (y, _, _) = toGregorian . localDay $ t | 97 | t' = TimeOfDay 0 0 0 |
98 | (y, _, _) = toGregorian d | ||
98 | 99 | ||
99 | yearEnd :: ZonedTime -> ZonedTime | 100 | yearEnd :: LocalTime -> LocalTime |
100 | yearEnd (ZonedTime t z) = (ZonedTime t' z) | 101 | yearEnd (LocalTime d _) = LocalTime d' t' |
101 | where | 102 | where |
102 | t' = LocalTime (fromGregorian (y + 1) 1 1) (TimeOfDay 0 0 0) | 103 | d' = fromGregorian (y + 1) 1 1 |
103 | (y, _, _) = toGregorian . localDay $ t | 104 | t' = TimeOfDay 0 0 0 |
105 | (y, _, _) = toGregorian d | ||
104 | 106 | ||
105 | 107 | ||
106 | dayNumOfYear :: ZonedTime -> Int | 108 | dayNumOfYear :: LocalTime -> Int |
107 | dayNumOfYear t = snd $ toOrdinalDate $ localDay $ zonedTimeToLocalTime t | 109 | dayNumOfYear = snd . toOrdinalDate . localDay |
108 | 110 | ||
109 | pluralize :: Integral i => i -> String | 111 | pluralize :: Integral i => i -> String |
110 | pluralize 1 = "" | 112 | pluralize 1 = "" |
@@ -121,11 +123,11 @@ drawUI st = [a] | |||
121 | -- <=> | 123 | -- <=> |
122 | (str "\n") | 124 | (str "\n") |
123 | <=> | 125 | <=> |
124 | (countdownWidget (isSimulatedTime st) $ utcToZonedTime zone $ st ^. stDisplayTime) | 126 | (countdownWidget (isSimulatedTime st) $ st ^. stDisplayTime) |
125 | 127 | ||
126 | printRemain unit quantity = printf "%d %s%s remain%s" | 128 | printRemain unit quantity = printf "%d %s%s remain%s" |
127 | 129 | ||
128 | countdownWidget :: Bool -> ZonedTime -> Widget n | 130 | countdownWidget :: Bool -> LocalTime -> Widget n |
129 | countdownWidget isSimulated t = | 131 | countdownWidget isSimulated t = |
130 | (hCenter (borderWithLabel (str $ printf "Current time%s" (if isSimulated then " (SIMULATED)" else "")) $ | 132 | (hCenter (borderWithLabel (str $ printf "Current time%s" (if isSimulated then " (SIMULATED)" else "")) $ |
131 | padLeftRight 3 $ (str (formatTime defaultTimeLocale "%A, %B %e%n%Y-%m-%d %r" t)))) | 133 | padLeftRight 3 $ (str (formatTime defaultTimeLocale "%A, %B %e%n%Y-%m-%d %r" t)))) |
@@ -179,7 +181,7 @@ countdownWidget isSimulated t = | |||
179 | numDays = daysInYear t | 181 | numDays = daysInYear t |
180 | yearLength = fromIntegral numDays * nominalDay | 182 | yearLength = fromIntegral numDays * nominalDay |
181 | -- yearLength = (zonedTimeToLocalTime $ yearEnd t) `diffLocalTime` (zonedTimeToLocalTime $ yearStart t) | 183 | -- yearLength = (zonedTimeToLocalTime $ yearEnd t) `diffLocalTime` (zonedTimeToLocalTime $ yearStart t) |
182 | yearElapsed = (zonedTimeToLocalTime t) `diffLocalTime` (zonedTimeToLocalTime $ yearStart t) | 184 | yearElapsed = t `diffLocalTime` (yearStart t) |
183 | 185 | ||
184 | daysLeft = numDays - dayNum | 186 | daysLeft = numDays - dayNum |
185 | hoursLeft = minutesLeft / 60 | 187 | hoursLeft = minutesLeft / 60 |
@@ -208,10 +210,10 @@ nextWholeSecond (UTCTime day dayTime) = (UTCTime day dayTime') | |||
208 | threadDelayUntil :: UTCTime -> UTCTime -> IO () | 210 | threadDelayUntil :: UTCTime -> UTCTime -> IO () |
209 | threadDelayUntil now t = threadDelay $ microsecondsUntil now t | 211 | threadDelayUntil now t = threadDelay $ microsecondsUntil now t |
210 | 212 | ||
211 | queueNextEvent :: MonadIO m => BChan CustomEvent -> UTCTime -> m () | 213 | queueNextEvent :: MonadIO m => BChan CustomEvent -> ZonedTime -> m () |
212 | queueNextEvent chan now = liftIO . void . forkIO $ do | 214 | queueNextEvent chan (zonedTimeToUTC -> now) = liftIO . void . forkIO $ do |
213 | threadDelayUntil now (nextWholeSecond now) | 215 | threadDelayUntil now (nextWholeSecond now) |
214 | getCurrentTime >>= writeBChan chan . TimeChanged | 216 | getZonedTime >>= writeBChan chan . TimeChanged |
215 | 217 | ||
216 | isSimulatedTime :: St -> Bool | 218 | isSimulatedTime :: St -> Bool |
217 | isSimulatedTime st = st ^. stDisplayTime /= st ^. stClockTime | 219 | isSimulatedTime st = st ^. stDisplayTime /= st ^. stClockTime |
@@ -220,26 +222,39 @@ handleEvent :: BChan CustomEvent -> St -> BrickEvent () CustomEvent -> EventM () | |||
220 | handleEvent chan st e = | 222 | handleEvent chan st e = |
221 | case e of | 223 | case e of |
222 | VtyEvent (V.EvKey V.KEsc []) -> halt st | 224 | VtyEvent (V.EvKey V.KEsc []) -> halt st |
223 | VtyEvent (V.EvKey V.KPageUp []) -> cont $ st & stDisplayTime %~ (addUTCTime lengthOfDay) | 225 | VtyEvent (V.EvKey V.KPageUp []) -> cont $ st & stDisplayTime %~ (addLocalTime lengthOfDay) |
224 | VtyEvent (V.EvKey V.KPageDown []) -> cont $ st & stDisplayTime %~ (addUTCTime (-lengthOfDay)) | 226 | VtyEvent (V.EvKey V.KPageDown []) -> cont $ st & stDisplayTime %~ (addLocalTime (-lengthOfDay)) |
225 | VtyEvent (V.EvKey V.KUp []) -> cont $ st & stDisplayTime %~ (addUTCTime (60 * 60)) | 227 | VtyEvent (V.EvKey V.KUp []) -> cont $ st & stDisplayTime %~ (addLocalTime (60 * 60)) |
226 | VtyEvent (V.EvKey V.KDown []) -> cont $ st & stDisplayTime %~ (addUTCTime (-60 * 60)) | 228 | VtyEvent (V.EvKey V.KDown []) -> cont $ st & stDisplayTime %~ (addLocalTime (-60 * 60)) |
227 | VtyEvent (V.EvKey V.KRight []) -> cont $ st & stDisplayTime %~ (addUTCTime (60)) | 229 | VtyEvent (V.EvKey V.KRight []) -> cont $ st & stDisplayTime %~ (addLocalTime (60)) |
228 | VtyEvent (V.EvKey V.KLeft []) -> cont $ st & stDisplayTime %~ (addUTCTime (-60)) | 230 | VtyEvent (V.EvKey V.KLeft []) -> cont $ st & stDisplayTime %~ (addLocalTime (-60)) |
229 | VtyEvent (V.EvKey V.KRight [MShift]) -> cont $ st & stDisplayTime %~ (addUTCTime (1)) | 231 | VtyEvent (V.EvKey V.KRight [MShift]) -> cont $ st & stDisplayTime %~ (addLocalTime (1)) |
230 | VtyEvent (V.EvKey V.KLeft [MShift]) -> cont $ st & stDisplayTime %~ (addUTCTime (-1)) | 232 | VtyEvent (V.EvKey V.KLeft [MShift]) -> cont $ st & stDisplayTime %~ (addLocalTime (-1)) |
231 | VtyEvent (V.EvKey V.KHome []) -> cont $ st & stDisplayTime .~ (st ^. stClockTime) | 233 | VtyEvent (V.EvKey V.KHome []) -> cont $ st & stDisplayTime .~ (st ^. stClockTime) |
234 | VtyEvent (V.EvKey V.KHome [MShift]) -> cont $ st & stDisplayTime .~ (newYearsEveNoon $ st ^. stClockTime) | ||
235 | VtyEvent (V.EvKey V.KHome [MCtrl]) -> cont $ st & stDisplayTime .~ (newYearsEveLast10 $ st ^. stClockTime) | ||
232 | VtyEvent _ -> cont st | 236 | VtyEvent _ -> cont st |
233 | AppEvent (TimeChanged now) -> do | 237 | AppEvent (TimeChanged now) -> do |
234 | queueNextEvent chan now | 238 | queueNextEvent chan now |
235 | let oldTime = st ^. stClockTime | 239 | let oldTime = st ^. stClockTime |
236 | cont $ st & stClockTime .~ now & stDisplayTime %~ (addUTCTime (now `diffUTCTime` oldTime)) | 240 | cont $ st & stClockTime .~ (zonedTimeToLocalTime now) & stDisplayTime %~ (addLocalTime ((zonedTimeToLocalTime now) `diffLocalTime` oldTime)) |
237 | _ -> cont st | 241 | _ -> cont st |
238 | where | 242 | where |
239 | cont s = do | 243 | cont s = do |
240 | continue $ s & stLastBrickEvent .~ (Just e) | 244 | continue $ s & stLastBrickEvent .~ (Just e) |
241 | 245 | ||
242 | initialState :: UTCTime -> St | 246 | newYearsEveLast10 :: LocalTime -> LocalTime |
247 | newYearsEveLast10 t = addLocalTime (12 * 60 * 60 - 10) $ newYearsEveNoon t | ||
248 | |||
249 | newYearsEveNoon :: LocalTime -> LocalTime | ||
250 | newYearsEveNoon (LocalTime d (TimeOfDay _ _ s)) = LocalTime d' t | ||
251 | where | ||
252 | (y, _) = toOrdinalDate d | ||
253 | d' = fromOrdinalDate y 366 | ||
254 | t = TimeOfDay 12 0 s' | ||
255 | s' = s `mod'` 1 -- keep the fractional part so we still tick the display on the same schedule | ||
256 | |||
257 | initialState :: LocalTime -> St | ||
243 | initialState t = | 258 | initialState t = |
244 | St { _stLastBrickEvent = Nothing | 259 | St { _stLastBrickEvent = Nothing |
245 | , _stClockTime = t | 260 | , _stClockTime = t |
@@ -247,8 +262,8 @@ initialState t = | |||
247 | , _stNextEvent = Nothing | 262 | , _stNextEvent = Nothing |
248 | } | 263 | } |
249 | 264 | ||
250 | daysInYear :: ZonedTime -> Int | 265 | daysInYear :: LocalTime -> Int |
251 | daysInYear (toGregorian . localDay . zonedTimeToLocalTime -> (y, _, _)) = if isLeapYear y then 366 else 365 | 266 | daysInYear (toGregorian . localDay -> (y, _, _)) = if isLeapYear y then 366 else 365 |
252 | 267 | ||
253 | theBaseAttr :: A.AttrName | 268 | theBaseAttr :: A.AttrName |
254 | theBaseAttr = A.attrName "theBase" | 269 | theBaseAttr = A.attrName "theBase" |
@@ -294,6 +309,6 @@ main = do | |||
294 | 309 | ||
295 | let buildVty = V.mkVty V.defaultConfig | 310 | let buildVty = V.mkVty V.defaultConfig |
296 | initialVty <- buildVty | 311 | initialVty <- buildVty |
297 | now <- getCurrentTime | 312 | now <- getZonedTime |
298 | queueNextEvent chan now | 313 | queueNextEvent chan now |
299 | void $ customMain initialVty buildVty (Just chan) (theApp chan) (initialState now) | 314 | void $ customMain initialVty buildVty (Just chan) (theApp chan) (initialState $ zonedTimeToLocalTime now) |