From 57b33f6639498e2b1fafba2552936892e1118108 Mon Sep 17 00:00:00 2001 From: Eric Suh Date: Sun, 29 Jan 2012 15:32:16 -0500 Subject: Added parsing of an optional @datetime@ field If @datetime@ is present in the format "January 1, 2000" or "January 1, 2000 1:00 PM", renderDateField uses that date preferentially over parsing the date from the filename. --- src/Hakyll/Web/Page/Metadata.hs | 28 +++++++++++++++++++--------- 1 file changed, 19 insertions(+), 9 deletions(-) (limited to 'src') diff --git a/src/Hakyll/Web/Page/Metadata.hs b/src/Hakyll/Web/Page/Metadata.hs index efae390..69c4608 100644 --- a/src/Hakyll/Web/Page/Metadata.hs +++ b/src/Hakyll/Web/Page/Metadata.hs @@ -118,11 +118,15 @@ copyField :: String -- ^ Key to copy -> Page a -- ^ Resulting page copyField src dst = renderField src dst id --- | When the metadata has a field called @path@ in a +-- | When the metadata has a field called @datetime@ in a +-- format such as "January 1, 2000 1:00 AM", then +-- this function can render the date. +-- +-- Alternatively, when the metadata has a field called @path@ in a -- @folder/yyyy-mm-dd-title.extension@ format (the convention for pages), -- this function can render the date. -- --- > renderDate "date" "%B %e, %Y" "Date unknown" +-- > renderDateField "date" "%B %e, %Y" "Date unknown" -- -- Will render something like @January 32, 2010@. -- @@ -143,19 +147,25 @@ renderDateFieldWith :: TimeLocale -- ^ Output time locale -> String -- ^ Default value -> Page a -- ^ Target page -> Page a -- ^ Resulting page -renderDateFieldWith locale key format defaultValue = - renderField "path" key renderDate' +renderDateFieldWith locale key format defaultValue page = + setField key renderTimeString page where - renderDate' filePath = fromMaybe defaultValue $ do + renderTimeString = fromMaybe renderDateString $ do + dateString <- getFieldMaybe "datetime" page + time <- parseTime locale "%B %e, %Y %l:%M %P" dateString :: Maybe UTCTime + return $ formatTime locale format time + renderDateString = fromMaybe renderFilePathDate $ do + dateString <- getFieldMaybe "datetime" page + time <- parseTime locale "%B %e, %Y" dateString :: Maybe UTCTime + return $ formatTime locale format time + renderFilePathDate = fromMaybe defaultValue $ do + filePath <- getFieldMaybe "path" page let dateString = intercalate "-" $ take 3 $ splitAll "-" $ takeFileName filePath - time <- parseTime defaultTimeLocale - "%Y-%m-%d" - dateString :: Maybe UTCTime + time <- parseTime locale "%Y-%m-%d" dateString :: Maybe UTCTime return $ formatTime locale format time -- | Set the modification time as a field in the page --- renderModificationTime :: String -- ^ Destination key -> String -- cgit v1.2.3 From 757a0b90e3f881e19d03a0af259d4d8923e0b1a7 Mon Sep 17 00:00:00 2001 From: Eric Suh Date: Sun, 5 Feb 2012 17:30:05 -0500 Subject: 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. --- src/Hakyll/Web/Page/Metadata.hs | 63 ++++++++++++++++++++++++++++++----------- 1 file changed, 47 insertions(+), 16 deletions(-) (limited to 'src') diff --git a/src/Hakyll/Web/Page/Metadata.hs b/src/Hakyll/Web/Page/Metadata.hs index 69c4608..948c349 100644 --- a/src/Hakyll/Web/Page/Metadata.hs +++ b/src/Hakyll/Web/Page/Metadata.hs @@ -12,6 +12,7 @@ module Hakyll.Web.Page.Metadata , copyField , renderDateField , renderDateFieldWith + , comparePagesByDate , renderModificationTime , renderModificationTimeWith , copyBodyToField @@ -22,7 +23,7 @@ import Prelude hiding (id) import Control.Category (id) import Control.Arrow (Arrow, arr, (>>>), (***), (&&&)) import Data.List (intercalate) -import Data.Maybe (fromMaybe) +import Data.Maybe (fromMaybe, fromJust, isJust) import Data.Time.Clock (UTCTime) import Data.Time.Format (parseTime, formatTime) import qualified Data.Map as M @@ -118,13 +119,21 @@ copyField :: String -- ^ Key to copy -> Page a -- ^ Resulting page copyField src dst = renderField src dst id --- | When the metadata has a field called @datetime@ in a --- format such as "January 1, 2000 1:00 AM", then --- this function can render the date. +-- | When the metadata has a field called @published@ in one of the +-- following formats then this function can render the date. +-- +-- * @Sun, 01 Feb 2000 13:00:00 UT@ (RSS date format) +-- +-- * @2000-02-01T13:00:00Z@ (Atom date format) +-- +-- * @February 1, 2000 1:00 PM@ (PM is usually uppercase) +-- +-- * @February 1, 2000@ (assumes 12:00 AM for the time) -- -- Alternatively, when the metadata has a field called @path@ in a --- @folder/yyyy-mm-dd-title.extension@ format (the convention for pages), --- this function can render the date. +-- @folder/yyyy-mm-dd-title.extension@ format (the convention for pages) +-- and no @published@ metadata field set, this function can render +-- the date. -- -- > renderDateField "date" "%B %e, %Y" "Date unknown" -- @@ -150,20 +159,42 @@ renderDateFieldWith :: TimeLocale -- ^ Output time locale renderDateFieldWith locale key format defaultValue page = setField key renderTimeString page where - renderTimeString = fromMaybe renderDateString $ do - dateString <- getFieldMaybe "datetime" page - time <- parseTime locale "%B %e, %Y %l:%M %P" dateString :: Maybe UTCTime - return $ formatTime locale format time - renderDateString = fromMaybe renderFilePathDate $ do - dateString <- getFieldMaybe "datetime" page - time <- parseTime locale "%B %e, %Y" dateString :: Maybe UTCTime + renderTimeString = fromMaybe defaultValue $ do + time <- getUTCMaybe locale page return $ formatTime locale format time - renderFilePathDate = fromMaybe defaultValue $ do + +-- | Parser to try to extract and parse the time from the @published@ +-- field or from the filename. See 'renderDateField' for more information. +getUTCMaybe :: TimeLocale -- ^ Output time locale + -> Page a -- ^ Input page + -> Maybe UTCTime -- ^ Parsed UTCTime +getUTCMaybe locale page = getUTCMaybe' formats + where + formats = [ "%a, %d %b %Y %H:%M:%S UT" -- RSS format + , "%Y-%m-%dT%H:%M:%SZ" -- Atom format + , "%B %e, %Y %l:%M %p" + , "%B %e, %Y" + ] + getUTCMaybe' [] = do filePath <- getFieldMaybe "path" page let dateString = intercalate "-" $ take 3 $ splitAll "-" $ takeFileName filePath - time <- parseTime locale "%Y-%m-%d" dateString :: Maybe UTCTime - return $ formatTime locale format time + parseTime locale "%Y-%m-%d" dateString :: Maybe UTCTime + getUTCMaybe' (f:fs) = if isJust timeMaybe + then timeMaybe + else getUTCMaybe' fs + where timeMaybe = do dateString <- getFieldMaybe "published" page + parseTime locale f dateString :: Maybe UTCTime + +-- | Compare pages by the date and time parsed as in 'renderDateField', +-- where 'LT' implies earlier, and 'GT' implies later. For more details, +-- see 'renderDateField'. +comparePagesByDate :: Page a -> Page a -> Ordering +comparePagesByDate p1 p2 = compare p1UTC p2UTC + where p1UTC = fromMaybe defaultTime $ getUTCMaybe defaultTimeLocale p1 + p2UTC = fromMaybe defaultTime $ getUTCMaybe defaultTimeLocale p2 + defaultTime = fromJust $ parseTime defaultTimeLocale + "%B %e, %Y %l:%M %p" "January 1, 1900 12:00 AM" -- | Set the modification time as a field in the page renderModificationTime :: String -- cgit v1.2.3