rrule 0.1.1 → 0.1.2
raw patch · 5 files changed
+42/−7 lines, 5 files
Files
- rrule.cabal +1/−1
- src/Data/Time/RRule.hs +4/−2
- src/Data/Time/RRule/Parse.hs +11/−3
- src/Data/Time/RRule/Types.hs +12/−1
- test/Spec.hs +14/−0
rrule.cabal view
@@ -1,7 +1,7 @@ cabal-version: 1.12 name: rrule-version: 0.1.1+version: 0.1.2 synopsis: Recurrence rule parser and formatter description: Parser for recurrence rules including formatting back to RFC 5545 recurrence rule strings as well as providing English descriptions
src/Data/Time/RRule.hs view
@@ -19,6 +19,7 @@ , RRule(..) , Day(..) , Frequency(..)+ , TimeOrDate(..) , ToRRule(toRRule) ) import Text.Megaparsec (parseMaybe)@@ -146,8 +147,9 @@ countDescription :: Int -> Text countDescription n = "for " <> showText n <> " occurrences" -untilDescription :: UTCTime -> Text-untilDescription t = "until " <> (pack $ formatTime defaultTimeLocale "%B %d, %Y at %H:%M:%S" t)+untilDescription :: Ty.TimeOrDate -> Text+untilDescription (Ty.Time t) = "until " <> (pack $ formatTime defaultTimeLocale "%B %d, %Y at %H:%M:%S" t)+untilDescription (Ty.Date d) = "until " <> (pack $ formatTime defaultTimeLocale "%B %d, %Y" d) weekStartDescription :: Day -> Text weekStartDescription d = "with weeks starting on " <> showText d
src/Data/Time/RRule/Parse.hs view
@@ -2,7 +2,6 @@ ( parseRRule ) where- import Prelude hiding (until) import Control.Monad (msum) import qualified Control.Monad.Combinators.NonEmpty as NE@@ -11,9 +10,10 @@ import Data.Text (Text, intercalate, pack, unpack) import Data.Time.Clock (UTCTime) import Data.Time.Format (parseTimeM, defaultTimeLocale)-import Data.Time.RRule.Types (defaultRRule, RRule(..), Day(..), Frequency(..), ToRRule)+import Data.Time.RRule.Types (defaultRRule, RRule(..), Day(..), Frequency(..), ToRRule, TimeOrDate(..)) import Text.Megaparsec hiding (count) import Text.Megaparsec.Char.Lexer+import qualified Data.Time.Calendar as Cal (Day, toGregorian) type Parser = Parsec () Text @@ -50,7 +50,7 @@ weekStart <- parseVar "WKST" parseDay frequency <- parseVar "FREQ" parseFrequency count <- parseVar "COUNT" decimal- until <- parseVar "UNTIL" parseUtcTime+ until <- parseVar "UNTIL" parseTimeOrDate interval <- parseVar "INTERVAL" decimal bySecond <- parseVar "BYSECOND" parseSomeInt byMinute <- parseVar "BYMINUTE" parseSomeInt@@ -83,6 +83,14 @@ n <- try . optional $ parseInt d <- parseDay return (fromMaybe 0 n, d)++parseTimeOrDate :: Parser TimeOrDate+parseTimeOrDate = fmap Time (try parseUtcTime) <|> fmap Date parseDate++parseDate :: Parser Cal.Day+parseDate = do+ d <- takeP Nothing 8+ parseTimeM False defaultTimeLocale "%Y%m%d" (unpack d) parseUtcTime :: Parser UTCTime parseUtcTime = do
src/Data/Time/RRule/Types.hs view
@@ -3,6 +3,7 @@ , RRule(..) , Day(..) , Frequency(..)+ , TimeOrDate(..) , ToRRule(toRRule) ) where@@ -12,6 +13,7 @@ import Data.Text (Text, intercalate, pack, unpack) import Data.Time.Format (formatTime, defaultTimeLocale) import Data.Time.Clock (UTCTime)+import qualified Data.Time.Calendar as Cal (Day, toGregorian) class Show a => ToRRule a where toRRule :: a -> Text@@ -28,6 +30,15 @@ instance ToRRule UTCTime where toRRule = pack . formatTime defaultTimeLocale "%Y%m%dT%H%M%SZ" +data TimeOrDate = Time UTCTime | Date Cal.Day+ deriving (Eq, Show)++instance ToRRule TimeOrDate where+ toRRule (Time utc) = toRRule utc+ toRRule (Date day) =+ let (y,m,d) = Cal.toGregorian day+ in pack (show y <> show m <> show d)+ instance ToRRule a => ToRRule (Maybe a) where toRRule Nothing = "" toRRule (Just a) = toRRule a@@ -70,7 +81,7 @@ , weekStart :: Maybe Day -- ^ starting day of the week , frequency :: Maybe Frequency -- ^ how often to recur , count :: Maybe Int -- ^ how many times to recur- , until :: Maybe UTCTime -- ^ what UTCTime to stop recurring after+ , until :: Maybe TimeOrDate -- ^ what UTCTime or Date to stop recurring after , interval :: Maybe Int -- ^ number of units to wait before recurring , bySecond :: Maybe (NonEmpty Int) -- ^ which second(s) to recur on , byMinute :: Maybe (NonEmpty Int) -- ^ which minute(s) to recur on
test/Spec.hs view
@@ -96,6 +96,12 @@ it "yearly in June and July for 10 occurrences" $ do roundTrip "FREQ=YEARLY;COUNT=10;BYMONTH=6,7" + it "every month on Tuesday until November 30, 2021" $ do+ roundTrip "RRULE:BYDAY=TU;INTERVAL=1;FREQ=MONTHLY;UNTIL=20211130"++ it "every other week on Friday until November 19, 1997" $ do+ roundTrip "RRULE:BYDAY=FR;INTERVAL=2;FREQ=WEEKLY;UNTIL=19971119"+ it "every other year on January, February, and March for 10 occurrences" $ do roundTrip "FREQ=YEARLY;INTERVAL=2;COUNT=10;BYMONTH=1,2,3" @@ -310,6 +316,14 @@ it "every 3 hours until 5:00 PM on a specific day" $ do description <$> fromText "FREQ=HOURLY;INTERVAL=3;UNTIL=19970902T170000Z" `shouldBe` Just "every 3rd hour until September 02, 1997 at 17:00:00"++ it "every month on Tuesday until November 30, 2021" $ do+ description <$> fromText "RRULE:BYDAY=TU;INTERVAL=1;FREQ=MONTHLY;UNTIL=20211130" `shouldBe`+ Just "every month on Tuesday until November 30, 2021"++ it "every other week on Friday until November 19, 1997" $ do+ description <$> fromText "RRULE:BYDAY=FR;INTERVAL=2;FREQ=WEEKLY;UNTIL=19971119" `shouldBe`+ Just "every other week on Friday until November 19, 1997" it "every 15 minutes for 6 occurrences" $ do description <$> fromText "FREQ=MINUTELY;INTERVAL=15;COUNT=6" `shouldBe`