packages feed

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 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