on master help sign in
Allow parsing of date/time from $published$ metadata field.
757a0b9Eric Suh
src/Hakyll/Web/Page/Metadata.hs+47−16
@@ -12,6 +12,7 @@ module Hakyll.Web.Page.Metadata
12 , copyField
12 , copyField
13 , renderDateField
13 , renderDateField
14 , renderDateFieldWith
14 , renderDateFieldWith
15+ , comparePagesByDate
15 , renderModificationTime
16 , renderModificationTime
16 , renderModificationTimeWith
17 , renderModificationTimeWith
17 , copyBodyToField
18 , copyBodyToField
@@ -22,7 +23,7 @@ import Prelude hiding (id)
22import Control.Category (id)
23import Control.Category (id)
23import Control.Arrow (Arrow, arr, (>>>), (***), (&&&))
24import Control.Arrow (Arrow, arr, (>>>), (***), (&&&))
24import Data.List (intercalate)
25import Data.List (intercalate)
25−import Data.Maybe (fromMaybe)
26+import Data.Maybe (fromMaybe, fromJust, isJust)
26import Data.Time.Clock (UTCTime)
27import Data.Time.Clock (UTCTime)
27import Data.Time.Format (parseTime, formatTime)
28import Data.Time.Format (parseTime, formatTime)
28import qualified Data.Map as M
29import qualified Data.Map as M
@@ -118,13 +119,21 @@ copyField :: String -- ^ Key to copy
118 -> Page a -- ^ Resulting page
119 -> Page a -- ^ Resulting page
119copyField src dst = renderField src dst id
120copyField src dst = renderField src dst id
120
121
121−-- | When the metadata has a field called @datetime@ in a
122+-- | When the metadata has a field called @published@ in one of the
122−-- format such as "January 1, 2000 1:00 AM", then
123−-- this function can render the date.
123+-- following formats then this function can render the date.
124+--
125+-- * @Sun, 01 Feb 2000 13:00:00 UT@ (RSS date format)
126+--
127+-- * @2000-02-01T13:00:00Z@ (Atom date format)
128+--
129+-- * @February 1, 2000 1:00 PM@ (PM is usually uppercase)
130+--
131+-- * @February 1, 2000@ (assumes 12:00 AM for the time)
124--
132--
125-- Alternatively, when the metadata has a field called @path@ in a
133-- Alternatively, when the metadata has a field called @path@ in a
126−-- @folder/yyyy-mm-dd-title.extension@ format (the convention for pages),
134+-- @folder/yyyy-mm-dd-title.extension@ format (the convention for pages)
127−-- this function can render the date.
135+-- and no @published@ metadata field set, this function can render
136+-- the date.
128--
137--
129-- > renderDateField "date" "%B %e, %Y" "Date unknown"
138-- > renderDateField "date" "%B %e, %Y" "Date unknown"
130--
139--
@@ -150,20 +159,42 @@ renderDateFieldWith :: TimeLocale -- ^ Output time locale
150renderDateFieldWith locale key format defaultValue page =
159renderDateFieldWith locale key format defaultValue page =
151 setField key renderTimeString page
160 setField key renderTimeString page
152 where
161 where
153− renderTimeString = fromMaybe renderDateString $ do
162+ renderTimeString = fromMaybe defaultValue $ do
154− dateString <- getFieldMaybe "datetime" page
163+ time <- getUTCMaybe locale page
155− time <- parseTime locale "%B %e, %Y %l:%M %P" dateString :: Maybe UTCTime
156− return $ formatTime locale format time
157− renderDateString = fromMaybe renderFilePathDate $ do
158− dateString <- getFieldMaybe "datetime" page
159− time <- parseTime locale "%B %e, %Y" dateString :: Maybe UTCTime
160 return $ formatTime locale format time
164 return $ formatTime locale format time
161− renderFilePathDate = fromMaybe defaultValue $ do
165+
166+-- | Parser to try to extract and parse the time from the @published@
167+-- field or from the filename. See 'renderDateField' for more information.
168+getUTCMaybe :: TimeLocale -- ^ Output time locale
169+ -> Page a -- ^ Input page
170+ -> Maybe UTCTime -- ^ Parsed UTCTime
171+getUTCMaybe locale page = getUTCMaybe' formats
172+ where
173+ formats = [ "%a, %d %b %Y %H:%M:%S UT" -- RSS format
174+ , "%Y-%m-%dT%H:%M:%SZ" -- Atom format
175+ , "%B %e, %Y %l:%M %p"
176+ , "%B %e, %Y"
177+ ]
178+ getUTCMaybe' [] = do
162 filePath <- getFieldMaybe "path" page
179 filePath <- getFieldMaybe "path" page
163 let dateString = intercalate "-" $ take 3
180 let dateString = intercalate "-" $ take 3
164 $ splitAll "-" $ takeFileName filePath
181 $ splitAll "-" $ takeFileName filePath
165− time <- parseTime locale "%Y-%m-%d" dateString :: Maybe UTCTime
182+ parseTime locale "%Y-%m-%d" dateString :: Maybe UTCTime
166− return $ formatTime locale format time
183+ getUTCMaybe' (f:fs) = if isJust timeMaybe
184+ then timeMaybe
185+ else getUTCMaybe' fs
186+ where timeMaybe = do dateString <- getFieldMaybe "published" page
187+ parseTime locale f dateString :: Maybe UTCTime
188+
189+-- | Compare pages by the date and time parsed as in 'renderDateField',
190+-- where 'LT' implies earlier, and 'GT' implies later. For more details,
191+-- see 'renderDateField'.
192+comparePagesByDate :: Page a -> Page a -> Ordering
193+comparePagesByDate p1 p2 = compare p1UTC p2UTC
194+ where p1UTC = fromMaybe defaultTime $ getUTCMaybe defaultTimeLocale p1
195+ p2UTC = fromMaybe defaultTime $ getUTCMaybe defaultTimeLocale p2
196+ defaultTime = fromJust $ parseTime defaultTimeLocale
197+ "%B %e, %Y %l:%M %p" "January 1, 1900 12:00 AM"
167
198
168-- | Set the modification time as a field in the page
199-- | Set the modification time as a field in the page
169renderModificationTime :: String
200renderModificationTime :: String