diff options
author | Rutger Broekhoff | 2025-03-22 14:52:35 +0100 |
---|---|---|
committer | Rutger Broekhoff | 2025-03-22 14:52:35 +0100 |
commit | 5493329b2eed7e151f4a323c108caad2253b08bb (patch) | |
tree | a8fd1a58e0ba77d06e75222034def5eb49043bb6 /app/Import/Ing/Shared.hs | |
parent | e40e290ef216656d304f4f3095dbef223e94191d (diff) | |
download | rdcapsis-5493329b2eed7e151f4a323c108caad2253b08bb.tar.gz rdcapsis-5493329b2eed7e151f4a323c108caad2253b08bb.zip |
Refactor parser for current account statement
Diffstat (limited to 'app/Import/Ing/Shared.hs')
-rw-r--r-- | app/Import/Ing/Shared.hs | 49 |
1 files changed, 23 insertions, 26 deletions
diff --git a/app/Import/Ing/Shared.hs b/app/Import/Ing/Shared.hs index c70f225..b5d1703 100644 --- a/app/Import/Ing/Shared.hs +++ b/app/Import/Ing/Shared.hs | |||
@@ -13,35 +13,32 @@ import Data.Time.Zones (TZ, localTimeToUTCTZ) | |||
13 | 13 | ||
14 | data DebitCredit = Debit | Credit deriving (Show) | 14 | data DebitCredit = Debit | Credit deriving (Show) |
15 | 15 | ||
16 | readDecimal :: T.Text -> Either String Decimal | ||
17 | readDecimal = AP.parseOnly $ do | ||
18 | decPart <- AP.decimal | ||
19 | _ <- AP.char ',' | ||
20 | f1 <- AP.digit | ||
21 | f2 <- AP.digit | ||
22 | AP.endOfInput | ||
23 | let fracPart = fromIntegral $ digitToInt f1 * 10 + digitToInt f2 | ||
24 | return $ normalizeDecimal (Decimal 2 (decPart * 100 + fracPart)) | ||
25 | |||
26 | scsvOptions :: C.DecodeOptions | 16 | scsvOptions :: C.DecodeOptions |
27 | scsvOptions = C.defaultDecodeOptions {C.decDelimiter = fromIntegral (ord ';')} | 17 | scsvOptions = C.defaultDecodeOptions {C.decDelimiter = fromIntegral (ord ';')} |
28 | 18 | ||
29 | eitherToCP :: Either String a -> C.Parser a | ||
30 | eitherToCP = either fail return | ||
31 | |||
32 | decimalCP :: T.Text -> C.Parser Decimal | ||
33 | decimalCP = eitherToCP . readDecimal | ||
34 | |||
35 | dateCP :: String -> T.Text -> C.Parser Day | ||
36 | dateCP fmt = parseTimeM False defaultTimeLocale fmt . T.unpack | ||
37 | |||
38 | maybeCP :: (T.Text -> C.Parser a) -> T.Text -> C.Parser (Maybe a) | 19 | maybeCP :: (T.Text -> C.Parser a) -> T.Text -> C.Parser (Maybe a) |
39 | maybeCP p t = if T.null t then return Nothing else Just <$> p t | 20 | maybeCP p t = if T.null t then return Nothing else Just <$> p t |
40 | 21 | ||
41 | ibanCP :: T.Text -> C.Parser Iban | 22 | parseDecimalM :: (MonadFail m) => T.Text -> m Decimal |
42 | ibanCP = eitherToCP . mkIban | 23 | parseDecimalM = |
43 | 24 | either fail return | |
44 | timestampCP :: String -> TZ -> T.Text -> C.Parser UTCTime | 25 | . AP.parseOnly |
45 | timestampCP fmt amsTz t = do | 26 | ( do |
46 | localTime <- parseTimeM False defaultTimeLocale fmt (T.unpack t) | 27 | decPart <- AP.decimal |
47 | return $ localTimeToUTCTZ amsTz localTime | 28 | _ <- AP.char ',' |
29 | f1 <- AP.digit | ||
30 | f2 <- AP.digit | ||
31 | AP.endOfInput | ||
32 | let fracPart = fromIntegral $ digitToInt f1 * 10 + digitToInt f2 | ||
33 | return $ normalizeDecimal (Decimal 2 (decPart * 100 + fracPart)) | ||
34 | ) | ||
35 | |||
36 | parseIbanM :: (MonadFail m) => T.Text -> m Iban | ||
37 | parseIbanM = either fail return . mkIban | ||
38 | |||
39 | parseDateM :: (MonadFail m) => String -> T.Text -> m Day | ||
40 | parseDateM fmt = parseTimeM False defaultTimeLocale fmt . T.unpack | ||
41 | |||
42 | parseTimestampM :: (MonadFail m) => String -> TZ -> T.Text -> m UTCTime | ||
43 | parseTimestampM fmt amsTz t = do | ||
44 | localTimeToUTCTZ amsTz <$> parseTimeM False defaultTimeLocale fmt (T.unpack t) | ||