diff --git a/CHANGES b/CHANGES
--- a/CHANGES
+++ b/CHANGES
@@ -1,23 +1,39 @@
 API-ish changes in the hledger-lib package.
 See also the hledger and project change logs (for user-visible changes).
 
+# 1.3.1 (2017/8/25)
 
-# 1.3 (2017/6/30)
+* Fix a bug with -H showing nothing for empty periods (Nicholas Niro)
+This patch fixes a bug that happened when using the -H option on
+a period without any transaction. Previously, the behavior was no
+output at all even though it should have shown the previous ending balances
+of past transactions. (This is similar to previously using -H with -E,
+but with the extra advantage of not showing empty accounts)
 
-Deps: allow megaparsec 5.3.
+* allow megaparsec 6 (#594)
 
-CSV conversion: assigning to the "balance" field name creates balance
-assertions (#537, Dmitry Astapov).
-Doubled minus signs are handled more robustly (fixes #524, Nicolas Wavrant, Simon Michael)
+* allow megaparsec-6.1 (Hans-Peter Deifel)
 
-The "uncleared" transaction/posting status, and associated UI flags
+* fix test suite with Cabal 2 (#596)
+
+
+# 1.3 (2017/6/30)
+
+journal: The "uncleared" transaction/posting status, and associated UI flags
 and keys, have been renamed to "unmarked" to remove ambiguity and
 confusion.  This means that we have dropped the `--uncleared` flag,
 and our `-U` flag now matches only unmarked things and not pending
 ones.  See the issue and linked mail list discussion for more
 background.  (#564)
 
-Multiple status: query terms are now OR'd together. (#564)
+csv: assigning to the "balance" field name creates balance
+assertions (#537, Dmitry Astapov).
+
+csv: Doubled minus signs are handled more robustly (fixes #524, Nicolas Wavrant, Simon Michael)
+
+Multiple "status:" query terms are now OR'd together. (#564)
+
+deps: allow megaparsec 5.3.
 
 
 # 1.2 (2017/3/31)
diff --git a/Hledger/Data/Dates.hs b/Hledger/Data/Dates.hs
--- a/Hledger/Data/Dates.hs
+++ b/Hledger/Data/Dates.hs
@@ -3,6 +3,7 @@
 {-# LANGUAGE FlexibleContexts #-}
 {-# LANGUAGE TypeFamilies #-}
 {-# LANGUAGE OverloadedStrings #-}
+{-# LANGUAGE ScopedTypeVariables #-}
 {-|
 
 Date parsing and utilities for hledger.
@@ -86,8 +87,7 @@
 import Data.Time.Clock
 import Data.Time.LocalTime
 import Safe (headMay, lastMay, readMay)
-import Text.Megaparsec
-import Text.Megaparsec.Text
+import Text.Megaparsec.Compat
 import Text.Printf
 
 import Hledger.Data.Types
@@ -256,7 +256,7 @@
 
 -- | Parse a period expression to an Interval and overall DateSpan using
 -- the provided reference date, or return a parse error.
-parsePeriodExpr :: Day -> Text -> Either (ParseError Char Dec) (Interval, DateSpan)
+parsePeriodExpr :: Day -> Text -> Either (ParseError Char MPErr) (Interval, DateSpan)
 parsePeriodExpr refdate = parsewith (periodexpr refdate <* eof)
 
 maybePeriod :: Day -> Text -> Maybe (Interval,DateSpan)
@@ -316,13 +316,13 @@
 fixSmartDateStr d s = either
                        (\e->error' $ printf "could not parse date %s %s" (show s) (show e))
                        id
-                       $ (fixSmartDateStrEither d s :: Either (ParseError Char Dec) String)
+                       $ (fixSmartDateStrEither d s :: Either (ParseError Char MPErr) String)
 
 -- | A safe version of fixSmartDateStr.
-fixSmartDateStrEither :: Day -> Text -> Either (ParseError Char Dec) String
+fixSmartDateStrEither :: Day -> Text -> Either (ParseError Char MPErr) String
 fixSmartDateStrEither d = either Left (Right . showDate) . fixSmartDateStrEither' d
 
-fixSmartDateStrEither' :: Day -> Text -> Either (ParseError Char Dec) Day
+fixSmartDateStrEither' :: Day -> Text -> Either (ParseError Char MPErr) Day
 fixSmartDateStrEither' d s = case parsewith smartdateonly (T.toLower s) of
                                Right sd -> Right $ fixSmartDate d sd
                                Left e -> Left e
@@ -550,14 +550,14 @@
 Returns a SmartDate, to be converted to a full date later (see fixSmartDate).
 Assumes any text in the parse stream has been lowercased.
 -}
-smartdate :: Parser SmartDate
+smartdate :: SimpleTextParser SmartDate
 smartdate = do
   -- XXX maybe obscures date errors ? see ledgerdate
   (y,m,d) <- choice' [yyyymmdd, ymd, ym, md, y, d, month, mon, today, yesterday, tomorrow, lastthisnextthing]
   return (y,m,d)
 
 -- | Like smartdate, but there must be nothing other than whitespace after the date.
-smartdateonly :: Parser SmartDate
+smartdateonly :: SimpleTextParser SmartDate
 smartdateonly = do
   d <- smartdate
   many spacenonewline
@@ -579,7 +579,7 @@
 failIfInvalidMonth s = unless (validMonth s) $ fail $ "bad month number: " ++ s
 failIfInvalidDay s   = unless (validDay s)   $ fail $ "bad day number: " ++ s
 
-yyyymmdd :: Parser SmartDate
+yyyymmdd :: SimpleTextParser SmartDate
 yyyymmdd = do
   y <- count 4 digitChar
   m <- count 2 digitChar
@@ -588,7 +588,7 @@
   failIfInvalidDay d
   return (y,m,d)
 
-ymd :: Parser SmartDate
+ymd :: SimpleTextParser SmartDate
 ymd = do
   y <- some digitChar
   failIfInvalidYear y
@@ -600,7 +600,7 @@
   failIfInvalidDay d
   return $ (y,m,d)
 
-ym :: Parser SmartDate
+ym :: SimpleTextParser SmartDate
 ym = do
   y <- some digitChar
   failIfInvalidYear y
@@ -609,19 +609,19 @@
   failIfInvalidMonth m
   return (y,m,"")
 
-y :: Parser SmartDate
+y :: SimpleTextParser SmartDate
 y = do
   y <- some digitChar
   failIfInvalidYear y
   return (y,"","")
 
-d :: Parser SmartDate
+d :: SimpleTextParser SmartDate
 d = do
   d <- some digitChar
   failIfInvalidDay d
   return ("","",d)
 
-md :: Parser SmartDate
+md :: SimpleTextParser SmartDate
 md = do
   m <- some digitChar
   failIfInvalidMonth m
@@ -636,48 +636,54 @@
 -- weekdays       = ["monday","tuesday","wednesday","thursday","friday","saturday","sunday"]
 -- weekdayabbrevs = ["mon","tue","wed","thu","fri","sat","sun"]
 
-monthIndex s = maybe 0 (+1) $ lowercase s `elemIndex` months
-monIndex s   = maybe 0 (+1) $ lowercase s `elemIndex` monthabbrevs
+#if MIN_VERSION_megaparsec(6,0,0)
+lc = T.toLower
+#else
+lc = lowercase
+#endif
 
-month :: Parser SmartDate
+monthIndex t = maybe 0 (+1) $ lc t `elemIndex` months
+monIndex t   = maybe 0 (+1) $ lc t `elemIndex` monthabbrevs
+
+month :: SimpleTextParser SmartDate
 month = do
   m <- choice $ map (try . string) months
   let i = monthIndex m
   return ("",show i,"")
 
-mon :: Parser SmartDate
+mon :: SimpleTextParser SmartDate
 mon = do
   m <- choice $ map (try . string) monthabbrevs
   let i = monIndex m
   return ("",show i,"")
 
-today,yesterday,tomorrow :: Parser SmartDate
+today,yesterday,tomorrow :: SimpleTextParser SmartDate
 today     = string "today"     >> return ("","","today")
 yesterday = string "yesterday" >> return ("","","yesterday")
 tomorrow  = string "tomorrow"  >> return ("","","tomorrow")
 
-lastthisnextthing :: Parser SmartDate
+lastthisnextthing :: SimpleTextParser SmartDate
 lastthisnextthing = do
-  r <- choice [
-        string "last"
-       ,string "this"
-       ,string "next"
+  r <- choice $ map mptext [
+        "last"
+       ,"this"
+       ,"next"
       ]
   many spacenonewline  -- make the space optional for easier scripting
-  p <- choice [
-        string "day"
-       ,string "week"
-       ,string "month"
-       ,string "quarter"
-       ,string "year"
+  p <- choice $ map mptext [
+        "day"
+       ,"week"
+       ,"month"
+       ,"quarter"
+       ,"year"
       ]
 -- XXX support these in fixSmartDate
 --       ++ (map string $ months ++ monthabbrevs ++ weekdays ++ weekdayabbrevs)
 
-  return ("",r,p)
+  return ("", T.unpack r, T.unpack p)
 
 -- |
--- >>> let p = parsewith (periodexpr (parsedate "2008/11/26")) :: T.Text -> Either (ParseError Char Dec) (Interval, DateSpan)
+-- >>> let p = parsewith (periodexpr (parsedate "2008/11/26")) :: T.Text -> Either (ParseError Char MPErr) (Interval, DateSpan)
 -- >>> p "from aug to oct"
 -- Right (NoInterval,DateSpan 2008/08/01-2008/09/30)
 -- >>> p "aug to oct"
@@ -688,7 +694,7 @@
 -- Right (Days 1,DateSpan 2008/08/01-)
 -- >>> p "every week to 2009"
 -- Right (Weeks 1,DateSpan -2008/12/31)
-periodexpr :: Day -> Parser (Interval, DateSpan)
+periodexpr :: Day -> SimpleTextParser (Interval, DateSpan)
 periodexpr rdate = choice $ map try [
                     intervalanddateperiodexpr rdate,
                     intervalperiodexpr,
@@ -696,7 +702,7 @@
                     (return (NoInterval,DateSpan Nothing Nothing))
                    ]
 
-intervalanddateperiodexpr :: Day -> Parser (Interval, DateSpan)
+intervalanddateperiodexpr :: Day -> SimpleTextParser (Interval, DateSpan)
 intervalanddateperiodexpr rdate = do
   many spacenonewline
   i <- reportinginterval
@@ -704,20 +710,20 @@
   s <- periodexprdatespan rdate
   return (i,s)
 
-intervalperiodexpr :: Parser (Interval, DateSpan)
+intervalperiodexpr :: SimpleTextParser (Interval, DateSpan)
 intervalperiodexpr = do
   many spacenonewline
   i <- reportinginterval
   return (i, DateSpan Nothing Nothing)
 
-dateperiodexpr :: Day -> Parser (Interval, DateSpan)
+dateperiodexpr :: Day -> SimpleTextParser (Interval, DateSpan)
 dateperiodexpr rdate = do
   many spacenonewline
   s <- periodexprdatespan rdate
   return (NoInterval, s)
 
 -- Parse a reporting interval.
-reportinginterval :: Parser Interval
+reportinginterval :: SimpleTextParser Interval
 reportinginterval = choice' [
                        tryinterval "day"     "daily"     Days,
                        tryinterval "week"    "weekly"    Weeks,
@@ -757,25 +763,28 @@
       thsuffix = choice' $ map string ["st","nd","rd","th"]
 
       -- Parse any of several variants of a basic interval, eg "daily", "every day", "every N days".
-      tryinterval :: String -> String -> (Int -> Interval) -> Parser Interval
+      tryinterval :: String -> String -> (Int -> Interval) -> SimpleTextParser Interval
       tryinterval singular compact intcons =
-          choice' [
-           do string compact
-              return $ intcons 1,
-           do string "every"
-              many spacenonewline
-              string singular
-              return $ intcons 1,
-           do string "every"
-              many spacenonewline
-              n <- fmap read $ some digitChar
-              many spacenonewline
-              string plural
-              return $ intcons n
-           ]
-          where plural = singular ++ "s"
+        choice' [
+          do mptext compact'
+             return $ intcons 1,
+          do mptext "every"
+             many spacenonewline
+             mptext singular'
+             return $ intcons 1,
+          do mptext "every"
+             many spacenonewline
+             n <- fmap read $ some digitChar
+             many spacenonewline
+             mptext plural'
+             return $ intcons n
+          ]
+        where
+          compact'  = T.pack compact
+          singular' = T.pack singular
+          plural'   = T.pack $ singular ++ "s"
 
-periodexprdatespan :: Day -> Parser DateSpan
+periodexprdatespan :: Day -> SimpleTextParser DateSpan
 periodexprdatespan rdate = choice $ map try [
                             doubledatespan rdate,
                             fromdatespan rdate,
@@ -783,7 +792,7 @@
                             justdatespan rdate
                            ]
 
-doubledatespan :: Day -> Parser DateSpan
+doubledatespan :: Day -> SimpleTextParser DateSpan
 doubledatespan rdate = do
   optional (string "from" >> many spacenonewline)
   b <- smartdate
@@ -792,7 +801,7 @@
   e <- smartdate
   return $ DateSpan (Just $ fixSmartDate rdate b) (Just $ fixSmartDate rdate e)
 
-fromdatespan :: Day -> Parser DateSpan
+fromdatespan :: Day -> SimpleTextParser DateSpan
 fromdatespan rdate = do
   b <- choice [
     do
@@ -806,13 +815,13 @@
     ]
   return $ DateSpan (Just $ fixSmartDate rdate b) Nothing
 
-todatespan :: Day -> Parser DateSpan
+todatespan :: Day -> SimpleTextParser DateSpan
 todatespan rdate = do
   choice [string "to", string "-"] >> many spacenonewline
   e <- smartdate
   return $ DateSpan Nothing (Just $ fixSmartDate rdate e)
 
-justdatespan :: Day -> Parser DateSpan
+justdatespan :: Day -> SimpleTextParser DateSpan
 justdatespan rdate = do
   optional (string "in" >> many spacenonewline)
   d <- smartdate
diff --git a/Hledger/Data/StringFormat.hs b/Hledger/Data/StringFormat.hs
--- a/Hledger/Data/StringFormat.hs
+++ b/Hledger/Data/StringFormat.hs
@@ -19,9 +19,9 @@
 import Data.Char (isPrint)
 import Data.Maybe
 import Test.HUnit
-import Text.Megaparsec
-import Text.Megaparsec.String
+import Text.Megaparsec.Compat
 
+import Hledger.Utils.Parse
 import Hledger.Utils.String (formatString)
 
 -- | A format specification/template to use when rendering a report line item as text.
@@ -86,7 +86,7 @@
 
 defaultStringFormatStyle = BottomAligned
 
-stringformatp :: Parser StringFormat
+stringformatp :: SimpleStringParser StringFormat
 stringformatp = do
   alignspec <- optional (try $ char '%' >> oneOf "^_,")
   let constructor =
@@ -97,10 +97,10 @@
           _        -> defaultStringFormatStyle
   constructor <$> many componentp
 
-componentp :: Parser StringFormatComponent
+componentp :: SimpleStringParser StringFormatComponent
 componentp = formatliteralp <|> formatfieldp
 
-formatliteralp :: Parser StringFormatComponent
+formatliteralp :: SimpleStringParser StringFormatComponent
 formatliteralp = do
     s <- some c
     return $ FormatLiteral s
@@ -109,7 +109,7 @@
       c =     (satisfy isPrintableButNotPercentage <?> "printable character")
           <|> try (string "%%" >> return '%')
 
-formatfieldp :: Parser StringFormatComponent
+formatfieldp :: SimpleStringParser StringFormatComponent
 formatfieldp = do
     char '%'
     leftJustified <- optional (char '-')
@@ -124,7 +124,7 @@
         Just text -> Just m where ((m,_):_) = readDec text
         _ -> Nothing
 
-fieldp :: Parser ReportItemField
+fieldp :: SimpleStringParser ReportItemField
 fieldp = do
         try (string "account" >> return AccountField)
     <|> try (string "depth_spacer" >> return DepthSpacerField)
diff --git a/Hledger/Query.hs b/Hledger/Query.hs
--- a/Hledger/Query.hs
+++ b/Hledger/Query.hs
@@ -1,7 +1,7 @@
 {-|
 
 A general query system for matching things (accounts, postings,
-transactions..)  by various criteria, and a parser for query expressions.
+transactions..)  by various criteria, and a SimpleTextParser for query expressions.
 
 -}
 
@@ -55,8 +55,7 @@
 import Data.Time.Calendar
 import Safe (readDef, headDef)
 import Test.HUnit
-import Text.Megaparsec
-import Text.Megaparsec.Text
+import Text.Megaparsec.Compat
 
 import Hledger.Utils hiding (words')
 import Hledger.Data.Types
@@ -185,23 +184,23 @@
 words'' :: [T.Text] -> T.Text -> [T.Text]
 words'' prefixes = fromparse . parsewith maybeprefixedquotedphrases -- XXX
     where
-      maybeprefixedquotedphrases :: Parser [T.Text]
+      maybeprefixedquotedphrases :: SimpleTextParser [T.Text]
       maybeprefixedquotedphrases = choice' [prefixedQuotedPattern, singleQuotedPattern, doubleQuotedPattern, pattern] `sepBy` some spacenonewline
-      prefixedQuotedPattern :: Parser T.Text
+      prefixedQuotedPattern :: SimpleTextParser T.Text
       prefixedQuotedPattern = do
-        not' <- fromMaybe "" `fmap` (optional $ string "not:")
-        let allowednexts | null not' = prefixes
-                         | otherwise = prefixes ++ [""]
-        next <- fmap T.pack $ choice' $ map (string . T.unpack) allowednexts
+        not' <- fromMaybe "" `fmap` (optional $ mptext "not:")
+        let allowednexts | T.null not' = prefixes
+                         | otherwise   = prefixes ++ [""]
+        next <- choice' $ map mptext allowednexts
         let prefix :: T.Text
-            prefix = T.pack not' <> next
+            prefix = not' <> next
         p <- singleQuotedPattern <|> doubleQuotedPattern
         return $ prefix <> stripquotes p
-      singleQuotedPattern :: Parser T.Text
+      singleQuotedPattern :: SimpleTextParser T.Text
       singleQuotedPattern = between (char '\'') (char '\'') (many $ noneOf ("'" :: [Char])) >>= return . stripquotes . T.pack
-      doubleQuotedPattern :: Parser T.Text
+      doubleQuotedPattern :: SimpleTextParser T.Text
       doubleQuotedPattern = between (char '"') (char '"') (many $ noneOf ("\"" :: [Char])) >>= return . stripquotes . T.pack
-      pattern :: Parser T.Text
+      pattern :: SimpleTextParser T.Text
       pattern = fmap T.pack $ many (noneOf (" \n\r" :: [Char]))
 
 tests_words'' = [
diff --git a/Hledger/Read/Common.hs b/Hledger/Read/Common.hs
--- a/Hledger/Read/Common.hs
+++ b/Hledger/Read/Common.hs
@@ -36,8 +36,7 @@
 import Data.Time.LocalTime
 import Safe
 import System.Time (getClockTime)
-import Text.Megaparsec hiding (parse,State)
-import Text.Megaparsec.Text
+import Text.Megaparsec.Compat
 
 import Hledger.Data
 import Hledger.Utils
@@ -47,12 +46,12 @@
 --- * parsing utils
 
 -- | Run a string parser with no state in the identity monad.
-runTextParser, rtp :: TextParser Identity a -> Text -> Either (ParseError Char Dec) a
+runTextParser, rtp :: TextParser Identity a -> Text -> Either (ParseError Char MPErr) a
 runTextParser p t =  runParser p "" t
 rtp = runTextParser
 
 -- | Run a journal parser with a null journal-parsing state.
-runJournalParser, rjp :: Monad m => TextParser m a -> Text -> m (Either (ParseError Char Dec) a)
+runJournalParser, rjp :: Monad m => TextParser m a -> Text -> m (Either (ParseError Char MPErr) a)
 runJournalParser p t = runParserT p "" t
 rjp = runJournalParser
 
@@ -89,7 +88,7 @@
                         Left e  -> throwError e
     Left e   -> throwError $ parseErrorPretty e
 
-parseAndFinaliseJournal' :: JournalParser ParsedJournal -> Bool -> FilePath -> Text -> ExceptT String IO Journal
+parseAndFinaliseJournal' :: JournalParser Identity ParsedJournal -> Bool -> FilePath -> Text -> ExceptT String IO Journal
 parseAndFinaliseJournal' parser assrt f txt = do
   t <- liftIO getClockTime
   y <- liftIO getCurrentYear
@@ -100,32 +99,32 @@
                         Left e  -> throwError e
     Left e   -> throwError $ parseErrorPretty e
 
-setYear :: Year -> JournalStateParser m ()
+setYear :: Year -> JournalParser m ()
 setYear y = modify' (\j -> j{jparsedefaultyear=Just y})
 
-getYear :: JournalStateParser m (Maybe Year)
+getYear :: JournalParser m (Maybe Year)
 getYear = fmap jparsedefaultyear get
 
-setDefaultCommodityAndStyle :: (CommoditySymbol,AmountStyle) -> JournalStateParser m ()
+setDefaultCommodityAndStyle :: (CommoditySymbol,AmountStyle) -> JournalParser m ()
 setDefaultCommodityAndStyle cs = modify' (\j -> j{jparsedefaultcommodity=Just cs})
 
-getDefaultCommodityAndStyle :: JournalStateParser m (Maybe (CommoditySymbol,AmountStyle))
+getDefaultCommodityAndStyle :: JournalParser m (Maybe (CommoditySymbol,AmountStyle))
 getDefaultCommodityAndStyle = jparsedefaultcommodity `fmap` get
 
-pushAccount :: AccountName -> JournalStateParser m ()
+pushAccount :: AccountName -> JournalParser m ()
 pushAccount acct = modify' (\j -> j{jaccounts = acct : jaccounts j})
 
-pushParentAccount :: AccountName -> JournalStateParser m ()
+pushParentAccount :: AccountName -> JournalParser m ()
 pushParentAccount acct = modify' (\j -> j{jparseparentaccounts = acct : jparseparentaccounts j})
 
-popParentAccount :: JournalStateParser m ()
+popParentAccount :: JournalParser m ()
 popParentAccount = do
   j <- get
   case jparseparentaccounts j of
     []       -> unexpected (Tokens ('E' :| "nd of apply account block with no beginning"))
     (_:rest) -> put j{jparseparentaccounts=rest}
 
-getParentAccount :: JournalStateParser m AccountName
+getParentAccount :: JournalParser m AccountName
 getParentAccount = fmap (concatAccountNames . reverse . jparseparentaccounts) get
 
 addAccountAlias :: MonadState Journal m => AccountAlias -> m ()
@@ -181,7 +180,7 @@
 codep :: TextParser m String
 codep = try (do { some spacenonewline; char '(' <?> "codep"; anyChar `manyTill` char ')' } ) <|> return ""
 
-descriptionp :: JournalStateParser m String
+descriptionp :: JournalParser m String
 descriptionp = many (noneOf (";\n" :: [Char]))
 
 --- ** dates
@@ -190,7 +189,7 @@
 -- Hyphen (-) and period (.) are also allowed as separators.
 -- The year may be omitted if a default year has been set.
 -- Leading zeroes may be omitted.
-datep :: JournalStateParser m Day
+datep :: JournalParser m Day
 datep = do
   -- hacky: try to ensure precise errors for invalid dates
   -- XXX reported error position is not too good
@@ -220,7 +219,7 @@
 -- Seconds are optional.
 -- The timezone is optional and ignored (the time is always interpreted as a local time).
 -- Leading zeroes may be omitted (except in a timezone).
-datetimep :: JournalStateParser m LocalTime
+datetimep :: JournalParser m LocalTime
 datetimep = do
   day <- datep
   lift $ some spacenonewline
@@ -248,7 +247,7 @@
   -- return $ localTimeToUTC tz' $ LocalTime day $ TimeOfDay h' m' (fromIntegral s')
   return $ LocalTime day $ TimeOfDay h' m' (fromIntegral s')
 
-secondarydatep :: Day -> JournalStateParser m Day
+secondarydatep :: Day -> JournalParser m Day
 secondarydatep primarydate = do
   char '='
   -- kludgy way to use primary date for default year
@@ -274,7 +273,7 @@
 --- ** account names
 
 -- | Parse an account name, then apply any parent account prefix and/or account aliases currently in effect.
-modifiedaccountnamep :: JournalStateParser m AccountName
+modifiedaccountnamep :: JournalParser m AccountName
 modifiedaccountnamep = do
   parent <- getParentAccount
   aliases <- getAccountAliases
@@ -313,7 +312,7 @@
 -- | Parse whitespace then an amount, with an optional left or right
 -- currency symbol and optional price, or return the special
 -- "missing" marker amount.
-spaceandamountormissingp :: Monad m => JournalStateParser m MixedAmount
+spaceandamountormissingp :: Monad m => JournalParser m MixedAmount
 spaceandamountormissingp =
   try (do
         lift $ some spacenonewline
@@ -337,7 +336,7 @@
 -- | Parse a single-commodity amount, with optional symbol on the left or
 -- right, optional unit or total price, and optional (ignored)
 -- ledger-style balance assertion or fixed lot price declaration.
-amountp :: Monad m => JournalStateParser m Amount
+amountp :: Monad m => JournalParser m Amount
 amountp = try leftsymbolamountp <|> try rightsymbolamountp <|> nosymbolamountp
 
 #ifdef TESTS
@@ -377,7 +376,7 @@
   return $ case multiplier of Just '*' -> True
                               _        -> False
 
-leftsymbolamountp :: Monad m => JournalStateParser m Amount
+leftsymbolamountp :: Monad m => JournalParser m Amount
 leftsymbolamountp = do
   sign <- lift signp
   m <- lift multiplierp
@@ -390,7 +389,7 @@
   return $ applysign $ Amount c q p s m
   <?> "left-symbol amount"
 
-rightsymbolamountp :: Monad m => JournalStateParser m Amount
+rightsymbolamountp :: Monad m => JournalParser m Amount
 rightsymbolamountp = do
   m <- lift multiplierp
   (q,prec,mdec,mgrps) <- lift numberp
@@ -401,7 +400,7 @@
   return $ Amount c q p s m
   <?> "right-symbol amount"
 
-nosymbolamountp :: Monad m => JournalStateParser m Amount
+nosymbolamountp :: Monad m => JournalParser m Amount
 nosymbolamountp = do
   m <- lift multiplierp
   (q,prec,mdec,mgrps) <- lift numberp
@@ -427,7 +426,7 @@
 simplecommoditysymbolp :: TextParser m CommoditySymbol
 simplecommoditysymbolp = T.pack <$> some (noneOf nonsimplecommoditychars)
 
-priceamountp :: Monad m => JournalStateParser m Price
+priceamountp :: Monad m => JournalParser m Price
 priceamountp =
     try (do
           lift (many spacenonewline)
@@ -443,7 +442,7 @@
             return $ UnitPrice a))
          <|> return NoPrice
 
-partialbalanceassertionp :: Monad m => JournalStateParser m (Maybe Amount)
+partialbalanceassertionp :: Monad m => JournalParser m (Maybe Amount)
 partialbalanceassertionp =
     try (do
           lift (many spacenonewline)
@@ -464,7 +463,7 @@
 --          <|> return Nothing
 
 -- http://ledger-cli.org/3.0/doc/ledger3.html#Fixing-Lot-Prices
-fixedlotpricep :: Monad m => JournalStateParser m (Maybe Amount)
+fixedlotpricep :: Monad m => JournalParser m (Maybe Amount)
 fixedlotpricep =
     try (do
           lift (many spacenonewline)
@@ -564,7 +563,7 @@
 
 --- ** comments
 
-multilinecommentp :: JournalStateParser m ()
+multilinecommentp :: JournalParser m ()
 multilinecommentp = do
   string "comment" >> lift (many spacenonewline) >> newline
   go
@@ -573,13 +572,13 @@
          <|> (anyLine >> go)
     anyLine = anyChar `manyTill` newline
 
-emptyorcommentlinep :: JournalStateParser m ()
+emptyorcommentlinep :: JournalParser m ()
 emptyorcommentlinep = do
   lift (many spacenonewline) >> (commentp <|> (lift (many spacenonewline) >> newline >> return ""))
   return ()
 
 -- | Parse a possibly multi-line comment following a semicolon.
-followingcommentp :: JournalStateParser m Text
+followingcommentp :: JournalParser m Text
 followingcommentp =
   -- ptrace "followingcommentp"
   do samelinecomment <- lift (many spacenonewline) >> (try semicoloncommentp <|> (newline >> return ""))
@@ -641,16 +640,16 @@
 
   return (comment, tags, mdate, mdate2)
 
-commentp :: JournalStateParser m Text
+commentp :: JournalParser m Text
 commentp = commentStartingWithp commentchars
 
 commentchars :: [Char]
 commentchars = "#;*"
 
-semicoloncommentp :: JournalStateParser m Text
+semicoloncommentp :: JournalParser m Text
 semicoloncommentp = commentStartingWithp ";"
 
-commentStartingWithp :: [Char] -> JournalStateParser m Text
+commentStartingWithp :: [Char] -> JournalParser m Text
 commentStartingWithp cs = do
   -- ptrace "commentStartingWith"
   oneOf cs
@@ -681,7 +680,7 @@
     Left _  -> [] -- shouldn't happen
 
 -- | Parse all tags found in a string.
-tagsp :: Parser [Tag]
+tagsp :: SimpleTextParser [Tag]
 tagsp = -- do
   -- pdbg 0 $ "tagsp"
   many (try (nontagp >> tagp))
@@ -690,7 +689,7 @@
 --
 -- >>> rtp nontagp "\na b:, \nd:e, f"
 -- Right "\na "
-nontagp :: Parser String
+nontagp :: SimpleTextParser String
 nontagp = -- do
   -- pdbg 0 "nontagp"
   -- anyChar `manyTill` (lookAhead (try (tagorbracketeddatetagsp Nothing >> return ()) <|> eof))
@@ -704,7 +703,7 @@
 -- >>> rtp tagp "a:b b , c AuxDate: 4/2"
 -- Right ("a","b b")
 --
-tagp :: Parser Tag
+tagp :: SimpleTextParser Tag
 tagp = do
   -- pdbg 0 "tagp"
   n <- tagnamep
@@ -714,7 +713,7 @@
 -- |
 -- >>> rtp tagnamep "a:"
 -- Right "a"
-tagnamep :: Parser Text
+tagnamep :: SimpleTextParser Text
 tagnamep = -- do
   -- pdbg 0 "tagnamep"
   T.pack <$> some (noneOf (": \t\n" :: [Char])) <* char ':'
@@ -761,13 +760,13 @@
 datetagp mdefdate = do
   -- pdbg 0 "datetagp"
   string "date"
-  n <- T.pack . fromMaybe "" <$> optional (string "2")
+  n <- fromMaybe "" <$> optional (mptext "2")
   char ':'
   startpos <- getPosition
   v <- lift tagvaluep
   -- re-parse value as a date.
   j <- get
-  let ep :: Either (ParseError Char Dec) Day
+  let ep :: Either (ParseError Char MPErr) Day
       ep = parseWithState'
              j{jparsedefaultyear=first3.toGregorian <$> mdefdate}
              -- The value extends to a comma, newline, or end of file.
@@ -827,7 +826,7 @@
   -- looks sufficiently like a bracketed date, now we
   -- re-parse as dates and throw any errors
   j <- get
-  let ep :: Either (ParseError Char Dec) (Maybe Day, Maybe Day)
+  let ep :: Either (ParseError Char MPErr) (Maybe Day, Maybe Day)
       ep = parseWithState'
              j{jparsedefaultyear=first3.toGregorian <$> mdefdate}
              (do
diff --git a/Hledger/Read/CsvReader.hs b/Hledger/Read/CsvReader.hs
--- a/Hledger/Read/CsvReader.hs
+++ b/Hledger/Read/CsvReader.hs
@@ -38,7 +38,6 @@
 import Data.List.Compat
 import Data.Maybe
 import Data.Ord
-import qualified Data.Set as S
 import Data.Text (Text)
 import qualified Data.Text as T
 import Data.Time.Calendar (Day)
@@ -54,8 +53,7 @@
 import System.IO (stderr)
 import Test.HUnit hiding (State)
 import Text.CSV (parseCSV, CSV)
-import Text.Megaparsec hiding (parse, State)
-import Text.Megaparsec.Text
+import Text.Megaparsec.Compat hiding (parse)
 import qualified Text.Parsec as Parsec
 import Text.Printf (hPrintf,printf)
 
@@ -130,21 +128,24 @@
   -- let (headerlines, datalines) = identifyHeaderLines records
   --     mfieldnames = lastMay headerlines
 
-  -- convert to transactions and return as a journal
-  let txns = snd $ mapAccumL
-                     (\pos r -> (pos,
-                                 transactionFromCsvRecord
-                                   (let SourcePos name line col =  pos in
-                                    SourcePos name (unsafePos $ unPos line + 1) col)
-                                   rules
-                                    r))
-                     (initialPos parsecfilename) records
+  let 
+    -- convert CSV records to transactions
+    txns = snd $ mapAccumL
+                   (\pos r -> 
+                      let
+                        SourcePos name line col = pos
+                        line' = (mpMkPos . (+1) . mpUnPos) line
+                        pos' = SourcePos name line' col
+                      in
+                        (pos, transactionFromCsvRecord pos' rules r)
+                   )
+                   (initialPos parsecfilename) records
 
   -- heuristic: if the records appear to have been in reverse date order,
   -- reverse them all as well as doing a txn date sort,
   -- so that same-day txns' original order is preserved
-      txns' | length txns > 1 && tdate (head txns) > tdate (last txns) = reverse txns
-            | otherwise = txns
+    txns' | length txns > 1 && tdate (head txns) > tdate (last txns) = reverse txns
+          | otherwise = txns
 
   when (not rulesfileexists) $ do
     hPrintf stderr "created default conversion rules file %s, edit this for better results\n" rulesfile
@@ -300,7 +301,7 @@
   rconditionalblocks :: [ConditionalBlock]
 } deriving (Show, Eq)
 
-type CsvRulesParser a = StateT CsvRules Parser a
+type CsvRulesParser a = StateT CsvRules SimpleTextParser a
 
 type DirectiveName    = String
 type CsvFieldName     = String
@@ -382,14 +383,11 @@
     Right r -> do
                r_ <- liftIO $ runExceptT $ validateRules r
                ExceptT $ case r_ of
-                 Left e -> return $ Left $ parseErrorPretty $ toParseError e
+                 Left  s -> return $ Left $ parseErrorPretty $ mpMkParseError rulesfile s
                  Right r -> return $ Right r
-  where
-    toParseError :: forall s. Ord s => s -> ParseError Char s
-    toParseError s = (mempty :: ParseError Char s) { errorCustom = S.singleton s}
 
 -- | Parse this text as CSV conversion rules. The file path is for error messages.
-parseCsvRules :: FilePath -> T.Text -> Either (ParseError Char Dec) CsvRules
+parseCsvRules :: FilePath -> T.Text -> Either (ParseError Char MPErr) CsvRules
 -- parseCsvRules rulesfile s = runParser csvrulesfile nullrules{baseAccount=takeBaseName rulesfile} rulesfile s
 parseCsvRules rulesfile s =
   runParser (evalStateT rulesp rules) rulesfile s
@@ -441,10 +439,10 @@
 directivep :: CsvRulesParser (DirectiveName, String)
 directivep = (do
   lift $ pdbg 3 "trying directive"
-  d <- choiceInState $ map string directives
+  d <- fmap T.unpack $ choiceInState $ map (lift . mptext . T.pack) directives
   v <- (((char ':' >> lift (many spacenonewline)) <|> lift (some spacenonewline)) >> directivevalp)
        <|> (optional (char ':') >> lift (many spacenonewline) >> lift eolof >> return "")
-  return (d,v)
+  return (d, v)
   ) <?> "directive"
 
 directives =
@@ -496,7 +494,9 @@
   <?> "field assignment"
 
 journalfieldnamep :: CsvRulesParser String
-journalfieldnamep = lift (pdbg 2 "trying journalfieldnamep") >> choiceInState (map string journalfieldnames)
+journalfieldnamep = do
+  lift (pdbg 2 "trying journalfieldnamep")
+  T.unpack <$> choiceInState (map (lift . mptext . T.pack) journalfieldnames)
 
 -- Transaction fields and pseudo fields for CSV conversion. 
 -- Names must precede any other name they contain, for the parser 
@@ -556,7 +556,7 @@
   <?> "record matcher"
 
 matchoperatorp :: CsvRulesParser String
-matchoperatorp = choiceInState $ map string
+matchoperatorp = fmap T.unpack $ choiceInState $ map mptext
   ["~"
   -- ,"!~"
   -- ,"="
diff --git a/Hledger/Read/JournalReader.hs b/Hledger/Read/JournalReader.hs
--- a/Hledger/Read/JournalReader.hs
+++ b/Hledger/Read/JournalReader.hs
@@ -90,7 +90,7 @@
 import Test.Framework
 import Text.Megaparsec.Error
 #endif
-import Text.Megaparsec hiding (parse)
+import Text.Megaparsec.Compat hiding (parse)
 import Text.Printf
 import System.FilePath
 
@@ -187,7 +187,7 @@
       let curdir = takeDirectory (sourceName parentpos)
       filepath <- expandPath curdir filename `orRethrowIOError` (show parentpos ++ " locating " ++ filename)
       txt      <- readFileAnyLineEnding filepath `orRethrowIOError` (show parentpos ++ " reading " ++ filepath)
-      (ej1::Either (ParseError Char Dec) ParsedJournal) <-
+      (ej1::Either (ParseError Char MPErr) ParsedJournal) <-
         runParserT
            (evalStateT
               (choiceInState
@@ -227,7 +227,7 @@
     (Right <$> io)
     `C.catch` \(e::C.IOException) -> return $ Left $ printf "%s:\n%s" msg (show e)
 
-accountdirectivep :: JournalStateParser m ()
+accountdirectivep :: JournalParser m ()
 accountdirectivep = do
   string "account"
   lift (some spacenonewline)
@@ -237,7 +237,7 @@
   modify' (\j -> j{jaccounts = acct : jaccounts j})
 
 
-indentedlinep :: JournalStateParser m String
+indentedlinep :: JournalParser m String
 indentedlinep = lift (some spacenonewline) >> (rstrip <$> lift restofline)
 
 -- | Parse a one-line or multi-line commodity directive.
@@ -253,7 +253,7 @@
 --
 -- >>> Right _ <- rejp commoditydirectiveonelinep "commodity $1.00"
 -- >>> Right _ <- rejp commoditydirectiveonelinep "commodity $1.00 ; blah\n"
-commoditydirectiveonelinep :: Monad m => JournalStateParser m ()
+commoditydirectiveonelinep :: Monad m => JournalParser m ()
 commoditydirectiveonelinep = do
   string "commodity"
   lift (some spacenonewline)
@@ -292,7 +292,7 @@
     else parserErrorAt pos $
          printf "commodity directive symbol \"%s\" and format directive symbol \"%s\" should be the same" expectedsym acommodity
 
-applyaccountdirectivep :: JournalStateParser m ()
+applyaccountdirectivep :: JournalParser m ()
 applyaccountdirectivep = do
   string "apply" >> lift (some spacenonewline) >> string "account"
   lift (some spacenonewline)
@@ -300,12 +300,12 @@
   newline
   pushParentAccount parent
 
-endapplyaccountdirectivep :: JournalStateParser m ()
+endapplyaccountdirectivep :: JournalParser m ()
 endapplyaccountdirectivep = do
   string "end" >> lift (some spacenonewline) >> string "apply" >> lift (some spacenonewline) >> string "account"
   popParentAccount
 
-aliasdirectivep :: JournalStateParser m ()
+aliasdirectivep :: JournalParser m ()
 aliasdirectivep = do
   string "alias"
   lift (some spacenonewline)
@@ -336,12 +336,12 @@
   repl <- rstrip <$> anyChar `manyTill` eolof
   return $ RegexAlias re repl
 
-endaliasesdirectivep :: JournalStateParser m ()
+endaliasesdirectivep :: JournalParser m ()
 endaliasesdirectivep = do
   string "end aliases"
   clearAccountAliases
 
-tagdirectivep :: JournalStateParser m ()
+tagdirectivep :: JournalParser m ()
 tagdirectivep = do
   string "tag" <?> "tag directive"
   lift (some spacenonewline)
@@ -349,13 +349,13 @@
   lift restofline
   return ()
 
-endtagdirectivep :: JournalStateParser m ()
+endtagdirectivep :: JournalParser m ()
 endtagdirectivep = do
   (string "end tag" <|> string "pop") <?> "end tag or pop directive"
   lift restofline
   return ()
 
-defaultyeardirectivep :: JournalStateParser m ()
+defaultyeardirectivep :: JournalParser m ()
 defaultyeardirectivep = do
   char 'Y' <?> "default year"
   lift (many spacenonewline)
@@ -364,7 +364,7 @@
   failIfInvalidYear y
   setYear y'
 
-defaultcommoditydirectivep :: Monad m => JournalStateParser m ()
+defaultcommoditydirectivep :: Monad m => JournalParser m ()
 defaultcommoditydirectivep = do
   char 'D' <?> "default commodity"
   lift (some spacenonewline)
@@ -372,7 +372,7 @@
   lift restofline
   setDefaultCommodityAndStyle (acommodity, astyle)
 
-marketpricedirectivep :: Monad m => JournalStateParser m MarketPrice
+marketpricedirectivep :: Monad m => JournalParser m MarketPrice
 marketpricedirectivep = do
   char 'P' <?> "market price"
   lift (many spacenonewline)
@@ -384,7 +384,7 @@
   lift restofline
   return $ MarketPrice date symbol price
 
-ignoredpricecommoditydirectivep :: JournalStateParser m ()
+ignoredpricecommoditydirectivep :: JournalParser m ()
 ignoredpricecommoditydirectivep = do
   char 'N' <?> "ignored-price commodity"
   lift (some spacenonewline)
@@ -392,7 +392,7 @@
   lift restofline
   return ()
 
-commodityconversiondirectivep :: Monad m => JournalStateParser m ()
+commodityconversiondirectivep :: Monad m => JournalParser m ()
 commodityconversiondirectivep = do
   char 'C' <?> "commodity conversion"
   lift (some spacenonewline)
diff --git a/Hledger/Read/TimeclockReader.hs b/Hledger/Read/TimeclockReader.hs
--- a/Hledger/Read/TimeclockReader.hs
+++ b/Hledger/Read/TimeclockReader.hs
@@ -60,7 +60,7 @@
 import           Data.Text (Text)
 import qualified Data.Text as T
 import           Test.HUnit
-import           Text.Megaparsec hiding (parse)
+import           Text.Megaparsec.Compat hiding (parse)
 
 import           Hledger.Data
 -- XXX too much reuse ?
@@ -105,7 +105,7 @@
                           ] <?> "timeclock entry, or default year or historical price directive"
 
 -- | Parse a timeclock entry.
-timeclockentryp :: JournalStateParser m TimeclockEntry
+timeclockentryp :: JournalParser m TimeclockEntry
 timeclockentryp = do
   sourcepos <- genericSourcePos <$> lift getPosition
   code <- oneOf ("bhioO" :: [Char])
diff --git a/Hledger/Read/TimedotReader.hs b/Hledger/Read/TimedotReader.hs
--- a/Hledger/Read/TimedotReader.hs
+++ b/Hledger/Read/TimedotReader.hs
@@ -42,7 +42,7 @@
 import Data.Maybe
 import Data.Text (Text)
 import Test.HUnit
-import Text.Megaparsec hiding (parse)
+import Text.Megaparsec.Compat hiding (parse)
 
 import Hledger.Data
 import Hledger.Read.Common
@@ -66,12 +66,12 @@
 parse :: Maybe FilePath -> Bool -> FilePath -> Text -> ExceptT String IO Journal
 parse _ = parseAndFinaliseJournal timedotfilep
 
-timedotfilep :: JournalStateParser m ParsedJournal
+timedotfilep :: JournalParser m ParsedJournal
 timedotfilep = do many timedotfileitemp
                   eof
                   get
     where
-      timedotfileitemp :: JournalStateParser m ()
+      timedotfileitemp :: JournalParser m ()
       timedotfileitemp = do
         ptrace "timedotfileitemp"
         choice [
@@ -89,7 +89,7 @@
 -- biz.research .
 -- inc.client1  .... .... .... .... .... ....
 -- @
-timedotdayp :: JournalStateParser m [Transaction]
+timedotdayp :: JournalParser m [Transaction]
 timedotdayp = do
   ptrace " timedotdayp"
   d <- datep <* lift eolof
@@ -101,7 +101,7 @@
 -- @
 -- fos.haskell  .... ..
 -- @
-timedotentryp :: JournalStateParser m Transaction
+timedotentryp :: JournalParser m Transaction
 timedotentryp = do
   ptrace "  timedotentryp"
   pos <- genericSourcePos <$> getPosition
@@ -125,14 +125,14 @@
         }
   return t
 
-timedotdurationp :: JournalStateParser m Quantity
+timedotdurationp :: JournalParser m Quantity
 timedotdurationp = try timedotnumberp <|> timedotdotsp
 
 -- | Parse a duration written as a decimal number of hours (optionally followed by the letter h).
 -- @
 -- 1.5h
 -- @
-timedotnumberp :: JournalStateParser m Quantity
+timedotnumberp :: JournalParser m Quantity
 timedotnumberp = do
    (q, _, _, _) <- lift numberp
    lift (many spacenonewline)
@@ -144,7 +144,7 @@
 -- @
 -- .... ..
 -- @
-timedotdotsp :: JournalStateParser m Quantity
+timedotdotsp :: JournalParser m Quantity
 timedotdotsp = do
   dots <- filter (not.isSpace) <$> many (oneOf (". " :: [Char]))
   return $ (/4) $ fromIntegral $ length dots
diff --git a/Hledger/Reports/MultiBalanceReports.hs b/Hledger/Reports/MultiBalanceReports.hs
--- a/Hledger/Reports/MultiBalanceReports.hs
+++ b/Hledger/Reports/MultiBalanceReports.hs
@@ -155,7 +155,7 @@
           dbg1 "displayedAccts" $
           (if tree_ opts then expandAccountNames else id) $
           nub $ map (clipOrEllipsifyAccountName depth) $
-          if empty_ opts then nub $ sort $ startAccts ++ postedAccts else postedAccts
+          if empty_ opts || (balancetype_ opts) == HistoricalBalance then nub $ sort $ startAccts ++ postedAccts else postedAccts
 
       acctBalChangesPerSpan :: [[(ClippedAccountName, MixedAmount)]] =
           dbg1 "acctBalChangesPerSpan"
diff --git a/Hledger/Utils/Parse.hs b/Hledger/Utils/Parse.hs
--- a/Hledger/Utils/Parse.hs
+++ b/Hledger/Utils/Parse.hs
@@ -1,38 +1,42 @@
-{-# LANGUAGE FlexibleContexts, TypeFamilies #-}
+{-# LANGUAGE CPP, TypeFamilies #-}
 module Hledger.Utils.Parse where
 
 import Control.Monad.Except
+import Control.Monad.State.Strict (StateT, evalStateT)
 import Data.Char
+import Data.Functor.Identity (Identity(..))
 import Data.List
 import Data.Text (Text)
-import Text.Megaparsec hiding (State)
-import Data.Functor.Identity (Identity(..))
+import Text.Megaparsec.Compat
 import Text.Printf
 
-import Control.Monad.State.Strict (StateT, evalStateT)
-
 import Hledger.Data.Types
 import Hledger.Utils.UTF8IOCompat (error')
 
--- | A parser of strict text with generic user state, monad and return type.
-type TextParser m a = ParsecT Dec Text m a
+-- | A parser of string to some type.
+type SimpleStringParser a = Parsec MPErr String a
 
-type JournalStateParser m a = StateT Journal (ParsecT Dec Text m) a
+-- | A parser of strict text to some type.
+type SimpleTextParser = Parsec MPErr Text  -- XXX an "a" argument breaks the CsvRulesParser declaration somehow
 
-type JournalParser a = StateT Journal (ParsecT Dec Text Identity) a
+-- | A parser of text in some monad.
+type TextParser m a = ParsecT MPErr Text m a
 
--- | A journal parser that runs in IO and can throw an error mid-parse.
-type ErroringJournalParser m a = StateT Journal (ParsecT Dec Text (ExceptT String m)) a
+-- | A parser of text in some monad, with a journal as state.
+type JournalParser m a = StateT Journal (ParsecT MPErr Text m) a
 
+-- | A parser of text in some monad, with a journal as state, that can throw an error string mid-parse.
+type ErroringJournalParser m a = StateT Journal (ParsecT MPErr Text (ExceptT String m)) a
+
 -- | Backtracking choice, use this when alternatives share a prefix.
 -- Consumes no input if all choices fail.
 choice' :: [TextParser m a] -> TextParser m a
-choice' = choice . map Text.Megaparsec.try
+choice' = choice . map try
 
 -- | Backtracking choice, use this when alternatives share a prefix.
 -- Consumes no input if all choices fail.
-choiceInState :: [StateT s (ParsecT Dec Text m) a] -> StateT s (ParsecT Dec Text m) a
-choiceInState = choice . map Text.Megaparsec.try
+choiceInState :: [StateT s (ParsecT MPErr Text m) a] -> StateT s (ParsecT MPErr Text m) a
+choiceInState = choice . map try
 
 parsewith :: Parsec e Text a -> Text -> Either (ParseError Char e) a
 parsewith p = runParser p ""
@@ -40,10 +44,15 @@
 parsewithString :: Parsec e String a -> String -> Either (ParseError Char e) a
 parsewithString p = runParser p ""
 
-parseWithState :: Monad m => st -> StateT st (ParsecT Dec Text m) a -> Text -> m (Either (ParseError Char Dec) a)
+parseWithState :: Monad m => st -> StateT st (ParsecT MPErr Text m) a -> Text -> m (Either (ParseError Char MPErr) a)
 parseWithState ctx p s = runParserT (evalStateT p ctx) "" s
 
-parseWithState' :: (Stream s, ErrorComponent e) => st -> StateT st (ParsecT e s Identity) a -> s -> (Either (ParseError (Token s) e) a)
+parseWithState' :: (
+  Stream s 
+#if !MIN_VERSION_megaparsec(6,0,0)
+  ,ErrorComponent e
+#endif
+  ) => st -> StateT st (ParsecT e s Identity) a -> s -> (Either (ParseError (Token s) e) a)
 parseWithState' ctx p s = runParser (evalStateT p ctx) "" s
 
 fromparse :: (Show t, Show e) => Either (ParseError t e) a -> a
@@ -61,7 +70,7 @@
 nonspace :: TextParser m Char
 nonspace = satisfy (not . isSpace)
 
-spacenonewline :: (Stream s, Char ~ Token s) => ParsecT Dec s m Char
+spacenonewline :: (Stream s, Char ~ Token s) => ParsecT MPErr s m Char
 spacenonewline = satisfy (`elem` " \v\f\t")
 
 restofline :: TextParser m String
diff --git a/Hledger/Utils/String.hs b/Hledger/Utils/String.hs
--- a/Hledger/Utils/String.hs
+++ b/Hledger/Utils/String.hs
@@ -49,7 +49,7 @@
 
 import Data.Char
 import Data.List
-import Text.Megaparsec
+import Text.Megaparsec.Compat
 import Text.Printf (printf)
 
 import Hledger.Utils.Parse
diff --git a/Text/Megaparsec/Compat.hs b/Text/Megaparsec/Compat.hs
new file mode 100644
--- /dev/null
+++ b/Text/Megaparsec/Compat.hs
@@ -0,0 +1,73 @@
+-- | Paper over some differences between megaparsec 5 and 6,
+-- making it possible to write code that supports both.
+
+{-# LANGUAGE CPP, FlexibleContexts #-}
+
+module Text.Megaparsec.Compat (
+   module Text.Megaparsec
+#if MIN_VERSION_megaparsec(6,0,0)
+  ,module Text.Megaparsec.Char
+#endif
+  ,MPErr
+  ,mptext
+  ,mpMkPos
+  ,mpUnPos
+  ,mpMkParseError
+  )
+where
+
+import qualified Data.Set as S
+import Data.Text
+import Text.Megaparsec
+
+#if MIN_VERSION_megaparsec(6,0,0)
+
+import Text.Megaparsec.Char
+import Data.List.NonEmpty (fromList)
+import Data.Void (Void)
+
+-- | A basic parse error type.
+type MPErr = Void
+
+-- | Make a simple parse error.
+mpMkParseError :: FilePath -> String -> ParseError Char String
+mpMkParseError f s = FancyError (fromList [initialPos f]) (S.singleton $ ErrorFail s)
+
+-- | Make a Pos. With a negative argument, throws InvalidPosException (megaparsec >= 6)
+-- or calls error (megaparsec < 6).
+mpMkPos :: Int -> Pos
+mpMkPos = mkPos 
+
+-- | Unmake a Pos.
+mpUnPos :: Pos -> Int
+mpUnPos = unPos
+
+-- | Parse and return some Text.  
+mptext :: MonadParsec e Text m => Tokens Text -> m (Tokens Text) 
+mptext = string
+
+#else
+
+import Text.Megaparsec.Prim (MonadParsec)
+
+-- | A basic parse error type.
+type MPErr = Dec
+
+-- | Make a simple parse error.
+mpMkParseError :: FilePath -> String -> ParseError Char String
+mpMkParseError f s = (mempty :: ParseError Char String){errorCustom = S.singleton $ f ++ ": " ++ s}
+
+-- | Make a Pos. With a negative argument, throws InvalidPosException (megaparsec >= 6)
+-- or calls error (megaparsec < 6).
+mpMkPos :: Int -> Pos
+mpMkPos = unsafePos . fromIntegral 
+
+-- | Unmake a Pos.
+mpUnPos :: Pos -> Int
+mpUnPos = fromIntegral . unPos 
+
+-- | Parse and return some Text.  
+mptext :: MonadParsec e Text m => Text -> m Text
+mptext = fmap pack . string . unpack
+
+#endif
diff --git a/doc/hledger_csv.5 b/doc/hledger_csv.5
--- a/doc/hledger_csv.5
+++ b/doc/hledger_csv.5
@@ -1,5 +1,5 @@
 
-.TH "hledger_csv" "5" "June 2017" "hledger 1.3" "hledger User Manuals"
+.TH "hledger_csv" "5" "August 2017" "hledger 1.3.1" "hledger User Manuals"
 
 
 
diff --git a/doc/hledger_csv.5.info b/doc/hledger_csv.5.info
--- a/doc/hledger_csv.5.info
+++ b/doc/hledger_csv.5.info
@@ -3,8 +3,8 @@
 
 File: hledger_csv.5.info,  Node: Top,  Next: CSV RULES,  Up: (dir)
 
-hledger_csv(5) hledger 1.3
-**************************
+hledger_csv(5) hledger 1.3.1
+****************************
 
 hledger can read CSV files, converting each CSV record into a journal
 entry (transaction), if you provide some conversion hints in a "rules
@@ -201,21 +201,21 @@
 
 Tag Table:
 Node: Top74
-Node: CSV RULES810
-Ref: #csv-rules920
-Node: skip1163
-Ref: #skip1259
-Node: date-format1431
-Ref: #date-format1560
-Node: field list2066
-Ref: #field-list2205
-Node: field assignment2910
-Ref: #field-assignment3067
-Node: conditional block3571
-Ref: #conditional-block3727
-Node: include4623
-Ref: #include4734
-Node: CSV TIPS4965
-Ref: #csv-tips5061
+Node: CSV RULES814
+Ref: #csv-rules924
+Node: skip1167
+Ref: #skip1263
+Node: date-format1435
+Ref: #date-format1564
+Node: field list2070
+Ref: #field-list2209
+Node: field assignment2914
+Ref: #field-assignment3071
+Node: conditional block3575
+Ref: #conditional-block3731
+Node: include4627
+Ref: #include4738
+Node: CSV TIPS4969
+Ref: #csv-tips5065
 
 End Tag Table
diff --git a/doc/hledger_csv.5.txt b/doc/hledger_csv.5.txt
--- a/doc/hledger_csv.5.txt
+++ b/doc/hledger_csv.5.txt
@@ -171,4 +171,4 @@
 
 
 
-hledger 1.3                        June 2017                    hledger_csv(5)
+hledger 1.3.1                     August 2017                   hledger_csv(5)
diff --git a/doc/hledger_journal.5 b/doc/hledger_journal.5
--- a/doc/hledger_journal.5
+++ b/doc/hledger_journal.5
@@ -1,6 +1,6 @@
 .\"t
 
-.TH "hledger_journal" "5" "June 2017" "hledger 1.3" "hledger User Manuals"
+.TH "hledger_journal" "5" "August 2017" "hledger 1.3.1" "hledger User Manuals"
 
 
 
diff --git a/doc/hledger_journal.5.info b/doc/hledger_journal.5.info
--- a/doc/hledger_journal.5.info
+++ b/doc/hledger_journal.5.info
@@ -4,8 +4,8 @@
 
 File: hledger_journal.5.info,  Node: Top,  Next: FILE FORMAT,  Up: (dir)
 
-hledger_journal(5) hledger 1.3
-******************************
+hledger_journal(5) hledger 1.3.1
+********************************
 
 hledger's usual data source is a plain text file containing journal
 entries in hledger journal format.  This file represents a standard
@@ -1047,83 +1047,83 @@
 
 Tag Table:
 Node: Top78
-Node: FILE FORMAT2292
-Ref: #file-format2418
-Node: Transactions2625
-Ref: #transactions2748
-Node: Postings3313
-Ref: #postings3442
-Node: Dates4437
-Ref: #dates4554
-Node: Simple dates4619
-Ref: #simple-dates4747
-Node: Secondary dates5113
-Ref: #secondary-dates5269
-Node: Posting dates6832
-Ref: #posting-dates6963
-Node: Status8337
-Ref: #status8461
-Node: Account names10175
-Ref: #account-names10315
-Node: Amounts10802
-Ref: #amounts10940
-Node: Virtual Postings13041
-Ref: #virtual-postings13202
-Node: Balance Assertions14422
-Ref: #balance-assertions14599
-Node: Assertions and ordering15495
-Ref: #assertions-and-ordering15683
-Node: Assertions and included files16383
-Ref: #assertions-and-included-files16626
-Node: Assertions and multiple -f options16959
-Ref: #assertions-and-multiple--f-options17215
-Node: Assertions and commodities17347
-Ref: #assertions-and-commodities17584
-Node: Assertions and subaccounts18280
-Ref: #assertions-and-subaccounts18514
-Node: Assertions and virtual postings19035
-Ref: #assertions-and-virtual-postings19244
-Node: Balance Assignments19386
-Ref: #balance-assignments19555
-Node: Prices20674
-Ref: #prices20809
-Node: Transaction prices20860
-Ref: #transaction-prices21007
-Node: Market prices23163
-Ref: #market-prices23300
-Node: Comments24260
-Ref: #comments24384
-Node: Tags25497
-Ref: #tags25617
-Node: Implicit tags27046
-Ref: #implicit-tags27154
-Node: Directives27671
-Ref: #directives27786
-Node: Account aliases27979
-Ref: #account-aliases28125
-Node: Basic aliases28729
-Ref: #basic-aliases28874
-Node: Regex aliases29564
-Ref: #regex-aliases29734
-Node: Multiple aliases30449
-Ref: #multiple-aliases30623
-Node: end aliases31121
-Ref: #end-aliases31263
-Node: account directive31364
-Ref: #account-directive31546
-Node: apply account directive31842
-Ref: #apply-account-directive32040
-Node: Multi-line comments32699
-Ref: #multi-line-comments32891
-Node: commodity directive33019
-Ref: #commodity-directive33205
-Node: Default commodity34077
-Ref: #default-commodity34252
-Node: Default year34789
-Ref: #default-year34956
-Node: Including other files35379
-Ref: #including-other-files35538
-Node: EDITOR SUPPORT35935
-Ref: #editor-support36055
+Node: FILE FORMAT2296
+Ref: #file-format2422
+Node: Transactions2629
+Ref: #transactions2752
+Node: Postings3317
+Ref: #postings3446
+Node: Dates4441
+Ref: #dates4558
+Node: Simple dates4623
+Ref: #simple-dates4751
+Node: Secondary dates5117
+Ref: #secondary-dates5273
+Node: Posting dates6836
+Ref: #posting-dates6967
+Node: Status8341
+Ref: #status8465
+Node: Account names10179
+Ref: #account-names10319
+Node: Amounts10806
+Ref: #amounts10944
+Node: Virtual Postings13045
+Ref: #virtual-postings13206
+Node: Balance Assertions14426
+Ref: #balance-assertions14603
+Node: Assertions and ordering15499
+Ref: #assertions-and-ordering15687
+Node: Assertions and included files16387
+Ref: #assertions-and-included-files16630
+Node: Assertions and multiple -f options16963
+Ref: #assertions-and-multiple--f-options17219
+Node: Assertions and commodities17351
+Ref: #assertions-and-commodities17588
+Node: Assertions and subaccounts18284
+Ref: #assertions-and-subaccounts18518
+Node: Assertions and virtual postings19039
+Ref: #assertions-and-virtual-postings19248
+Node: Balance Assignments19390
+Ref: #balance-assignments19559
+Node: Prices20678
+Ref: #prices20813
+Node: Transaction prices20864
+Ref: #transaction-prices21011
+Node: Market prices23167
+Ref: #market-prices23304
+Node: Comments24264
+Ref: #comments24388
+Node: Tags25501
+Ref: #tags25621
+Node: Implicit tags27050
+Ref: #implicit-tags27158
+Node: Directives27675
+Ref: #directives27790
+Node: Account aliases27983
+Ref: #account-aliases28129
+Node: Basic aliases28733
+Ref: #basic-aliases28878
+Node: Regex aliases29568
+Ref: #regex-aliases29738
+Node: Multiple aliases30453
+Ref: #multiple-aliases30627
+Node: end aliases31125
+Ref: #end-aliases31267
+Node: account directive31368
+Ref: #account-directive31550
+Node: apply account directive31846
+Ref: #apply-account-directive32044
+Node: Multi-line comments32703
+Ref: #multi-line-comments32895
+Node: commodity directive33023
+Ref: #commodity-directive33209
+Node: Default commodity34081
+Ref: #default-commodity34256
+Node: Default year34793
+Ref: #default-year34960
+Node: Including other files35383
+Ref: #including-other-files35542
+Node: EDITOR SUPPORT35939
+Ref: #editor-support36059
 
 End Tag Table
diff --git a/doc/hledger_journal.5.txt b/doc/hledger_journal.5.txt
--- a/doc/hledger_journal.5.txt
+++ b/doc/hledger_journal.5.txt
@@ -835,4 +835,4 @@
 
 
 
-hledger 1.3                        June 2017                hledger_journal(5)
+hledger 1.3.1                     August 2017               hledger_journal(5)
diff --git a/doc/hledger_timeclock.5 b/doc/hledger_timeclock.5
--- a/doc/hledger_timeclock.5
+++ b/doc/hledger_timeclock.5
@@ -1,5 +1,5 @@
 
-.TH "hledger_timeclock" "5" "June 2017" "hledger 1.3" "hledger User Manuals"
+.TH "hledger_timeclock" "5" "August 2017" "hledger 1.3.1" "hledger User Manuals"
 
 
 
diff --git a/doc/hledger_timeclock.5.info b/doc/hledger_timeclock.5.info
--- a/doc/hledger_timeclock.5.info
+++ b/doc/hledger_timeclock.5.info
@@ -4,8 +4,8 @@
 
 File: hledger_timeclock.5.info,  Node: Top,  Up: (dir)
 
-hledger_timeclock(5) hledger 1.3
-********************************
+hledger_timeclock(5) hledger 1.3.1
+**********************************
 
 hledger can read timeclock files.  As with Ledger, these are (a subset
 of) timeclock.el's format, containing clock-in and clock-out entries as
diff --git a/doc/hledger_timeclock.5.txt b/doc/hledger_timeclock.5.txt
--- a/doc/hledger_timeclock.5.txt
+++ b/doc/hledger_timeclock.5.txt
@@ -79,4 +79,4 @@
 
 
 
-hledger 1.3                        June 2017              hledger_timeclock(5)
+hledger 1.3.1                     August 2017             hledger_timeclock(5)
diff --git a/doc/hledger_timedot.5 b/doc/hledger_timedot.5
--- a/doc/hledger_timedot.5
+++ b/doc/hledger_timedot.5
@@ -1,5 +1,5 @@
 
-.TH "hledger_timedot" "5" "June 2017" "hledger 1.3" "hledger User Manuals"
+.TH "hledger_timedot" "5" "August 2017" "hledger 1.3.1" "hledger User Manuals"
 
 
 
diff --git a/doc/hledger_timedot.5.info b/doc/hledger_timedot.5.info
--- a/doc/hledger_timedot.5.info
+++ b/doc/hledger_timedot.5.info
@@ -4,8 +4,8 @@
 
 File: hledger_timedot.5.info,  Node: Top,  Next: FILE FORMAT,  Up: (dir)
 
-hledger_timedot(5) hledger 1.3
-******************************
+hledger_timedot(5) hledger 1.3.1
+********************************
 
 Timedot is a plain text format for logging dated, categorised quantities
 (eg time), supported by hledger.  It is convenient for approximate and
@@ -106,7 +106,7 @@
 
 Tag Table:
 Node: Top78
-Node: FILE FORMAT882
-Ref: #file-format985
+Node: FILE FORMAT886
+Ref: #file-format989
 
 End Tag Table
diff --git a/doc/hledger_timedot.5.txt b/doc/hledger_timedot.5.txt
--- a/doc/hledger_timedot.5.txt
+++ b/doc/hledger_timedot.5.txt
@@ -120,4 +120,4 @@
 
 
 
-hledger 1.3                        June 2017                hledger_timedot(5)
+hledger 1.3.1                     August 2017               hledger_timedot(5)
diff --git a/hledger-lib.cabal b/hledger-lib.cabal
--- a/hledger-lib.cabal
+++ b/hledger-lib.cabal
@@ -1,9 +1,9 @@
--- This file has been generated from package.yaml by hpack version 0.17.0.
+-- This file has been generated from package.yaml by hpack version 0.17.1.
 --
 -- see: https://github.com/sol/hpack
 
 name:           hledger-lib
-version:        1.3
+version:        1.3.1
 synopsis:       Core data types, parsers and functionality for the hledger accounting tools
 description:    This is a reusable library containing hledger's core functionality.
                 .
@@ -72,7 +72,7 @@
     , directory
     , filepath
     , hashtables >= 1.2
-    , megaparsec >=5.0 && < 5.4
+    , megaparsec >=5.0 && < 6.2
     , mtl
     , mtl-compat
     , old-time
@@ -141,6 +141,7 @@
       Hledger.Utils.Text
       Hledger.Utils.Tree
       Hledger.Utils.UTF8IOCompat
+      Text.Megaparsec.Compat
   other-modules:
       Paths_hledger_lib
   default-language: Haskell2010
@@ -168,7 +169,7 @@
     , directory
     , filepath
     , hashtables >= 1.2
-    , megaparsec >=5.0 && < 5.4
+    , megaparsec >=5.0 && < 6.2
     , mtl
     , mtl-compat
     , old-time
@@ -186,6 +187,13 @@
   if impl(ghc <7.6)
     build-depends:
         ghc-prim
+  if flag(oldtime)
+    build-depends:
+        time <1.5
+      , old-locale
+  else
+    build-depends:
+        time >=1.5
   other-modules:
       Hledger
       Hledger.Data
@@ -230,6 +238,7 @@
       Hledger.Utils.Text
       Hledger.Utils.Tree
       Hledger.Utils.UTF8IOCompat
+      Text.Megaparsec.Compat
   default-language: Haskell2010
 
 test-suite hunittests
@@ -255,7 +264,7 @@
     , directory
     , filepath
     , hashtables >= 1.2
-    , megaparsec >=5.0 && < 5.4
+    , megaparsec >=5.0 && < 6.2
     , mtl
     , mtl-compat
     , old-time
@@ -326,4 +335,5 @@
       Hledger.Utils.Text
       Hledger.Utils.Tree
       Hledger.Utils.UTF8IOCompat
+      Text.Megaparsec.Compat
   default-language: Haskell2010
