PO8

haskell-date-stuff

PO8
Aug 22nd, 2015
177
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. -- Copyright (c) 2015 Adrian "Boom" Nwk
  2. -- Extensively revised by Bart Massey
  3. -- Day-of-week computations
  4.  
  5. import Text.Printf
  6.  
  7. data Months = Jan | Feb | Mar | Apr | May | Jun
  8.             | Jul | Aug | Sep | Oct | Nov | Dec
  9.               deriving (Show, Eq, Enum, Bounded)
  10.  
  11. data Days = Mon | Tue | Wed | Thu | Fri | Sat | Sun
  12.             deriving (Show, Eq, Enum, Bounded)
  13.  
  14. data Date = Date {  dayOfWeek :: Days
  15.                   , dayNumber :: Int
  16.                   , month     :: Months
  17.                   , year      :: Int }
  18.             deriving Eq
  19.  
  20. instance Show Date where
  21.     show d = printf "%s %d/%s/%d" (show (dayOfWeek d))
  22.              (dayNumber d) (show (month d)) (year d)
  23.  
  24. circSucc :: (Enum a, Bounded a, Eq a) => a -> a
  25. circSucc e
  26.          | e == (maxBound `asTypeOf` e) = minBound `asTypeOf` e
  27.          | otherwise = succ e
  28.  
  29. dateSucc :: Date -> Date
  30. dateSucc (Date d dn m y) = Date (circSucc d) (succ dn) m y
  31.  
  32. daysFromDate :: Date -> [Date]
  33. daysFromDate now =
  34.     normalNow : daysFromDate (dateSucc normalNow)
  35.     where
  36.       normalNow = dateNormalize now
  37.  
  38. dateToDate :: Date -> Date -> [Date]
  39. dateToDate now later =
  40.     takeWhile (\d -> d /= later) $ daysFromDate now
  41.  
  42. divides :: Integral a => a -> a -> Bool
  43. divides d n | n < 0 = divides d (-n)
  44. divides d n = n `mod` d == 0
  45.  
  46. -- If the date is not normalized, it means that it is the end of the month
  47. -- If the date is normalized, it means that the date is still within the month
  48.  
  49. dateNormalized :: Date -> Bool
  50. dateNormalized (Date _ dn m0 y0) =
  51.     (monthsWith30 m0 && dn <= 30) ||
  52.     (monthsWith31 m0 && dn <= 31) ||
  53.     (m0 == Feb && dn <= febDays y0)
  54.     where
  55.       monthsWith31 m = m `elem` [Jan, Mar, May, Jul, Aug, Oct, Dec]
  56.       monthsWith30 m = m `elem` [Apr, Jun, Sep, Nov]
  57.       febDays y
  58.           | 400 `divides` y  = 29
  59.           | 100 `divides` y  = 28
  60.           | 4 `divides` y  = 29
  61.           | otherwise = 28
  62.  
  63. dateNormalize :: Date -> Date
  64. dateNormalize now@(Date d _ m y)
  65.   | dateNormalized now =
  66.       now                     -- Normal day
  67.   | m == Dec =
  68.       Date d 1 Jan (succ y)   -- End of Year
  69.   | otherwise =
  70.       Date d 1 (succ m) y     -- End of Month
  71.  
  72. ------------------------------------- New Edits
  73.  
  74. main :: IO ()
  75. main = putStr $ unlines $ map show $
  76.        [x | x <- days, dayOfWeek x `elem` [Mon, Wed, Fri]]
  77.        where
  78.          days  = dateToDate (Date Mon 2 Aug 2010) (Date Sat 22 Aug 2015)
Advertisement
Add Comment
Please, Sign In to add comment