iCalendar 0.1 → 0.2
raw patch · 10 files changed
+325/−256 lines, 10 filesdep ~containersPVP ok
version bump matches the API change (PVP)
Dependency ranges changed: containers
API changes (from Hackage documentation)
- Text.ICalendar.Types: instance Default Range
+ Text.ICalendar.Printer: instance ToParam Range
+ Text.ICalendar.Types: instance Monoid VCalendar
- Text.ICalendar.Types: RecurrenceIdDate :: Date -> Range -> OtherParams -> RecurrenceId
+ Text.ICalendar.Types: RecurrenceIdDate :: Date -> Maybe Range -> OtherParams -> RecurrenceId
- Text.ICalendar.Types: RecurrenceIdDateTime :: DateTime -> Range -> OtherParams -> RecurrenceId
+ Text.ICalendar.Types: RecurrenceIdDateTime :: DateTime -> Maybe Range -> OtherParams -> RecurrenceId
- Text.ICalendar.Types: VCalendar :: ProdId -> ICalVersion -> Scale -> Maybe Method -> Set OtherProperty -> Set VTimeZone -> Set VEvent -> Set VTodo -> Set VJournal -> Set VFreeBusy -> Set VOther -> VCalendar
+ Text.ICalendar.Types: VCalendar :: ProdId -> ICalVersion -> Scale -> Maybe Method -> Set OtherProperty -> Map Text VTimeZone -> Map (Text, Maybe (Either Date DateTime)) VEvent -> Map (Text, Maybe (Either Date DateTime)) VTodo -> Map (Text, Maybe (Either Date DateTime)) VJournal -> Map Text VFreeBusy -> Set VOther -> VCalendar
- Text.ICalendar.Types: recurrenceIdRange :: RecurrenceId -> Range
+ Text.ICalendar.Types: recurrenceIdRange :: RecurrenceId -> Maybe Range
- Text.ICalendar.Types: vcEvents :: VCalendar -> Set VEvent
+ Text.ICalendar.Types: vcEvents :: VCalendar -> Map (Text, Maybe (Either Date DateTime)) VEvent
- Text.ICalendar.Types: vcFreeBusys :: VCalendar -> Set VFreeBusy
+ Text.ICalendar.Types: vcFreeBusys :: VCalendar -> Map Text VFreeBusy
- Text.ICalendar.Types: vcJournals :: VCalendar -> Set VJournal
+ Text.ICalendar.Types: vcJournals :: VCalendar -> Map (Text, Maybe (Either Date DateTime)) VJournal
- Text.ICalendar.Types: vcTimeZones :: VCalendar -> Set VTimeZone
+ Text.ICalendar.Types: vcTimeZones :: VCalendar -> Map Text VTimeZone
- Text.ICalendar.Types: vcTodos :: VCalendar -> Set VTodo
+ Text.ICalendar.Types: vcTodos :: VCalendar -> Map (Text, Maybe (Either Date DateTime)) VTodo
Files
- Text/ICalendar.hs +3/−3
- Text/ICalendar/Parser.hs +15/−15
- Text/ICalendar/Parser/Common.hs +36/−34
- Text/ICalendar/Parser/Components.hs +30/−14
- Text/ICalendar/Parser/Content.hs +12/−12
- Text/ICalendar/Parser/Parameters.hs +17/−17
- Text/ICalendar/Parser/Properties.hs +21/−22
- Text/ICalendar/Printer.hs +38/−31
- Text/ICalendar/Types.hs +150/−106
- iCalendar.cabal +3/−2
Text/ICalendar.hs view
@@ -1,9 +1,9 @@ module Text.ICalendar- ( module Text.ICalendar.Types- , module Text.ICalendar.Parser+ ( module Text.ICalendar.Parser , module Text.ICalendar.Printer+ , module Text.ICalendar.Types ) where -import Text.ICalendar.Types import Text.ICalendar.Parser import Text.ICalendar.Printer+import Text.ICalendar.Types
Text/ICalendar/Parser.hs view
@@ -1,31 +1,31 @@-{-# LANGUAGE OverloadedStrings #-}-{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE TypeSynonymInstances #-}-{-# LANGUAGE FlexibleInstances #-} module Text.ICalendar.Parser ( parseICal , parseICalFile , DecodingFunctions(..) ) where -import Prelude-import Control.Applicative-import Control.Monad-import Control.Monad.Error-import Control.Monad.RWS ( runRWS )-import Data.ByteString.Lazy (ByteString)+import Control.Applicative+import Control.Monad+import Control.Monad.Error+import Control.Monad.RWS (runRWS)+import Data.ByteString.Lazy (ByteString) import qualified Data.ByteString.Lazy.Char8 as B-import Data.Monoid+import Data.Monoid+import Prelude -import Text.Parsec.Prim hiding (many, (<|>))-import Text.Parsec.Pos import Text.Parsec.ByteString.Lazy ()-import Text.Parsec.Text.Lazy ()+import Text.Parsec.Pos+import Text.Parsec.Prim hiding (many, (<|>))+import Text.Parsec.Text.Lazy () -import Text.ICalendar.Types import Text.ICalendar.Parser.Common-import Text.ICalendar.Parser.Content import Text.ICalendar.Parser.Components+import Text.ICalendar.Parser.Content+import Text.ICalendar.Types -- | Parse a ByteString containing iCalendar data.
Text/ICalendar/Parser/Common.hs view
@@ -1,38 +1,39 @@-{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE ScopedTypeVariables #-} module Text.ICalendar.Parser.Common where -import Prelude hiding (mapM)-import Control.Applicative-import Control.Arrow (second)-import Control.Monad.Error hiding (mapM)-import Control.Monad.RWS ( RWS, MonadWriter(tell) , MonadState(get, put), asks- , modify )-import Data.ByteString.Lazy.Char8 (ByteString)-import qualified Data.ByteString.Lazy.Char8 as B+import Control.Applicative+import Control.Arrow (second)+import Control.Monad.Error hiding (mapM)+import Control.Monad.RWS (MonadState (get, put),+ MonadWriter (tell), RWS, asks,+ modify) import qualified Data.ByteString.Lazy.Builder as Bu-import Data.CaseInsensitive (CI)-import qualified Data.CaseInsensitive as CI-import Data.Char-import Data.Default-import Data.List (partition)-import Data.Maybe-import Data.Monoid-import Data.Set (Set)-import qualified Data.Set as S-import Data.Text.Lazy (Text)-import qualified Data.Text.Lazy as T-import qualified Data.Text.Lazy.Encoding as TE-import Data.Time ( UTCTime(UTCTime), LocalTime(LocalTime), Day- , TimeOfDay())-import qualified Data.Time as Time-import Data.Traversable (mapM)-import qualified Network.URI as URI-import qualified System.Locale as L+import Data.ByteString.Lazy.Char8 (ByteString)+import qualified Data.ByteString.Lazy.Char8 as B+import Data.CaseInsensitive (CI)+import qualified Data.CaseInsensitive as CI+import Data.Char+import Data.Default+import Data.List (partition)+import Data.Maybe+import Data.Monoid+import Data.Set (Set)+import qualified Data.Set as S+import Data.Text.Lazy (Text)+import qualified Data.Text.Lazy as T+import qualified Data.Text.Lazy.Encoding as TE+import Data.Time (Day, LocalTime (LocalTime),+ TimeOfDay (), UTCTime (UTCTime))+import qualified Data.Time as Time+import Data.Traversable (mapM)+import qualified Network.URI as URI+import Prelude hiding (mapM)+import qualified System.Locale as L -import qualified Text.Parsec as P-import Text.Parsec.Prim hiding ((<|>))-import Text.Parsec.Combinator hiding (optional)+import qualified Text.Parsec as P+import Text.Parsec.Combinator hiding (optional)+import Text.Parsec.Prim hiding ((<|>)) import Text.ICalendar.Types @@ -49,7 +50,7 @@ -- | Functions for decoding 'ByteString's into 'Text'. data DecodingFunctions = DecodingFunctions- { dfBS2Text :: ByteString -> Text+ { dfBS2Text :: ByteString -> Text , dfBS2IText :: ByteString -> CI Text } @@ -64,7 +65,7 @@ Left e -> throwError $ "parseText': " ++ show e Right (x, r) -> return ( map (c . Bu.toLazyByteString) x , r)- where texts = sepBy text (P.char ',')+ where texts = sepBy1 text (P.char ',') <|> return [mempty] text = do x <- P.satisfy isTSafe' case x of '\\' -> do y <- P.anyChar@@ -75,9 +76,10 @@ z | z `elem` "nN" -> nxt '\n' _ -> fail $ "unexpected " ++ show x y -> nxt y- -- isTSafe + 0x22, 0x3A+ -- isTSafe + 0x22, 0x3A, and 0x5C is pattern matched against. isTSafe' c = let n = ord c- in n == 9 || (n >= 0x20 && n <= 0x3A)+ in n == 9 || (n >= 0x20 && n <= 0x2B)+ || (n >= 0x2D && n <= 0x3A) || (n >= 0x3C && n /= 0x7F) nxt c = (Bu.char8 c <>) <$> (text <|> return mempty)
Text/ICalendar/Parser/Components.hs view
@@ -1,19 +1,22 @@ {-# LANGUAGE OverloadedStrings #-}-{-# LANGUAGE RecordWildCards #-}+{-# LANGUAGE RecordWildCards #-} module Text.ICalendar.Parser.Components where -import Control.Applicative-import Control.Monad.Error hiding (mapM)-import Control.Monad.RWS ( MonadState(get), tell )+import Control.Applicative+import Control.Arrow ((&&&))+import Control.Monad.Error hiding (mapM)+import Control.Monad.RWS (MonadState (get), tell) import qualified Data.CaseInsensitive as CI-import Data.List (partition)-import Data.Maybe-import Data.Set (Set)-import qualified Data.Set as S+import qualified Data.Foldable as F+import Data.List (partition)+import qualified Data.Map as M+import Data.Maybe+import Data.Set (Set)+import qualified Data.Set as S -import Text.ICalendar.Types import Text.ICalendar.Parser.Common import Text.ICalendar.Parser.Properties+import Text.ICalendar.Types -- | Parse a VCALENDAR component. 3.4 parseVCalendar :: Content -> ContentParser VCalendar@@ -22,14 +25,27 @@ vcVersion <- reqLine1 "VERSION" parseVersion vcScale <- optLine1 "CALSCALE" (parseSimpleI Scale) vcMethod <- optLine1 "METHOD" (parseSimpleI ((Just .) . Method))- vcTimeZones <- optCompN "VTIMEZONE" parseVTimeZone- vcEvents <- optCompN "VEVENT" (parseVEvent vcMethod)- vcTodos <- optCompN "VTODO" parseVTodo- vcJournals <- optCompN "VJOURNAL" parseVJournal- vcFreeBusys <- optCompN "VFREEBUSY" parseVFreeBusy+ vcTimeZones <- f (tzidValue . vtzId) =<< optCompN "VTIMEZONE" parseVTimeZone+ vcEvents <- f (uidValue . veUID &&& recur . veRecurId)+ =<< optCompN "VEVENT" (parseVEvent vcMethod)+ vcTodos <- f (uidValue . vtUID &&& recur . vtRecurId)+ =<< optCompN "VTODO" parseVTodo+ vcJournals <- f (uidValue . vjUID &&& recur . vjRecurId)+ =<< optCompN "VJOURNAL" parseVJournal+ vcFreeBusys <- f (uidValue . vfbUID) =<< optCompN "VFREEBUSY" parseVFreeBusy vcOtherComps <- otherComponents vcOther <- otherProperties return VCalendar {..}+ where recur :: Maybe RecurrenceId -> Maybe (Either Date DateTime)+ recur Nothing = Nothing+ recur (Just (RecurrenceIdDate x _ _)) = Just (Left x)+ recur (Just (RecurrenceIdDateTime x _ _)) = Just (Right x)+ f :: Ord b => (a -> b) -> Set a -> ContentParser (M.Map b a)+ f g = F.foldlM h M.empty+ where h m e = let k = g e+ in if k `M.member` m+ then throwError "Duplicate UID/RecurId/TZID."+ else return $ M.insert k e m parseVCalendar _ = throwError "parseVCalendar: Content given not a VCALENDAR\ \ component."
Text/ICalendar/Parser/Content.hs view
@@ -1,20 +1,20 @@ {-# LANGUAGE OverloadedStrings #-} module Text.ICalendar.Parser.Content where -import Control.Applicative-import Control.Monad-import Data.ByteString.Lazy (ByteString)+import Control.Applicative+import Control.Monad+import Data.ByteString.Lazy (ByteString) import qualified Data.ByteString.Lazy.Builder as Bu-import Data.CaseInsensitive (CI)-import Data.Char-import Data.Monoid-import Data.Text.Lazy (Text)+import Data.CaseInsensitive (CI)+import Data.Char+import Data.Monoid+import Data.Text.Lazy (Text) -import qualified Text.Parsec as P-import Text.Parsec.Prim hiding (many, (<|>))-import Text.Parsec.Combinator hiding (optional)-import Text.Parsec.ByteString.Lazy ()-import Text.Parsec.Text.Lazy ()+import qualified Text.Parsec as P+import Text.Parsec.ByteString.Lazy ()+import Text.Parsec.Combinator hiding (optional)+import Text.Parsec.Prim hiding (many, (<|>))+import Text.Parsec.Text.Lazy () import Text.ICalendar.Parser.Common
Text/ICalendar/Parser/Parameters.hs view
@@ -1,27 +1,27 @@ {-# LANGUAGE OverloadedStrings #-} module Text.ICalendar.Parser.Parameters where -import Control.Applicative-import Control.Monad.Error-import Control.Monad.RWS ( MonadWriter(tell) )-import Data.ByteString.Lazy.Char8 (ByteString)+import Control.Applicative+import Control.Monad.Error+import Control.Monad.RWS (MonadWriter (tell))+import Data.ByteString.Lazy.Char8 (ByteString) import qualified Data.ByteString.Lazy.Char8 as B-import Data.CaseInsensitive (CI)-import Data.Char-import Data.Default-import Data.Maybe-import Data.Text.Lazy (Text)-import qualified Data.Text.Lazy as T+import Data.CaseInsensitive (CI)+import Data.Char+import Data.Default+import Data.Maybe+import Data.Text.Lazy (Text)+import qualified Data.Text.Lazy as T -import Codec.MIME.Parse (parseMIMEType)-import Codec.MIME.Type (mimeType, MIMEType)-import qualified Text.Parsec as P-import Text.Parsec.Prim hiding ((<|>))-import Text.Parsec.Perm-import Text.Parsec.Combinator hiding (optional)+import Codec.MIME.Parse (parseMIMEType)+import Codec.MIME.Type (MIMEType, mimeType)+import qualified Text.Parsec as P+import Text.Parsec.Combinator hiding (optional)+import Text.Parsec.Perm+import Text.Parsec.Prim hiding ((<|>)) -import Text.ICalendar.Types import Text.ICalendar.Parser.Common+import Text.ICalendar.Types parseAlarmTriggerRelationship :: CI Text -> ContentParser AlarmTriggerRelationship
Text/ICalendar/Parser/Properties.hs view
@@ -1,31 +1,31 @@ {-# LANGUAGE OverloadedStrings #-}-{-# LANGUAGE TupleSections #-}-{-# LANGUAGE RecordWildCards #-}+{-# LANGUAGE RecordWildCards #-}+{-# LANGUAGE TupleSections #-} module Text.ICalendar.Parser.Properties where -import Prelude hiding (mapM)-import Control.Applicative-import Control.Monad.Error hiding (mapM)-import Control.Monad.RWS ( asks )-import qualified Data.ByteString.Base64.Lazy as B64-import qualified Data.ByteString.Lazy.Char8 as B-import Data.CaseInsensitive (CI)-import qualified Data.CaseInsensitive as CI-import Data.Char-import Data.Default-import Data.Maybe-import qualified Data.Set as S-import Data.Text.Lazy (Text)-import qualified Data.Text.Lazy as T-import Data.Traversable (mapM)-import qualified Data.Version as Ver-import Text.ParserCombinators.ReadP (readP_to_S)+import Control.Applicative+import Control.Monad.Error hiding (mapM)+import Control.Monad.RWS (asks)+import qualified Data.ByteString.Base64.Lazy as B64+import qualified Data.ByteString.Lazy.Char8 as B+import Data.CaseInsensitive (CI)+import qualified Data.CaseInsensitive as CI+import Data.Char+import Data.Default+import Data.Maybe+import qualified Data.Set as S+import Data.Text.Lazy (Text)+import qualified Data.Text.Lazy as T+import Data.Traversable (mapM)+import qualified Data.Version as Ver+import Prelude hiding (mapM)+import Text.ParserCombinators.ReadP (readP_to_S) import Text.Parsec.Prim hiding ((<|>)) -import Text.ICalendar.Types import Text.ICalendar.Parser.Common import Text.ICalendar.Parser.Parameters+import Text.ICalendar.Types parseFreeBusy :: Content -> ContentParser FreeBusy parseFreeBusy (ContentLine _ "FREEBUSY" o bs) = do@@ -198,8 +198,7 @@ parseRecurId :: Maybe DTStart -> Content -> ContentParser RecurrenceId parseRecurId dts (ContentLine p "RECURRENCE-ID" o bs) = do- range' <- maybe (return def) (parseRange . CI.mk <=< paramOnlyOne) $- lookup "RANGE" o+ range' <- mapM (parseRange . CI.mk <=< paramOnlyOne) $ lookup "RANGE" o recurid <- parseSimpleDateOrDateTime (($ range') . RecurrenceIdDateTime) (($ range') . RecurrenceIdDate)
Text/ICalendar/Printer.hs view
@@ -1,39 +1,40 @@-{-# LANGUAGE OverloadedStrings #-}-{-# LANGUAGE RecordWildCards #-}-{-# LANGUAGE TupleSections #-} {-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE RecordWildCards #-}+{-# LANGUAGE TupleSections #-} module Text.ICalendar.Printer ( EncodingFunctions(..) , printICal ) where -import Prelude hiding (mapM_)-import Control.Applicative-import Control.Arrow ((&&&))-import Control.Monad hiding (mapM_, forM_)-import Control.Monad.RWS ( RWS, runRWS, MonadWriter(tell)- , MonadState(get, put), asks, modify)-import Data.ByteString.Lazy (ByteString)-import qualified Data.ByteString.Lazy.Char8 as BS-import Data.ByteString.Lazy.Builder (Builder)+import Control.Applicative+import Control.Arrow ((&&&))+import Control.Monad hiding (forM_, mapM_)+import Control.Monad.RWS (MonadState (get, put),+ MonadWriter (tell), RWS, asks,+ modify, runRWS)+import Data.ByteString.Lazy (ByteString)+import Data.ByteString.Lazy.Builder (Builder) import qualified Data.ByteString.Lazy.Builder as Bu-import qualified Data.CaseInsensitive as CI-import Data.Char (ord, toUpper)-import Data.Default-import Data.Foldable (mapM_, forM_)-import Data.Monoid-import Data.Set (Set)-import qualified Data.Set as S-import Data.Text.Lazy (Text)-import qualified Data.Text.Lazy as T-import Data.Time (FormatTime())-import qualified Data.Time as Time-import qualified Data.Version as Ver-import qualified Network.URI as URI-import qualified System.Locale as L-import Text.Printf (printf)+import qualified Data.ByteString.Lazy.Char8 as BS+import qualified Data.CaseInsensitive as CI+import Data.Char (ord, toUpper)+import Data.Default+import Data.Foldable (forM_, mapM_)+import Data.Monoid+import Data.Set (Set)+import qualified Data.Set as S+import Data.Text.Lazy (Text)+import qualified Data.Text.Lazy as T+import Data.Time (FormatTime ())+import qualified Data.Time as Time+import qualified Data.Version as Ver+import qualified Network.URI as URI+import Prelude hiding (mapM_)+import qualified System.Locale as L+import Text.Printf (printf) -import Codec.MIME.Type (showMIMEType, MIMEType)+import Codec.MIME.Type (MIMEType, showMIMEType) import qualified Data.ByteString.Base64.Lazy as B64 import Text.ICalendar.Types@@ -352,7 +353,7 @@ printValue classValue instance IsProperty Created where- printProperty Created {..} = ln $ do + printProperty Created {..} = ln $ do prop "CREATED" $ toParam createdOther <> toParam createdValue printValue createdValue @@ -513,7 +514,7 @@ -> a -> ContentPrinter () prop b x = do- put (fromIntegral $ BS.length b) -- + put (fromIntegral $ BS.length b) tell (Bu.lazyByteString b) mapM_ param $ toParam x out ":"@@ -605,10 +606,16 @@ instance ToParam RecurrenceId where toParam RecurrenceIdDate {..} = [("VALUE", [(NoQuotes, "DATE")])] <>+ toParam recurrenceIdRange <> toParam recurrenceIdOther toParam RecurrenceIdDateTime {..} = toParam recurrenceIdDateTime <>+ toParam recurrenceIdRange <> toParam recurrenceIdOther +instance ToParam Range where+ toParam ThisAndFuture = [("RANGE", [(NoQuotes, "THISANDFUTURE")])]+ toParam _ = [] -- ThisAndPrior MUST NOT be generated.+ instance ToParam FBType where toParam x | x == def = [] toParam Free = [("FBTYPE", [(NoQuotes, "FREE")])]@@ -659,7 +666,7 @@ toParam Delegated = [("PARTSTAT", [(NoQuotes, "DELEGATED")])] toParam PartStatCompleted = [("PARTSTAT", [(NoQuotes, "COMPLETED")])] toParam InProcess = [("PARTSTAT", [(NoQuotes, "IN-PROCESS")])]- toParam (PartStatX x) = [("PARTSTAT", [(NoQuotes, CI.original x)])]+ toParam (PartStatX x) = [("PARTSTAT", [(Optional, CI.original x)])] instance ToParam RelationshipType where toParam x | x == def = []
Text/ICalendar/Types.hs view
@@ -1,21 +1,26 @@ {-# LANGUAGE DeriveDataTypeable #-}-{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE OverloadedStrings #-} -- | ICalendar types, based on RFC5545. module Text.ICalendar.Types ( module Text.ICalendar.Types ) where -import Codec.MIME.Type (MIMEType)-import Data.ByteString.Lazy.Char8 (ByteString)-import Data.CaseInsensitive (CI)-import Data.Default-import Data.Set (Set)-import Data.Text.Lazy (Text)-import Data.Time-import Data.Typeable (Typeable)-import Data.Version (Version(..))-import Network.URI (URI)+import Codec.MIME.Type (MIMEType)+import Data.ByteString.Lazy.Char8 (ByteString)+import Data.CaseInsensitive (CI)+import Data.Default+import Data.Map (Map)+import qualified Data.Map as M+import Data.Monoid+import Data.Set (Set)+import Data.Text.Lazy (Text, pack)+import Data.Time+import Data.Typeable (Typeable)+import Data.Version (Version (..), showVersion)+import Network.URI (URI) +import Paths_iCalendar (version)+ -- | Language. newtype Language = Language (CI Text) -- TODO: RFC5646 types and parser. deriving (Eq, Show, Ord, Typeable)@@ -40,19 +45,61 @@ , vcScale :: Scale , vcMethod :: Maybe Method , vcOther :: Set OtherProperty- , vcTimeZones :: Set VTimeZone- , vcEvents :: Set VEvent- , vcTodos :: Set VTodo- , vcJournals :: Set VJournal- , vcFreeBusys :: Set VFreeBusy+ , vcTimeZones :: Map Text VTimeZone+ -- ^ Map TZID-value VTimeZone+ , vcEvents :: Map (Text, Maybe (Either Date DateTime)) VEvent+ -- ^ Map (UID-value, Maybe RecurrenceID-value) VEvent+ , vcTodos :: Map (Text, Maybe (Either Date DateTime)) VTodo+ -- ^ Map (UID-value, Maybe RecurrenceID-value) VTodo+ , vcJournals :: Map (Text, Maybe (Either Date DateTime)) VJournal+ -- ^ Map (UID-value, Maybe RecurrenceID-value) VJournal+ , vcFreeBusys :: Map Text VFreeBusy+ -- ^ Map UID-value VFreeBusy , vcOtherComps :: Set VOther } deriving (Show, Eq, Ord, Typeable) instance Default VCalendar where- def = VCalendar (ProdId "-//haskell.org/NONSGML iCalendar-0.1//EN" def)+ def = VCalendar (ProdId ("-//haskell.org/NONSGML iCalendar-" <>+ pack (showVersion version) <> "//EN") def) (MaxICalVersion (Version [2,0] []) def) def Nothing def def def def def def def +-- | 'vcMethod' is ignored at the moment.+--+-- Picks the left in most cases.+--+-- On UID/RecurrenceId/TZID clash, picks the 'VEvent's, 'VTodo's and+-- 'VJournal's with the highest ('Sequence', 'DTStamp'), the 'VTimeZone's+-- with the highest 'LastModified', and 'VFreeBusy' with the highest 'DTStamp'.+--+-- If the Sequence, DTStamp or LastModified is the same, picks the left.+instance Monoid VCalendar where+ mempty = def+ mappend a b = VCalendar { vcProdId = vcProdId a+ , vcVersion = vcVersion a+ , vcScale = vcScale a+ , vcMethod = vcMethod a+ , vcOther = vcOther a <> vcOther b+ , vcTimeZones = merge tz (vcTimeZones a)+ (vcTimeZones b)+ , vcEvents = merge ev (vcEvents a) (vcEvents b)+ , vcTodos = merge td (vcTodos a) (vcTodos b)+ , vcJournals = merge jo (vcJournals a)+ (vcJournals b)+ , vcFreeBusys = merge fb (vcFreeBusys a)+ (vcFreeBusys b)+ , vcOtherComps = vcOtherComps a <> vcOtherComps b+ }+ where merge f = M.mergeWithKey (((Just .) .) . const f) id id+ tz c d = if vtzLastMod c >= vtzLastMod d then c else d+ ev c d = if (veSeq c, veDTStamp c) >= (veSeq d, veDTStamp d)+ then c else d+ td c d = if (vtSeq c, vtDTStamp c) >= (vtSeq d, vtDTStamp d)+ then c else d+ jo c d = if (vjSeq c, vjDTStamp c) >= (vjSeq d, vjDTStamp d)+ then c else d+ fb c d = if vfbDTStamp c >= vfbDTStamp d then c else d+ -- | Product Identifier. 3.7.3. data ProdId = ProdId { prodIdValue :: Text@@ -123,92 +170,92 @@ -- | To-Do Component. 3.6.2 data VTodo = VTodo- { vtDTStamp :: DTStamp- , vtUID :: UID- , vtClass :: Class -- ^ 'def' = 'Public'- , vtCompleted :: Maybe Completed- , vtCreated :: Maybe Created- , vtDescription :: Maybe Description- , vtDTStart :: Maybe DTStart- , vtGeo :: Maybe Geo- , vtLastMod :: Maybe LastModified- , vtLocation :: Maybe Location- , vtOrganizer :: Maybe Organizer- , vtPercent :: Maybe PercentComplete- , vtPriority :: Priority -- ^ 'def' = 0- , vtRecurId :: Maybe RecurrenceId- , vtSeq :: Sequence -- ^ 'def' = 0- , vtStatus :: Maybe TodoStatus- , vtSummary :: Maybe Summary- , vtUrl :: Maybe URL- , vtRRule :: Set RRule- , vtDueDuration :: Maybe (Either Due DurationProp)- , vtAttach :: Set Attachment- , vtAttendee :: Set Attendee- , vtCategories :: Set Categories- , vtComment :: Set Comment- , vtContact :: Set Contact- , vtExDate :: Set ExDate- , vtRStatus :: Set RequestStatus- , vtRelated :: Set RelatedTo- , vtResources :: Set Resources- , vtRDate :: Set RDate- , vtAlarms :: Set VAlarm- , vtOther :: Set OtherProperty+ { vtDTStamp :: DTStamp+ , vtUID :: UID+ , vtClass :: Class -- ^ 'def' = 'Public'+ , vtCompleted :: Maybe Completed+ , vtCreated :: Maybe Created+ , vtDescription :: Maybe Description+ , vtDTStart :: Maybe DTStart+ , vtGeo :: Maybe Geo+ , vtLastMod :: Maybe LastModified+ , vtLocation :: Maybe Location+ , vtOrganizer :: Maybe Organizer+ , vtPercent :: Maybe PercentComplete+ , vtPriority :: Priority -- ^ 'def' = 0+ , vtRecurId :: Maybe RecurrenceId+ , vtSeq :: Sequence -- ^ 'def' = 0+ , vtStatus :: Maybe TodoStatus+ , vtSummary :: Maybe Summary+ , vtUrl :: Maybe URL+ , vtRRule :: Set RRule+ , vtDueDuration :: Maybe (Either Due DurationProp)+ , vtAttach :: Set Attachment+ , vtAttendee :: Set Attendee+ , vtCategories :: Set Categories+ , vtComment :: Set Comment+ , vtContact :: Set Contact+ , vtExDate :: Set ExDate+ , vtRStatus :: Set RequestStatus+ , vtRelated :: Set RelatedTo+ , vtResources :: Set Resources+ , vtRDate :: Set RDate+ , vtAlarms :: Set VAlarm+ , vtOther :: Set OtherProperty } deriving (Show, Eq, Ord, Typeable) -- | Journal Component. 3.6.3 data VJournal = VJournal- { vjDTStamp :: DTStamp- , vjUID :: UID- , vjClass :: Class -- ^ 'def' = 'Public'- , vjCreated :: Maybe Created- , vjDTStart :: Maybe DTStart- , vjLastMod :: Maybe LastModified- , vjOrganizer :: Maybe Organizer- , vjRecurId :: Maybe RecurrenceId- , vjSeq :: Sequence -- ^ 'def' = 0- , vjStatus :: Maybe JournalStatus- , vjSummary :: Maybe Summary- , vjUrl :: Maybe URL- , vjRRule :: Set RRule- , vjAttach :: Set Attachment- , vjAttendee :: Set Attendee- , vjCategories :: Set Categories- , vjComment :: Set Comment- , vjContact :: Set Contact- , vjDescription :: Set Description- , vjExDate :: Set ExDate- , vjRelated :: Set RelatedTo- , vjRDate :: Set RDate- , vjRStatus :: Set RequestStatus- , vjOther :: Set OtherProperty+ { vjDTStamp :: DTStamp+ , vjUID :: UID+ , vjClass :: Class -- ^ 'def' = 'Public'+ , vjCreated :: Maybe Created+ , vjDTStart :: Maybe DTStart+ , vjLastMod :: Maybe LastModified+ , vjOrganizer :: Maybe Organizer+ , vjRecurId :: Maybe RecurrenceId+ , vjSeq :: Sequence -- ^ 'def' = 0+ , vjStatus :: Maybe JournalStatus+ , vjSummary :: Maybe Summary+ , vjUrl :: Maybe URL+ , vjRRule :: Set RRule+ , vjAttach :: Set Attachment+ , vjAttendee :: Set Attendee+ , vjCategories :: Set Categories+ , vjComment :: Set Comment+ , vjContact :: Set Contact+ , vjDescription :: Set Description+ , vjExDate :: Set ExDate+ , vjRelated :: Set RelatedTo+ , vjRDate :: Set RDate+ , vjRStatus :: Set RequestStatus+ , vjOther :: Set OtherProperty } deriving (Show, Eq, Ord, Typeable) -- | Free/Busy Component. 3.6.4 data VFreeBusy = VFreeBusy- { vfbDTStamp :: DTStamp- , vfbUID :: UID- , vfbContact :: Maybe Contact- , vfbDTStart :: Maybe DTStart- , vfbDTEnd :: Maybe DTEnd- , vfbOrganizer :: Maybe Organizer- , vfbUrl :: Maybe URL- , vfbAttendee :: Set Attendee- , vfbComment :: Set Comment- , vfbFreeBusy :: Set FreeBusy- , vfbRStatus :: Set RequestStatus- , vfbOther :: Set OtherProperty+ { vfbDTStamp :: DTStamp+ , vfbUID :: UID+ , vfbContact :: Maybe Contact+ , vfbDTStart :: Maybe DTStart+ , vfbDTEnd :: Maybe DTEnd+ , vfbOrganizer :: Maybe Organizer+ , vfbUrl :: Maybe URL+ , vfbAttendee :: Set Attendee+ , vfbComment :: Set Comment+ , vfbFreeBusy :: Set FreeBusy+ , vfbRStatus :: Set RequestStatus+ , vfbOther :: Set OtherProperty } deriving (Show, Eq, Ord, Typeable) -- | Time Zone Component. 3.6.5. data VTimeZone = VTimeZone- { vtzId :: TZID- , vtzLastMod :: Maybe LastModified- , vtzUrl :: Maybe TZUrl- , vtzStandardC :: Set TZProp- , vtzDaylightC :: Set TZProp- , vtzOther :: Set OtherProperty+ { vtzId :: TZID+ , vtzLastMod :: Maybe LastModified+ , vtzUrl :: Maybe TZUrl+ , vtzStandardC :: Set TZProp+ , vtzDaylightC :: Set TZProp+ , vtzOther :: Set OtherProperty } deriving (Show, Eq, Ord, Typeable) -- | Time zone property, also 3.6.5.@@ -261,7 +308,7 @@ -- | Any other component not recognized. data VOther = VOther- { voName :: CI Text+ { voName :: CI Text , voProps :: Set OtherProperty } deriving (Show, Eq, Ord, Typeable) @@ -407,7 +454,7 @@ { dateTimeFloating :: LocalTime } | UTCDateTime- { dateTimeUTC :: UTCTime+ { dateTimeUTC :: UTCTime } | ZonedDateTime { dateTimeFloating :: LocalTime@@ -421,8 +468,8 @@ , dtEndOther :: OtherParams } | DTEndDate- { dtEndDateValue :: Date- , dtEndOther :: OtherParams+ { dtEndDateValue :: Date+ , dtEndOther :: OtherParams } deriving (Show, Eq, Ord, Typeable) -- | Date-Time Due. 3.8.2.3.@@ -432,8 +479,8 @@ , dueOther :: OtherParams } | DueDate- { dueDateValue :: Date- , dueOther :: OtherParams+ { dueDateValue :: Date+ , dueOther :: OtherParams } deriving (Show, Eq, Ord, Typeable) -- | Date-Time Start. 3.8.2.4.@@ -443,8 +490,8 @@ , dtStartOther :: OtherParams } | DTStartDate- { dtStartDateValue :: Date- , dtStartOther :: OtherParams+ { dtStartDateValue :: Date+ , dtStartOther :: OtherParams } deriving (Show, Eq, Ord, Typeable) -- | Duration value. 3.3.6.@@ -463,8 +510,8 @@ , durSecond :: Int } | DurationWeek- { durSign :: Sign- , durWeek :: Int+ { durSign :: Sign+ , durWeek :: Int } deriving (Show, Eq, Ord, Typeable) -- | Sign.@@ -626,21 +673,18 @@ data RecurrenceId = RecurrenceIdDate { recurrenceIdDate :: Date- , recurrenceIdRange :: Range -- ^ 'def' = 'ThisAndFuture'+ , recurrenceIdRange :: Maybe Range , recurrenceIdOther :: OtherParams } | RecurrenceIdDateTime { recurrenceIdDateTime :: DateTime- , recurrenceIdRange :: Range -- ^ 'def' = 'ThisAndFuture'+ , recurrenceIdRange :: Maybe Range , recurrenceIdOther :: OtherParams } deriving (Show, Eq, Ord, Typeable) -- | Recurrence Identifier Range. 3.2.13 data Range = ThisAndFuture | ThisAndPrior deriving (Show, Eq, Ord, Typeable)--instance Default Range where- def = ThisAndFuture -- | Related To. 3.8.4.5. data RelatedTo = RelatedTo
iCalendar.cabal view
@@ -1,5 +1,5 @@ name: iCalendar-version: 0.1+version: 0.2 synopsis: iCalendar data types, parser, and printer. description: Data definitions, parsing and printing of the iCalendar format (RFC5545).@@ -30,9 +30,10 @@ , Text.ICalendar.Parser.Content , Text.ICalendar.Parser.Parameters , Text.ICalendar.Parser.Properties+ , Paths_iCalendar build-depends: base ==4.*, time ==1.4.*, data-default >=0.3 , case-insensitive ==0.4.*, network ==2.4.* , bytestring >=0.10 && < 0.11, parsec ==3.1.*- , text, containers >= 0.4 && < 0.6, mime ==0.3.*+ , text, containers >= 0.5 && < 0.6, mime ==0.3.* , mtl ==2.1.*, old-locale, base64-bytestring ==1.0.* ghc-options: -Wall