on master help sign in
Allow parsing of date/time from $published$ metadata field.

Allows parsing of date/time from $published$ metadata field by a number of formats. Also includes a function to compare pages by this parsed date, since in that case filename-based sorting is no longer as useful for pagelist and RSS feed generation.

commit757a0b90e3f881e19d03a0af259d4d8923e0b1a7 authorEric Suh <contact@ericsuh.com> dateSun 5 Feb 2012, 17:30 (15 years ago) parent57b33f6
1 file changed+47−16
src/Hakyll/Web/Page/Metadata.hs+47−16
src/Hakyll/Web/Page/Metadata.hs+47−16
@@ -12,6 +12,7 @@ module Hakyll.Web.Page.Metadata
1212 , copyField
1313 , renderDateField
1414 , renderDateFieldWith
15+ , comparePagesByDate
1516 , renderModificationTime
1617 , renderModificationTimeWith
1718 , copyBodyToField
@@ -22,7 +23,7 @@ import Prelude hiding (id)
2223import Control.Category (id)
2324import Control.Arrow (Arrow, arr, (>>>), (***), (&&&))
2425import Data.List (intercalate)
25−import Data.Maybe (fromMaybe)
26+import Data.Maybe (fromMaybe, fromJust, isJust)
2627import Data.Time.Clock (UTCTime)
2728import Data.Time.Format (parseTime, formatTime)
2829import qualified Data.Map as M
@@ -118,13 +119,21 @@ copyField :: String -- ^ Key to copy
118119 -> Page a -- ^ Resulting page
119120copyField src dst = renderField src dst id
120121
121−-- | When the metadata has a field called @datetime@ in a
122−-- format such as "January 1, 2000 1:00 AM", then
123−-- this function can render the date.
122+-- | When the metadata has a field called @published@ in one of the
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)
124132--
125133-- Alternatively, when the metadata has a field called @path@ in a
126−-- @folder/yyyy-mm-dd-title.extension@ format (the convention for pages),
127−-- this function can render the date.
134+-- @folder/yyyy-mm-dd-title.extension@ format (the convention for pages)
135+-- and no @published@ metadata field set, this function can render
136+-- the date.
128137--
129138-- > renderDateField "date" "%B %e, %Y" "Date unknown"
130139--
@@ -150,20 +159,42 @@ renderDateFieldWith :: TimeLocale -- ^ Output time locale
150159renderDateFieldWith locale key format defaultValue page =
151160 setField key renderTimeString page
152161 where
153− renderTimeString = fromMaybe renderDateString $ do
154− dateString <- getFieldMaybe "datetime" 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
162+ renderTimeString = fromMaybe defaultValue $ do
163+ time <- getUTCMaybe locale page
160164 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
162179 filePath <- getFieldMaybe "path" page
163180 let dateString = intercalate "-" $ take 3
164181 $ splitAll "-" $ takeFileName filePath
165− time <- parseTime locale "%Y-%m-%d" dateString :: Maybe UTCTime
166− return $ formatTime locale format time
182+ parseTime locale "%Y-%m-%d" dateString :: Maybe UTCTime
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"
167198
168199-- | Set the modification time as a field in the page
169200renderModificationTime :: String