{-# LANGUAGE NoImplicitPrelude #-} {-# LANGUAGE TemplateHaskell #-} module Data.Time.Aviation.SixFigureGroup( DayOfMonth(..) , HasDayOfMonth(..) , AsDayOfMonth(..) , parseDayOfMonth , HourOfDay(..) , HasHourOfDay(..) , AsHourOfDay(..) , parseHourOfDay , MinuteOfHour(..) , HasMinuteOfHour(..) , AsMinuteOfHour(..) , parseMinuteOfHour , SixFigureGroup(..) , HasSixFigureGroup(..) , parseSixFigureGroup , parseSixFigureGroupz ) where import Control.Applicative((<|>), empty, (<*>), (<*)) import Control.Category((.)) import Control.Lens(makeClassy, makeClassyPrisms, Prism', prism') import Data.Eq(Eq) import Data.Foldable(foldr) import Data.Functor((<$>), (<$)) import Data.Int(Int) import Data.Maybe(Maybe(Nothing, Just)) import Data.Ord(Ord) import Text.Parser.Char(CharParsing, string, char) import Text.Parser.Combinators((), try) import Prelude(Show, Num, Integer, Float, Double) -- $setup -- -- >>> import Text.Parsec(parse) -- >>> import Control.Lens -- >>> import Prelude(show) data DayOfMonth = DayOfMonth_01 | DayOfMonth_02 | DayOfMonth_03 | DayOfMonth_04 | DayOfMonth_05 | DayOfMonth_06 | DayOfMonth_07 | DayOfMonth_08 | DayOfMonth_09 | DayOfMonth_10 | DayOfMonth_11 | DayOfMonth_12 | DayOfMonth_13 | DayOfMonth_14 | DayOfMonth_15 | DayOfMonth_16 | DayOfMonth_17 | DayOfMonth_18 | DayOfMonth_19 | DayOfMonth_20 | DayOfMonth_21 | DayOfMonth_22 | DayOfMonth_23 | DayOfMonth_24 | DayOfMonth_25 | DayOfMonth_26 | DayOfMonth_27 | DayOfMonth_28 | DayOfMonth_29 | DayOfMonth_30 | DayOfMonth_31 deriving (Eq, Ord, Show) makeClassy ''DayOfMonth makeClassyPrisms ''DayOfMonth integralDayOfMonth :: (Eq a, Num a) => Prism' a DayOfMonth integralDayOfMonth = prism' (\d -> case d of DayOfMonth_01 -> 1 DayOfMonth_02 -> 2 DayOfMonth_03 -> 3 DayOfMonth_04 -> 4 DayOfMonth_05 -> 5 DayOfMonth_06 -> 6 DayOfMonth_07 -> 7 DayOfMonth_08 -> 8 DayOfMonth_09 -> 9 DayOfMonth_10 -> 10 DayOfMonth_11 -> 11 DayOfMonth_12 -> 12 DayOfMonth_13 -> 13 DayOfMonth_14 -> 14 DayOfMonth_15 -> 15 DayOfMonth_16 -> 16 DayOfMonth_17 -> 17 DayOfMonth_18 -> 18 DayOfMonth_19 -> 19 DayOfMonth_20 -> 20 DayOfMonth_21 -> 21 DayOfMonth_22 -> 22 DayOfMonth_23 -> 23 DayOfMonth_24 -> 24 DayOfMonth_25 -> 25 DayOfMonth_26 -> 26 DayOfMonth_27 -> 27 DayOfMonth_28 -> 28 DayOfMonth_29 -> 29 DayOfMonth_30 -> 30 DayOfMonth_31 -> 31) (\n -> case n of 1 -> Just DayOfMonth_01 2 -> Just DayOfMonth_02 3 -> Just DayOfMonth_03 4 -> Just DayOfMonth_04 5 -> Just DayOfMonth_05 6 -> Just DayOfMonth_06 7 -> Just DayOfMonth_07 8 -> Just DayOfMonth_08 9 -> Just DayOfMonth_09 10 -> Just DayOfMonth_10 11 -> Just DayOfMonth_11 12 -> Just DayOfMonth_12 13 -> Just DayOfMonth_13 14 -> Just DayOfMonth_14 15 -> Just DayOfMonth_15 16 -> Just DayOfMonth_16 17 -> Just DayOfMonth_17 18 -> Just DayOfMonth_18 19 -> Just DayOfMonth_19 20 -> Just DayOfMonth_20 21 -> Just DayOfMonth_21 22 -> Just DayOfMonth_22 23 -> Just DayOfMonth_23 24 -> Just DayOfMonth_24 25 -> Just DayOfMonth_25 26 -> Just DayOfMonth_26 27 -> Just DayOfMonth_27 28 -> Just DayOfMonth_28 29 -> Just DayOfMonth_29 30 -> Just DayOfMonth_30 31 -> Just DayOfMonth_31 _ -> Nothing) instance AsDayOfMonth Int where _DayOfMonth = integralDayOfMonth instance AsDayOfMonth Integer where _DayOfMonth = integralDayOfMonth instance AsDayOfMonth Float where _DayOfMonth = integralDayOfMonth instance AsDayOfMonth Double where _DayOfMonth = integralDayOfMonth -- | Parse two digits to a day of month (01-31). -- -- >>> parse parseDayOfMonth "test" "01" -- Right DayOfMonth_01 -- -- >>> parse parseDayOfMonth "test" "02" -- Right DayOfMonth_02 -- -- >>> parse parseDayOfMonth "test" "18" -- Right DayOfMonth_18 -- -- >>> parse parseDayOfMonth "test" "30" -- Right DayOfMonth_30 -- -- >>> parse parseDayOfMonth "test" "31" -- Right DayOfMonth_31 -- -- >>> isn't _Right (parse parseDayOfMonth "test" "00") -- True -- -- >>> isn't _Right (parse parseDayOfMonth "test" "32") -- True -- -- >>> isn't _Right (parse parseDayOfMonth "test" "9") -- True -- -- >>> parse (show <$> parseDayOfMonth <|> string "00") "test" "00" -- Right "00" parseDayOfMonth :: CharParsing f => f DayOfMonth parseDayOfMonth = let t = [ (DayOfMonth_01, "01") , (DayOfMonth_02, "02") , (DayOfMonth_03, "03") , (DayOfMonth_04, "04") , (DayOfMonth_05, "05") , (DayOfMonth_06, "06") , (DayOfMonth_07, "07") , (DayOfMonth_08, "08") , (DayOfMonth_09, "09") , (DayOfMonth_10, "10") , (DayOfMonth_11, "11") , (DayOfMonth_12, "12") , (DayOfMonth_13, "13") , (DayOfMonth_14, "14") , (DayOfMonth_15, "15") , (DayOfMonth_16, "16") , (DayOfMonth_17, "17") , (DayOfMonth_18, "18") , (DayOfMonth_19, "19") , (DayOfMonth_20, "20") , (DayOfMonth_21, "21") , (DayOfMonth_22, "22") , (DayOfMonth_23, "23") , (DayOfMonth_24, "24") , (DayOfMonth_25, "25") , (DayOfMonth_26, "26") , (DayOfMonth_27, "27") , (DayOfMonth_28, "28") , (DayOfMonth_29, "29") , (DayOfMonth_30, "30") , (DayOfMonth_31, "31") ] in foldr (\(a, b) x -> try (a <$ string b) <|> x) empty t "day of month" data HourOfDay = HourOfDay_00 | HourOfDay_01 | HourOfDay_02 | HourOfDay_03 | HourOfDay_04 | HourOfDay_05 | HourOfDay_06 | HourOfDay_07 | HourOfDay_08 | HourOfDay_09 | HourOfDay_10 | HourOfDay_11 | HourOfDay_12 | HourOfDay_13 | HourOfDay_14 | HourOfDay_15 | HourOfDay_16 | HourOfDay_17 | HourOfDay_18 | HourOfDay_19 | HourOfDay_20 | HourOfDay_21 | HourOfDay_22 | HourOfDay_23 deriving (Eq, Ord, Show) makeClassy ''HourOfDay makeClassyPrisms ''HourOfDay integralHourOfDay :: (Eq a, Num a) => Prism' a HourOfDay integralHourOfDay = prism' (\d -> case d of HourOfDay_00 -> 0 HourOfDay_01 -> 1 HourOfDay_02 -> 2 HourOfDay_03 -> 3 HourOfDay_04 -> 4 HourOfDay_05 -> 5 HourOfDay_06 -> 6 HourOfDay_07 -> 7 HourOfDay_08 -> 8 HourOfDay_09 -> 9 HourOfDay_10 -> 10 HourOfDay_11 -> 11 HourOfDay_12 -> 12 HourOfDay_13 -> 13 HourOfDay_14 -> 14 HourOfDay_15 -> 15 HourOfDay_16 -> 16 HourOfDay_17 -> 17 HourOfDay_18 -> 18 HourOfDay_19 -> 19 HourOfDay_20 -> 20 HourOfDay_21 -> 21 HourOfDay_22 -> 22 HourOfDay_23 -> 23) (\n -> case n of 0 -> Just HourOfDay_00 1 -> Just HourOfDay_01 2 -> Just HourOfDay_02 3 -> Just HourOfDay_03 4 -> Just HourOfDay_04 5 -> Just HourOfDay_05 6 -> Just HourOfDay_06 7 -> Just HourOfDay_07 8 -> Just HourOfDay_08 9 -> Just HourOfDay_09 10 -> Just HourOfDay_10 11 -> Just HourOfDay_11 12 -> Just HourOfDay_12 13 -> Just HourOfDay_13 14 -> Just HourOfDay_14 15 -> Just HourOfDay_15 16 -> Just HourOfDay_16 17 -> Just HourOfDay_17 18 -> Just HourOfDay_18 19 -> Just HourOfDay_19 20 -> Just HourOfDay_20 21 -> Just HourOfDay_21 22 -> Just HourOfDay_22 23 -> Just HourOfDay_23 _ -> Nothing) instance AsHourOfDay Int where _HourOfDay = integralHourOfDay instance AsHourOfDay Integer where _HourOfDay = integralHourOfDay instance AsHourOfDay Float where _HourOfDay = integralHourOfDay instance AsHourOfDay Double where _HourOfDay = integralHourOfDay -- | Parse two digits to an hour of day (00-23). -- -- >>> parse parseHourOfDay "test" "00" -- Right HourOfDay_00 -- -- >>> parse parseHourOfDay "test" "01" -- Right HourOfDay_01 -- -- >>> parse parseHourOfDay "test" "18" -- Right HourOfDay_18 -- -- >>> parse parseHourOfDay "test" "22" -- Right HourOfDay_22 -- -- >>> parse parseHourOfDay "test" "23" -- Right HourOfDay_23 -- -- >>> isn't _Right (parse parseHourOfDay "test" "24") -- True -- -- >>> isn't _Right (parse parseHourOfDay "test" "9") -- True -- -- >>> parse (show <$> parseHourOfDay <|> string "25") "test" "25" -- Right "25" parseHourOfDay :: CharParsing f => f HourOfDay parseHourOfDay = let t = [ (HourOfDay_00, "00") , (HourOfDay_01, "01") , (HourOfDay_02, "02") , (HourOfDay_03, "03") , (HourOfDay_04, "04") , (HourOfDay_05, "05") , (HourOfDay_06, "06") , (HourOfDay_07, "07") , (HourOfDay_08, "08") , (HourOfDay_09, "09") , (HourOfDay_10, "10") , (HourOfDay_11, "11") , (HourOfDay_12, "12") , (HourOfDay_13, "13") , (HourOfDay_14, "14") , (HourOfDay_15, "15") , (HourOfDay_16, "16") , (HourOfDay_17, "17") , (HourOfDay_18, "18") , (HourOfDay_19, "19") , (HourOfDay_20, "20") , (HourOfDay_21, "21") , (HourOfDay_22, "22") , (HourOfDay_23, "23") ] in foldr (\(a, b) x -> try (a <$ string b) <|> x) empty t "hour of day" data MinuteOfHour = MinuteOfHour_00 | MinuteOfHour_01 | MinuteOfHour_02 | MinuteOfHour_03 | MinuteOfHour_04 | MinuteOfHour_05 | MinuteOfHour_06 | MinuteOfHour_07 | MinuteOfHour_08 | MinuteOfHour_09 | MinuteOfHour_10 | MinuteOfHour_11 | MinuteOfHour_12 | MinuteOfHour_13 | MinuteOfHour_14 | MinuteOfHour_15 | MinuteOfHour_16 | MinuteOfHour_17 | MinuteOfHour_18 | MinuteOfHour_19 | MinuteOfHour_20 | MinuteOfHour_21 | MinuteOfHour_22 | MinuteOfHour_23 | MinuteOfHour_24 | MinuteOfHour_25 | MinuteOfHour_26 | MinuteOfHour_27 | MinuteOfHour_28 | MinuteOfHour_29 | MinuteOfHour_30 | MinuteOfHour_31 | MinuteOfHour_32 | MinuteOfHour_33 | MinuteOfHour_34 | MinuteOfHour_35 | MinuteOfHour_36 | MinuteOfHour_37 | MinuteOfHour_38 | MinuteOfHour_39 | MinuteOfHour_40 | MinuteOfHour_41 | MinuteOfHour_42 | MinuteOfHour_43 | MinuteOfHour_44 | MinuteOfHour_45 | MinuteOfHour_46 | MinuteOfHour_47 | MinuteOfHour_48 | MinuteOfHour_49 | MinuteOfHour_50 | MinuteOfHour_51 | MinuteOfHour_52 | MinuteOfHour_53 | MinuteOfHour_54 | MinuteOfHour_55 | MinuteOfHour_56 | MinuteOfHour_57 | MinuteOfHour_58 | MinuteOfHour_59 deriving (Eq, Ord, Show) makeClassy ''MinuteOfHour makeClassyPrisms ''MinuteOfHour -- | Parse two digits to a minute of hour (00-59). -- -- >>> parse parseMinuteOfHour "test" "00" -- Right MinuteOfHour_00 -- -- >>> parse parseMinuteOfHour "test" "01" -- Right MinuteOfHour_01 -- -- >>> parse parseMinuteOfHour "test" "18" -- Right MinuteOfHour_18 -- -- >>> parse parseMinuteOfHour "test" "58" -- Right MinuteOfHour_58 -- -- >>> parse parseMinuteOfHour "test" "59" -- Right MinuteOfHour_59 -- -- >>> isn't _Right (parse parseMinuteOfHour "test" "60") -- True -- -- >>> isn't _Right (parse parseMinuteOfHour "test" "9") -- True -- -- >>> parse (show <$> parseMinuteOfHour <|> string "61") "test" "61" -- Right "61" parseMinuteOfHour :: CharParsing f => f MinuteOfHour parseMinuteOfHour = let t = [ (MinuteOfHour_00, "00") , (MinuteOfHour_01, "01") , (MinuteOfHour_02, "02") , (MinuteOfHour_03, "03") , (MinuteOfHour_04, "04") , (MinuteOfHour_05, "05") , (MinuteOfHour_06, "06") , (MinuteOfHour_07, "07") , (MinuteOfHour_08, "08") , (MinuteOfHour_09, "09") , (MinuteOfHour_10, "10") , (MinuteOfHour_11, "11") , (MinuteOfHour_12, "12") , (MinuteOfHour_13, "13") , (MinuteOfHour_14, "14") , (MinuteOfHour_15, "15") , (MinuteOfHour_16, "16") , (MinuteOfHour_17, "17") , (MinuteOfHour_18, "18") , (MinuteOfHour_19, "19") , (MinuteOfHour_20, "20") , (MinuteOfHour_21, "21") , (MinuteOfHour_22, "22") , (MinuteOfHour_23, "23") , (MinuteOfHour_24, "24") , (MinuteOfHour_25, "25") , (MinuteOfHour_26, "26") , (MinuteOfHour_27, "27") , (MinuteOfHour_28, "28") , (MinuteOfHour_29, "29") , (MinuteOfHour_30, "30") , (MinuteOfHour_31, "31") , (MinuteOfHour_32, "32") , (MinuteOfHour_33, "33") , (MinuteOfHour_34, "34") , (MinuteOfHour_35, "35") , (MinuteOfHour_36, "36") , (MinuteOfHour_37, "37") , (MinuteOfHour_38, "38") , (MinuteOfHour_39, "39") , (MinuteOfHour_40, "40") , (MinuteOfHour_41, "41") , (MinuteOfHour_42, "42") , (MinuteOfHour_43, "43") , (MinuteOfHour_44, "44") , (MinuteOfHour_45, "45") , (MinuteOfHour_46, "46") , (MinuteOfHour_47, "47") , (MinuteOfHour_48, "48") , (MinuteOfHour_49, "49") , (MinuteOfHour_50, "50") , (MinuteOfHour_51, "51") , (MinuteOfHour_52, "52") , (MinuteOfHour_53, "53") , (MinuteOfHour_54, "54") , (MinuteOfHour_55, "55") , (MinuteOfHour_56, "56") , (MinuteOfHour_57, "57") , (MinuteOfHour_58, "58") , (MinuteOfHour_59, "59") ] in foldr (\(a, b) x -> try (a <$ string b) <|> x) empty t "minute of hour" data SixFigureGroup = SixFigureGroup { _dayofmonth :: DayOfMonth , _hourofday :: HourOfDay , _minuteofhour :: MinuteOfHour } deriving (Eq, Ord, Show) makeClassy ''SixFigureGroup integralMinuteOfHour :: (Eq a, Num a) => Prism' a MinuteOfHour integralMinuteOfHour = prism' (\d -> case d of MinuteOfHour_01 -> 1 MinuteOfHour_00 -> 0 MinuteOfHour_02 -> 2 MinuteOfHour_03 -> 3 MinuteOfHour_04 -> 4 MinuteOfHour_05 -> 5 MinuteOfHour_06 -> 6 MinuteOfHour_07 -> 7 MinuteOfHour_08 -> 8 MinuteOfHour_09 -> 9 MinuteOfHour_10 -> 10 MinuteOfHour_11 -> 11 MinuteOfHour_12 -> 12 MinuteOfHour_13 -> 13 MinuteOfHour_14 -> 14 MinuteOfHour_15 -> 15 MinuteOfHour_16 -> 16 MinuteOfHour_17 -> 17 MinuteOfHour_18 -> 18 MinuteOfHour_19 -> 19 MinuteOfHour_20 -> 20 MinuteOfHour_21 -> 21 MinuteOfHour_22 -> 22 MinuteOfHour_23 -> 23 MinuteOfHour_24 -> 24 MinuteOfHour_25 -> 25 MinuteOfHour_26 -> 26 MinuteOfHour_27 -> 27 MinuteOfHour_28 -> 28 MinuteOfHour_29 -> 29 MinuteOfHour_30 -> 30 MinuteOfHour_31 -> 31 MinuteOfHour_32 -> 32 MinuteOfHour_33 -> 33 MinuteOfHour_34 -> 34 MinuteOfHour_35 -> 35 MinuteOfHour_36 -> 36 MinuteOfHour_37 -> 37 MinuteOfHour_38 -> 38 MinuteOfHour_39 -> 39 MinuteOfHour_40 -> 40 MinuteOfHour_41 -> 41 MinuteOfHour_42 -> 42 MinuteOfHour_43 -> 43 MinuteOfHour_44 -> 44 MinuteOfHour_45 -> 45 MinuteOfHour_46 -> 46 MinuteOfHour_47 -> 47 MinuteOfHour_48 -> 48 MinuteOfHour_49 -> 49 MinuteOfHour_50 -> 50 MinuteOfHour_51 -> 51 MinuteOfHour_52 -> 52 MinuteOfHour_53 -> 53 MinuteOfHour_54 -> 54 MinuteOfHour_55 -> 55 MinuteOfHour_56 -> 56 MinuteOfHour_57 -> 57 MinuteOfHour_58 -> 58 MinuteOfHour_59 -> 59) (\n -> case n of 0 -> Just MinuteOfHour_00 1 -> Just MinuteOfHour_01 2 -> Just MinuteOfHour_02 3 -> Just MinuteOfHour_03 4 -> Just MinuteOfHour_04 5 -> Just MinuteOfHour_05 6 -> Just MinuteOfHour_06 7 -> Just MinuteOfHour_07 8 -> Just MinuteOfHour_08 9 -> Just MinuteOfHour_09 10 -> Just MinuteOfHour_10 11 -> Just MinuteOfHour_11 12 -> Just MinuteOfHour_12 13 -> Just MinuteOfHour_13 14 -> Just MinuteOfHour_14 15 -> Just MinuteOfHour_15 16 -> Just MinuteOfHour_16 17 -> Just MinuteOfHour_17 18 -> Just MinuteOfHour_18 19 -> Just MinuteOfHour_19 20 -> Just MinuteOfHour_20 21 -> Just MinuteOfHour_21 22 -> Just MinuteOfHour_22 23 -> Just MinuteOfHour_23 24 -> Just MinuteOfHour_24 25 -> Just MinuteOfHour_25 26 -> Just MinuteOfHour_26 27 -> Just MinuteOfHour_27 28 -> Just MinuteOfHour_28 29 -> Just MinuteOfHour_29 30 -> Just MinuteOfHour_30 31 -> Just MinuteOfHour_31 32 -> Just MinuteOfHour_32 33 -> Just MinuteOfHour_33 34 -> Just MinuteOfHour_34 35 -> Just MinuteOfHour_35 36 -> Just MinuteOfHour_36 37 -> Just MinuteOfHour_37 38 -> Just MinuteOfHour_38 39 -> Just MinuteOfHour_39 40 -> Just MinuteOfHour_40 41 -> Just MinuteOfHour_41 42 -> Just MinuteOfHour_42 43 -> Just MinuteOfHour_43 44 -> Just MinuteOfHour_44 45 -> Just MinuteOfHour_45 46 -> Just MinuteOfHour_46 47 -> Just MinuteOfHour_47 48 -> Just MinuteOfHour_48 49 -> Just MinuteOfHour_49 50 -> Just MinuteOfHour_50 51 -> Just MinuteOfHour_51 52 -> Just MinuteOfHour_52 53 -> Just MinuteOfHour_53 54 -> Just MinuteOfHour_54 55 -> Just MinuteOfHour_55 56 -> Just MinuteOfHour_56 57 -> Just MinuteOfHour_57 58 -> Just MinuteOfHour_58 59 -> Just MinuteOfHour_59 _ -> Nothing) instance AsMinuteOfHour Int where _MinuteOfHour = integralMinuteOfHour instance AsMinuteOfHour Integer where _MinuteOfHour = integralMinuteOfHour instance AsMinuteOfHour Float where _MinuteOfHour = integralMinuteOfHour instance AsMinuteOfHour Double where _MinuteOfHour = integralMinuteOfHour instance HasDayOfMonth SixFigureGroup where dayOfMonth = dayofmonth . dayOfMonth instance HasHourOfDay SixFigureGroup where hourOfDay = hourofday . hourOfDay instance HasMinuteOfHour SixFigureGroup where minuteOfHour = minuteofhour . minuteOfHour -- | Parse six digits to a six figure group. -- -- >>> parse parseSixFigureGroup "test" "302301" -- Right (SixFigureGroup {_dayofmonth = DayOfMonth_30, _hourofday = HourOfDay_23, _minuteofhour = MinuteOfHour_01}) -- -- >>> parse parseSixFigureGroup "test" "090113" -- Right (SixFigureGroup {_dayofmonth = DayOfMonth_09, _hourofday = HourOfDay_01, _minuteofhour = MinuteOfHour_13}) -- -- >>> isn't _Right (parse parseSixFigureGroup "test" "322301") -- True -- -- >>> isn't _Right (parse parseSixFigureGroup "test" "302401") -- True -- -- >>> isn't _Right (parse parseSixFigureGroup "test" "302360") -- True -- -- >>> isn't _Right (parse parseSixFigureGroup "test" "30230") -- True -- -- >>> parse (show <$> parseSixFigureGroup <|> string "302360") "test" "302360" -- Right "302360" parseSixFigureGroup :: CharParsing f => f SixFigureGroup parseSixFigureGroup = try (SixFigureGroup <$> parseDayOfMonth <*> parseHourOfDay <*> parseMinuteOfHour) "six figure group" -- | Parse six digits to a six figure group appended with 'Z'. -- -- >>> parse parseSixFigureGroup "test" "302301Z" -- Right (SixFigureGroup {_dayofmonth = DayOfMonth_30, _hourofday = HourOfDay_23, _minuteofhour = MinuteOfHour_01}) -- -- >>> parse parseSixFigureGroup "test" "090113Z" -- Right (SixFigureGroup {_dayofmonth = DayOfMonth_09, _hourofday = HourOfDay_01, _minuteofhour = MinuteOfHour_13}) -- -- >>> isn't _Right (parse parseSixFigureGroup "test" "322301Z") -- True -- -- >>> isn't _Right (parse parseSixFigureGroup "test" "302401Z") -- True -- -- >>> isn't _Right (parse parseSixFigureGroup "test" "302360Z") -- True -- -- >>> isn't _Right (parse parseSixFigureGroup "test" "30230Z") -- True -- -- >>> parse (show <$> parseSixFigureGroup <|> string "302360Z") "test" "302360Z" -- Right "302360Z" parseSixFigureGroupz :: CharParsing f => f SixFigureGroup parseSixFigureGroupz = parseSixFigureGroup <* char 'Z'