advent-of-code-api 0.2.6.2 → 0.2.7.0
raw patch · 5 files changed
+100/−32 lines, 5 filesdep +time-compatPVP: major bump suggested
API removals or changes: PVP suggests a major version bump
Dependencies added: time-compat
API changes (from Hackage documentation)
- Advent.Types: [dlbmTime] :: DailyLeaderboardMember -> UTCTime
+ Advent.Types: [dlbmDecTime] :: DailyLeaderboardMember -> NominalDiffTime
+ Advent.Types: challengeReleaseTime :: Integer -> Day -> ZonedTime
+ Advent.Types: dlbmCompleteTime :: Integer -> Day -> NominalDiffTime -> ZonedTime
+ Advent.Types: dlbmTime :: Day -> NominalDiffTime -> NominalDiffTime
- Advent: challengeReleaseTime :: Integer -> Day -> UTCTime
+ Advent: challengeReleaseTime :: Integer -> Day -> ZonedTime
- Advent.Types: DLBM :: Rank -> UTCTime -> Either Integer Text -> Maybe Text -> Maybe Text -> Bool -> DailyLeaderboardMember
+ Advent.Types: DLBM :: Rank -> NominalDiffTime -> Either Integer Text -> Maybe Text -> Maybe Text -> Bool -> DailyLeaderboardMember
Files
- CHANGELOG.md +20/−0
- advent-of-code-api.cabal +3/−2
- src/Advent.hs +1/−9
- src/Advent/API.hs +24/−19
- src/Advent/Types.hs +52/−2
CHANGELOG.md view
@@ -1,6 +1,26 @@ Changelog ========= +Version 0.2.7.0+---------------++*December 4, 2019*++<https://github.com/mstksg/advent-of-code-api/releases/tag/v0.2.7.0>++* Throughout the library, change from `UTCTime` to `ZonedTime`, except for+ situations where the official site uses actual UTCTime. The main change is+ in `challengeReleaseTime`.+* `challengeReleaseTime` moved to *Advent.Types* but re-exported from+ *Advent*.+* `dlbmTime` changed from `UTCTime` to `NominalDiffTime` `dlbmDecTime`, which+ is time from December 1st. This is because we don't have information about+ the year from the HTML returned alone. This fixes a bug where the time+ would always be in 1970.+* To convert `dlbmDecTime` back into a useful time,added `dlbmCompleteTime`+ to get the actual time of completion (as a `ZonedTime`), and `dlbmTime` to+ get the `NominalDiffTime` representing how long the challenge took.+ Version 0.2.6.0 ---------------
advent-of-code-api.cabal view
@@ -4,10 +4,10 @@ -- -- see: https://github.com/sol/hpack ----- hash: 29142f7dd051872d37ae0e834ec0dd60a68dc650d60dfa4d913add426cceb3c3+-- hash: 9603fe2e4c2300c11c4f62de11e190053b3d67925bc185d13a30248d5f13406d name: advent-of-code-api-version: 0.2.6.2+version: 0.2.7.0 synopsis: Advent of Code REST API bindings and servant API description: Haskell bindings for Advent of Code REST API and a servant API. Please use responsibly! See README.md or "Advent" module for an introduction and@@ -73,6 +73,7 @@ , tagsoup , text , time+ , time-compat >=1.9 default-language: Haskell2010 test-suite advent-of-code-api-test
src/Advent.hs view
@@ -463,7 +463,7 @@ :: Integer -- ^ year -> Day -- ^ day -> IO NominalDiffTime-timeToRelease y d = (challengeReleaseTime y d `diffUTCTime`) <$> getCurrentTime+timeToRelease y d = (zonedTimeToUTC (challengeReleaseTime y d) `diffUTCTime`) <$> getCurrentTime -- | Check if a challenge has been released yet. challengeReleased@@ -471,14 +471,6 @@ -> Day -- ^ day -> IO Bool challengeReleased y = fmap (<= 0) . timeToRelease y---- | Prompt release time-challengeReleaseTime- :: Integer -- ^ year- -> Day -- ^ day- -> UTCTime-challengeReleaseTime y d = UTCTime (fromGregorian y 12 (fromIntegral (dayInt d)))- (5 * 60 * 60) -- | Utility to get the current time on AoC servers. Basically just gets the current -- time in Eastern Standard Time. This is only as accurate as your
src/Advent/API.hs view
@@ -54,32 +54,35 @@ import Data.Char import Data.Finite import Data.Foldable-import Data.List.NonEmpty (NonEmpty(..))-import Data.Map (Map)+import Data.List.NonEmpty (NonEmpty(..))+import Data.Map (Map) import Data.Maybe import Data.Ord import Data.Proxy-import Data.Text (Text)-import Data.Time.Format-import Data.Time.LocalTime+import Data.Text (Text)+import Data.Time hiding (Day) import GHC.TypeLits import Servant.API import Servant.Client-import Text.HTML.TagSoup.Tree (TagTree(..))-import Text.Read (readMaybe)-import qualified Data.ByteString.Lazy as BSL-import qualified Data.List.NonEmpty as NE-import qualified Data.Map as M-import qualified Data.Text as T-import qualified Data.Text.Encoding as T-import qualified Network.HTTP.Media as M-import qualified Text.HTML.TagSoup as H-import qualified Text.HTML.TagSoup.Tree as H+import Text.HTML.TagSoup.Tree (TagTree(..))+import Text.Read (readMaybe)+import qualified Data.ByteString.Lazy as BSL+import qualified Data.List.NonEmpty as NE+import qualified Data.Map as M+import qualified Data.Text as T+import qualified Data.Text.Encoding as T+import qualified Network.HTTP.Media as M+import qualified Text.HTML.TagSoup as H+import qualified Text.HTML.TagSoup.Tree as H #if !MIN_VERSION_base(4,11,0) import Data.Semigroup ((<>)) #endif +#if !MIN_VERSION_time(1,9,0)+import Data.Time.LocalTime.Compat+#endif+ -- | Raw "text/plain" MIME type data RawText @@ -144,10 +147,10 @@ dlbmRank <- fmap Rank . packFinite . subtract 1 =<< readMaybe . filter isDigit . T.unpack . fst =<< findTag uni "span" (Just "leaderboard-position")- dlbmTime <- fmap (localTimeToUTC (read "EST"))- . parseTimeM True defaultTimeLocale "%b %d %H:%M:%S"- . T.unpack . fst- =<< findTag uni "span" (Just "leaderboard-time")+ dlbmDecTime <- fmap mkDiff+ . parseTimeM True defaultTimeLocale "%b %d %H:%M:%S"+ . T.unpack . fst+ =<< findTag uni "span" (Just "leaderboard-time") dlbmUser <- eitherUser tr pure DLBM{..} where@@ -170,6 +173,8 @@ where dlb1 = (Just Nothing , dlb { dlbStar1 = M.insert dlbmRank m (dlbStar1 dlb) }) dlb2 = (Just (Just dlbmRank), dlb { dlbStar2 = M.insert dlbmRank m (dlbStar2 dlb) })+ mkDiff t = t `diffLocalTime` decemberFirst+ decemberFirst = LocalTime (fromGregorian 1970 12 1) midnight instance FromTags "div" GlobalLeaderboard where fromTags _ = Just . GLB . reScore . M.fromListWith (<>)
src/Advent/Types.hs view
@@ -47,6 +47,9 @@ , partInt , partChar , fullDailyBoard+ , dlbmCompleteTime+ , dlbmTime+ , challengeReleaseTime -- * Internal , parseSubmitRes ) where@@ -54,6 +57,7 @@ import Control.Applicative import Data.Aeson import Data.Aeson.Types+import Data.Bifunctor import Data.Char import Data.Finite import Data.Foldable@@ -63,7 +67,7 @@ import Data.Maybe import Data.Profunctor import Data.Text (Text)-import Data.Time.Clock+import Data.Time hiding (Day) import Data.Time.Clock.POSIX import Data.Typeable import Data.Void@@ -83,6 +87,10 @@ import Data.Semigroup ((<>)) #endif +#if !MIN_VERSION_time(1,9,0)+import Data.Time.LocalTime.Compat+#endif+ -- | Describes the day: a number between 1 and 25 inclusive. -- -- Represented by a 'Finite' ranging from 0 to 24 inclusive; you should@@ -172,7 +180,12 @@ -- @since 0.2.3.0 data DailyLeaderboardMember = DLBM { dlbmRank :: Rank- , dlbmTime :: UTCTime+ -- | Time from midnight EST of December 1st for that event. Use+ -- 'dlbmCompleteTime' to convert to an actual time for event+ -- completion, and 'dlbmTime' to get the time it took to solve.+ --+ -- @since 0.2.7.0+ , dlbmDecTime :: NominalDiffTime -- ^ time from midnight EST. , dlbmUser :: Either Integer Text , dlbmLink :: Maybe Text , dlbmImage :: Maybe Text@@ -180,6 +193,26 @@ } deriving (Show, Eq, Ord, Typeable, Generic) +-- | Turn a 'dlbmDecTime' field into a 'ZonedTime' for the actual+-- completion of the puzzle, based on the year and day of event.+--+-- @since 0.2.7.0+dlbmCompleteTime :: Integer -> Day -> NominalDiffTime -> ZonedTime+dlbmCompleteTime y d t = r+ { zonedTimeToLocalTime = dlbmTime d t `addLocalTime` zonedTimeToLocalTime r+ }+ where+ r = challengeReleaseTime y d++-- | Turn a 'dlbmDecTime' field into a 'NominalDiffTime' representing the+-- actual amount of time taken to complete the puzzle.+--+-- @since 0.2.7.0+dlbmTime :: Day -> NominalDiffTime -> NominalDiffTime+dlbmTime d = uncurry daysAndTimeOfDayToTime+ . first (subtract (dayInt d - 1))+ . timeToDaysAndTimeOfDay+ -- | Daily leaderboard, containing Star 1 and Star 2 completions -- -- @since 0.2.3.0@@ -455,3 +488,20 @@ :: DailyLeaderboard -> Bool fullDailyBoard DLB{..} = (M.size dlbStar1 + M.size dlbStar2) >= 200++-- | Prompt release time.+--+-- Changed from 'UTCTime' to 'ZonedTime' in v0.2.7.0. To use as+-- a 'UTCTime', use 'zonedTimeToUTC'.+challengeReleaseTime+ :: Integer -- ^ year+ -> Day -- ^ day+ -> ZonedTime+challengeReleaseTime y d = ZonedTime+ { zonedTimeToLocalTime = LocalTime+ { localDay = fromGregorian y 12 (fromIntegral (dayInt d))+ , localTimeOfDay = midnight+ }+ , zonedTimeZone = read "EST"+ }+