从 [Char] 中提取 YYYYMMDD 并创建日期时间值



我有包含日期的字符串,格式为"YYYYMMDD"。这是理所当然的,没有出错的可能性。

我想从他们创建日期时间。

我设法有一些工作,但对于这些小事情来说似乎很复杂:

-- Only works in base 10 , for positive values
stringToInt :: String -> Int
stringToInt [] = 0
stringToInt (x:xs) = (digitToInt x * 10^length xs ) + (stringToInt xs) 
-- Expecting format = "YYYYMMDD"
stringToDateTime :: String -> DateTime
stringToDateTime s = DateTime year month day 0 0 0
  where year = stringToInt $ take 4 s 
        month = stringToInt $ take(6-4) . drop 4 $ s
        day = stringToInt $ take(8-6) . drop 6 $ s
date1 = stringToDateTime "20180409"

我尝试了parseDate函数,但无法让它工作,因为我找不到预期的字符串格式(这里是Data.Dates文档:我们如何知道预期的格式?

这就是为什么我最终做了自己的函数来从我的字符串创建日期时间,这样做我必须创建一个函数来从 [Char] 转换 Int ,因为我找不到已经存在的函数。

使用 dates 包,我认为您需要parseDateFormat

> import Data.Dates
> import Data.Dates.Formats (parseDateFormat)
> parseDateFormat "YYYYMMDD" "20180409"
Right 9 April 2018, 0:0:0

如果确定字符串具有正确的日期格式,则可以使用 extrafromRight'Right中提取结果:

> import Data.Either.Extra
> fromRight' $ parseDateFormat "YYYYMMDD" "20180409"
9 April 2018, 0:0:0

为了"正确"地做这些事情,你应该阅读解析器组合器库。使用megaparsec库的(非常矫枉过正(解决方案:

import Text.Megaparsec
import Text.Megaparsec.Char
import Control.Monad
type Parser = Parsec String String
decimalNInt :: Int -> Parser Int
decimalNInt nDigits = read <$> replicateM nDigits digitChar
data DateTime = DateTime Int Int Int Int Int Int deriving (Show)
dateYYYYMMDD :: Parser DateTime
dateYYYYMMDD = DateTime <$>
       decimalNInt 4 <*> decimalNInt 2 <*> decimalNInt 2
   <*> pure 0 <*> pure 0 <*> pure 0
> runParser dateYYYYMMDD "" "20180409"
    Right (DateTime 2018 4 9 0 0 0)
> runParser dateYYYYMMDD "" "2018009"
    Left (TrivialError (SourcePos {sourceName = "", sourceLine = Pos 1, sourceColumn = Pos 8} :| []) (Just EndOfInput) (fromList [Label ('d' :| "igit")]))
> runParser dateYYYYMMDD "" "abcdefgh"
    Left (TrivialError (SourcePos {sourceName = "", sourceLine = Pos 1, sourceColumn = Pos 1} :| []) (Just (Tokens ('a' :| ""))) (fromList [Label ('d' :| "igit")]))

在也许更好理解的一元表示法中,解析器如下所示:

dateYYYYMMDD = do
    year <- decimalNInt 4
    month <- decimalNInt 2
    day <- decimalNInt 2
    return $ DateTime year month day 0 0 0

切片我认为你必须自己做,但要从字符串中读取整数,你应该使用函数 read ,如下所示:

read "1234" :: Int

要使此函数适用于任何数据类型,它必须是类 Read 的实例。不幸的是,查看文档,日期时间不是。

使用 parseTimeM ,来自唯一真正仔细处理日期和时间的 Haskell 包,时间。这是一个非常全面的图书馆;它唯一真正缺乏的是自然语言处理和生产。

Data.Time> parseTimeM False defaultTimeLocale "%0Y%m%d" "20180409" :: Maybe Day
Just 2018-04-09

上面链接的文档和formatTime文档提供了可用格式说明符的完整列表。

如果您确实需要DateTime并且没有替代品可以,则可以使用toGregorianDay中提取年,月和日。

最新更新