+{-# LANGUAGE ScopedTypeVariables #-}
+
-- | (Un)picklers for data types present in The Sports Network XML
-- feed.
--
module TSN.Picklers (
pickler_tests,
xp_ambiguous_time,
+ xp_attr_option,
xp_date,
xp_date_padded,
xp_datetime,
xp_earnings,
xp_fracpart_only_double,
xp_gamedate,
+ xp_tba_int,
xp_tba_time,
xp_time,
xp_time_dots,
--
-- >>> import Data.Maybe ( fromJust )
-- >>> :{
--- let parse_date :: String -> Maybe UTCTime;
--- parse_date = parseTime defaultTimeLocale date_format;
+-- let parse_date :: String -> Maybe UTCTime
+-- parse_date = parseTime defaultTimeLocale date_format
-- :}
--
-- >>> let dates = [ "1/" ++ (d : "/1970") | d <- ['1'..'9'] ]
from_time (Just t) = formatTime defaultTimeLocale time_format t
+-- | (Un)pickle a 'Int', allowing for a value of \"TBA\" (which gets
+-- translated to 'Nothing').
+--
+-- /Examples/:
+--
+-- A failed parse will return 'Nothing':
+--
+-- >>> let tn = text_node "YO"
+-- >>> unpickleDoc xp_tba_int tn
+-- Just Nothing
+--
+-- And so will parsing a \"TBA\":
+--
+-- >>> let tn = text_node "TBA"
+-- >>> unpickleDoc xp_tba_int tn
+-- Just Nothing
+--
+-- But re-pickling 'Nothing' gives only \"TBA\":
+--
+-- >>> pickleDoc xp_tba_int Nothing
+-- NTree (XTag "/" []) [NTree (XText "TBA") []]
+--
+-- A normal integer is also parsed successfully, of course:
+--
+-- >>> let tn = text_node "110"
+-- >>> unpickleDoc xp_tba_int tn
+-- Just (Just 110)
+--
+xp_tba_int :: PU (Maybe Int)
+xp_tba_int =
+ (to_int, from_int) `xpWrap` xpText
+ where
+ to_int :: String -> Maybe Int
+ to_int = readMaybe
+
+ from_int :: Maybe Int -> String
+ from_int Nothing = "TBA"
+ from_int (Just t) = show t
+
+
-- | (Un)pickle the \<time_stamp\> element format to/from a 'UTCTime'.
-- The time_stamp elements look something like,
xp_time_stamp =
(parse_time_stamp, from_time_stamp) `xpWrapMaybe` xpText
where
+ -- | We have to re-pad the time_stamp_format with a leading and
+ -- trailing space; see the documentation of 'time_stamp_format'
+ -- for more information.
from_time_stamp :: UTCTime -> String
from_time_stamp =
- formatTime defaultTimeLocale time_stamp_format
+ formatTime defaultTimeLocale (" " ++ time_stamp_format ++ " ")
fmt = "%A, %B %-d" ++ upper_suffix ++ " (" ++ date_format_padded ++ ")"
+-- | This is a replacement for @xpOption xpFoo@ within an 'xpAttr'.
+-- There's a bug <https://github.com/UweSchmidt/hxt/issues/39> in
+-- newer versions of HXT that prevents us from using the usual
+-- 'xpOption' solution, so this is our stopgap. It should work on
+-- any type that can be unpickled with a plain read/show.
+--
+xp_attr_option :: forall a. (Read a, Show a) => PU (Maybe a)
+xp_attr_option =
+ (to_a, from_a) `xpWrap` xpText
+ where
+ to_a :: String -> Maybe a
+ to_a = readMaybe
+
+ from_a :: Maybe a -> String
+ from_a Nothing = ""
+ from_a (Just x) = show x
+
-- | Create an 'XmlTree' containing only the given text. This is
-- useful for testing (un)picklers, where we don't want to have to