-- | -- Module : Data.Hourglass.Calendar -- License : BSD-style -- Maintainer : Vincent Hanquez -- Stability : experimental -- Portability : unknown -- -- Misc calendar functions -- module Data.Hourglass.Calendar ( isLeapYear , getWeekDay , getDayOfTheYear , daysInMonth , dateToUnixEpoch , dateFromUnixEpoch , todToSeconds , dateTimeToUnixEpoch , dateTimeFromUnixEpoch , dateTimeFromUnixEpochP ) where import Data.Hourglass.Types import Data.Hourglass.Internal -- | Return if this year is a leap year (366 days) -- or not (365 days in a year) isLeapYear :: Int -> Bool isLeapYear year | year `mod` 4 /= 0 = False | year `mod` 100 /= 0 = True | year `mod` 400 == 0 = True | otherwise = False -- | Return the day of the week a specific date fall in getWeekDay :: Date -> WeekDay getWeekDay date = toEnum (d `mod` 7) where d = daysOfDate date -- | return the number of days until the beggining of the month specified for a specific year. daysUntilMonth :: Int -> Month -> Int daysUntilMonth y m | isLeapYear y = leapYears !! fromEnum m | otherwise = normalYears !! fromEnum m where normalYears = [ 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 ] leapYears = [ 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 ] -- | Return the number of days in a month. daysInMonth :: Int -> Month -> Int daysInMonth y m | m == February && isLeapYear y = 29 | otherwise = days !! fromEnum m where days = [31,28,31,30,31,30,31,31,30,31,30,31] -- | return the day of the year where Jan 1 is 0 -- -- between 0 and 364. 365 for leap years getDayOfTheYear :: Date -> Int getDayOfTheYear (Date y m d) = daysUntilMonth y m + d -- | return the number of days before Jan 1st of the year daysBeforeYear :: Int -> Int daysBeforeYear year = y * 365 + (y `div` 4) - (y `div` 100) + (y `div` 400) where y = year - 1 -- | Return the number of day since 1 january 1 daysOfDate :: Date -> Int daysOfDate (Date y m d) = daysBeforeYear y + daysUntilMonth y m + d -- | Return the number of seconds to unix epoch of a date considering hour=0,minute=0,second=0 dateToUnixEpoch :: Date -> Elapsed dateToUnixEpoch date = Elapsed $ Seconds (fromIntegral (daysOfDate date - epochDays) * secondsPerDay) where epochDays = 719163 secondsPerDay = 86400 -- julian day is 24h -- | Return the Date associated with the unix epoch dateFromUnixEpoch :: Elapsed -> Date dateFromUnixEpoch e = dtDate $ dateTimeFromUnixEpoch e -- | Return the number of seconds from a time structure todToSeconds :: TimeOfDay -> Seconds todToSeconds (TimeOfDay h m s _) = toSeconds h + toSeconds m + s -- | Return the number of seconds to unix epoch of a date time dateTimeToUnixEpoch :: DateTime -> Elapsed dateTimeToUnixEpoch (DateTime d t) = dateToUnixEpoch d + Elapsed (todToSeconds t)