Haskell date parsing and formatting

后端 未结 4 1856
悲&欢浪女
悲&欢浪女 2020-12-30 23:39

I\'ve been working with Haskell\'s Date.Time modules to parse a date like 12-4-1999 or 1-31-1999. I tried:

parseDay :: String -&g         


        
4条回答
  •  抹茶落季
    2020-12-31 00:00

    Here is some old code that contains two types of homemade dates, dates with just YMD, no time or timezones, etc.

    It shows how to parse strings into dates using readDec. See the parseDate function. With readDec, read the number, it doesn't matter about leading spaces(because of filter) or leading zeros,and the parse stops at the first non-digit. Then used tail (to skip the non digit) to get to the next numerical field of the date.

    It shows several ways of formatting for output, but the most flexible way is to use Text.printf. See instance Show LtDate. With printf, anything is possible!

    import Char
    import Numeric
    import Data.Time.Calendar
    import Data.Time.Clock
    import Text.Printf
    -- ================================================================
    --                        LtDate
    -- ================================================================
    type Date=(Int,Int,Int)
    data LtDate = LtDate 
      { ltYear :: Int,
        ltMonth:: Int,
        ltDay  :: Int
      } 
    instance Show LtDate 
      where show d = printf "%4d-%02d-%02d" (ltYear d) (ltMonth d) (ltDay d)
    
    toLtDate :: Date -> LtDate
    toLtDate (y,m,d)= LtDate y m d
    
    -- =============================================================
    --                         Date
    -- =============================================================
    -- | Parse a String mm/dd/yy into tuple (y,m,d)
    -- accepted formats
    --
    -- @
    -- 12\/01\/2004
    -- 12\/ 1\' 4
    -- 12-01-99
    -- @
    parseDate :: String -> Date
    parseDate s = (y,m,d)
        where [(m,rest) ] = readDec (filter (not . isSpace) s)
              [(d,rest1)] = readDec (tail rest)
              [(y, _)   ] = parseDate' rest1
    
    -- | parse the various year formats used by Quicken dates
    parseDate':: String -> [(Int,String)]
    parseDate' (y:ys) =
      let [(iy,rest)] = readDec ys
          year=case y of '\''      -> iy + 2000
                         _  ->
                           if iy < 1900 then  iy + 1900 else iy
       in [(year,rest)]
    
    -- | Note some functions sort by this format
    -- | So be careful when changing it.
    showDate::(Int, Int, Int) -> String
    showDate (y,m,d)= yy ++ '-':mm ++ '-':dd
        where dd=zpad (show d)
              mm = zpad (show m)
              yy = show y
              zpad ds@(_:ds')
               | ds'==[] = '0':ds
               | otherwise = ds
    
    
    -- | from LtDate to Date
    fromLtDate :: LtDate -> Date
    fromLtDate  lt = (ltYear lt, ltMonth lt, ltDay lt)
    

    Once you have (Y,M,D), it's easy to convert to a Haskell library type for data manipulations. Once you are done with the HS libraries, Text.printf can be used to format a date for display.

提交回复
热议问题