Parse a date in various formats
Don't repeat yourself

Your code violates the DRY principle. If we replace

germanNumeralShort = parseTimeM True defaultTimeLocale
    "%-d.%-m.%y" (t2s datestring) :: Maybe UTCTime
isoformat = parseTimeM True defaultTimeLocale
    "%Y-%m-%d" (t2s datestring) :: Maybe UTCTime
...


with

parse format = parseTimeM True defaultTimeLocale format (t2s datestring)

germanNumeralShort = parse "%-d.%-m.%y"
isoformat          = parse "%Y-%m-%d"
...


then we immediately notice that we use parse on all formats after another till we find a suitable one.

This can be modelled with map parse, e.g.

map parse
    [ "%b %-d, %Y"
    , "%B %-d, %Y"
    , "%b. %-d, %Y"
    , "%-d.%-m.%Y"
    , "%-d.%-m.%y"
    , "%Y-%m-%d"
    ]


We could use &lt;|&gt; alternatively, e.g.

parse "%b %-d, %Y" &lt;|&gt; parse "%B %-d, %Y" &lt;|&gt; ...


but that's less flexible than the list approach.

Use asum to get a single Maybe from a list of Maybes

To get a single Maybe a from [Maybe a], we can use asum. To get the errorT, we just need to pattern match on a single result and end up with

readDate3 :: Text -&gt;   UTCTime
readDate3 datestring = case result of
   Nohing -&gt; errorT ["readDate3", datestring, "is not parsed"]
   Just t -&gt; t
 where 
   parse format = parseTimeM True defaultTimeLocale format (t2s datestring) 
   result = asum . map parse $
        [ "%b %-d, %Y"
        , "%B %-d, %Y"
        , "%b. %-d, %Y"
        , "%-d.%-m.%Y"
        , "%-d.%-m.%y"
        , "%Y-%m-%d"
        ]


As the current strings are missing some documentation, we could introduce additional types to remedy that:

data DateFormat = ShortMonth
                | LongMonth
                | MonthPoint
                | GermanNumeral
                | GermanNumeralShort
                | ISOFormat

toFormatString :: DateFormat -&gt; String
toFormatString f = case f of
    ShortMonth -&gt; "%b %-d, %Y"
    LongMonth  -&gt; "%B %-d, %Y"
    MonthPoint -&gt; "%b. %-d, %Y"
    -- other left as an exercise


We can also use fromMaybe to get rid of the last pattern match and end up with

import Data.Foldable (asum)
import Data.Maybe (fromMaybe)

readDate :: Text -&gt;   UTCTime
readDate datestring = 
    fromMaybe (errorT ["readDate", datestring, "is not parsed"]) $
      asum . map parse $
        [ ShortMonth
        , LongMonth
        , MonthPoint
        , GermanNumeral
        , GermanNumeralShort
        , ISOFormat
        ]
 where 
   parse format = parseTimeM True defaultTimeLocale (toFormatString format) (t2s datestring)