{-# LANGUAGE CPP #-}
{-# LANGUAGE BangPatterns #-}
{-# LANGUAGE DeriveDataTypeable #-}
#if __GLASGOW_HASKELL__ >= 710
{-# LANGUAGE PatternSynonyms #-}
{-# LANGUAGE ViewPatterns #-}
#endif
module Data.Time.Calendar.WeekDate.Compat (
Year, WeekOfYear, DayOfWeek(..), dayOfWeek,
FirstWeekType (..),
toWeekCalendar,
fromWeekCalendar,
fromWeekCalendarValid,
toWeekDate,
fromWeekDate,
#if __GLASGOW_HASKELL__ >= 710
pattern YearWeekDay,
#endif
fromWeekDateValid,
showWeekDate,
) where
import Data.Time.Orphans ()
import Data.Time.Calendar
import Data.Time.Calendar.WeekDate
#if !MIN_VERSION_time(1,9,0)
import Data.Time.Format
#endif
#if !MIN_VERSION_time(1,11,0)
import Data.Data (Data)
import Data.Typeable (Typeable)
import Data.Time.Calendar.Types
import Data.Time.Calendar.Private
import Data.Time.Calendar.OrdinalDate
#endif
import Control.DeepSeq (NFData (..))
import Data.Hashable (Hashable (..))
#if !MIN_VERSION_time(1,11,0)
data FirstWeekType
= FirstWholeWeek
| FirstMostWeek
deriving (FirstWeekType -> FirstWeekType -> Bool
(FirstWeekType -> FirstWeekType -> Bool)
-> (FirstWeekType -> FirstWeekType -> Bool) -> Eq FirstWeekType
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: FirstWeekType -> FirstWeekType -> Bool
$c/= :: FirstWeekType -> FirstWeekType -> Bool
== :: FirstWeekType -> FirstWeekType -> Bool
$c== :: FirstWeekType -> FirstWeekType -> Bool
Eq, Typeable)
firstDayOfWeekCalendar :: FirstWeekType -> DayOfWeek -> Year -> Day
firstDayOfWeekCalendar :: FirstWeekType -> DayOfWeek -> Year -> Day
firstDayOfWeekCalendar FirstWeekType
wt DayOfWeek
dow Year
year = let
jan1st :: Day
jan1st = Year -> Int -> Day
fromOrdinalDate Year
year Int
1
in case FirstWeekType
wt of
FirstWeekType
FirstWholeWeek -> DayOfWeek -> Day -> Day
firstDayOfWeekOnAfter DayOfWeek
dow Day
jan1st
FirstWeekType
FirstMostWeek -> DayOfWeek -> Day -> Day
firstDayOfWeekOnAfter DayOfWeek
dow (Day -> Day) -> Day -> Day
forall a b. (a -> b) -> a -> b
$ Year -> Day -> Day
addDays (-Year
3) Day
jan1st
toWeekCalendar ::
FirstWeekType
-> DayOfWeek
-> Day
-> (Year, WeekOfYear, DayOfWeek)
toWeekCalendar :: FirstWeekType -> DayOfWeek -> Day -> (Year, Int, DayOfWeek)
toWeekCalendar FirstWeekType
wt DayOfWeek
ws Day
d = let
dw :: DayOfWeek
dw = Day -> DayOfWeek
dayOfWeek Day
d
(Year
y0,Int
_) = Day -> (Year, Int)
toOrdinalDate Day
d
j1p :: Day
j1p = FirstWeekType -> DayOfWeek -> Year -> Day
firstDayOfWeekCalendar FirstWeekType
wt DayOfWeek
ws (Year -> Day) -> Year -> Day
forall a b. (a -> b) -> a -> b
$ Year -> Year
forall a. Enum a => a -> a
pred Year
y0
j1 :: Day
j1 = FirstWeekType -> DayOfWeek -> Year -> Day
firstDayOfWeekCalendar FirstWeekType
wt DayOfWeek
ws Year
y0
j1s :: Day
j1s = FirstWeekType -> DayOfWeek -> Year -> Day
firstDayOfWeekCalendar FirstWeekType
wt DayOfWeek
ws (Year -> Day) -> Year -> Day
forall a b. (a -> b) -> a -> b
$ Year -> Year
forall a. Enum a => a -> a
succ Year
y0
in if Day
d Day -> Day -> Bool
forall a. Ord a => a -> a -> Bool
< Day
j1
then (Year -> Year
forall a. Enum a => a -> a
pred Year
y0,Int -> Int
forall a. Enum a => a -> a
succ (Int -> Int) -> Int -> Int
forall a b. (a -> b) -> a -> b
$ Int -> Int -> Int
forall a. Integral a => a -> a -> a
div (Year -> Int
forall a. Num a => Year -> a
fromInteger (Year -> Int) -> Year -> Int
forall a b. (a -> b) -> a -> b
$ Day -> Day -> Year
diffDays Day
d Day
j1p) Int
7,DayOfWeek
dw)
else if Day
d Day -> Day -> Bool
forall a. Ord a => a -> a -> Bool
< Day
j1s then (Year
y0,Int -> Int
forall a. Enum a => a -> a
succ (Int -> Int) -> Int -> Int
forall a b. (a -> b) -> a -> b
$ Int -> Int -> Int
forall a. Integral a => a -> a -> a
div (Year -> Int
forall a. Num a => Year -> a
fromInteger (Year -> Int) -> Year -> Int
forall a b. (a -> b) -> a -> b
$ Day -> Day -> Year
diffDays Day
d Day
j1) Int
7,DayOfWeek
dw)
else (Year -> Year
forall a. Enum a => a -> a
succ Year
y0,Int -> Int
forall a. Enum a => a -> a
succ (Int -> Int) -> Int -> Int
forall a b. (a -> b) -> a -> b
$ Int -> Int -> Int
forall a. Integral a => a -> a -> a
div (Year -> Int
forall a. Num a => Year -> a
fromInteger (Year -> Int) -> Year -> Int
forall a b. (a -> b) -> a -> b
$ Day -> Day -> Year
diffDays Day
d Day
j1s) Int
7,DayOfWeek
dw)
fromWeekCalendar ::
FirstWeekType
-> DayOfWeek
-> Year -> WeekOfYear -> DayOfWeek -> Day
fromWeekCalendar :: FirstWeekType -> DayOfWeek -> Year -> Int -> DayOfWeek -> Day
fromWeekCalendar FirstWeekType
wt DayOfWeek
ws Year
y Int
wy DayOfWeek
dw = let
d1 :: Day
d1 :: Day
d1 = FirstWeekType -> DayOfWeek -> Year -> Day
firstDayOfWeekCalendar FirstWeekType
wt DayOfWeek
ws Year
y
wy' :: Int
wy' = Int -> Int -> Int -> Int
forall t. Ord t => t -> t -> t -> t
clip Int
1 Int
53 Int
wy
getday :: WeekOfYear -> Day
getday :: Int -> Day
getday Int
wy'' = Year -> Day -> Day
addDays (Int -> Year
forall a. Integral a => a -> Year
toInteger (Int -> Year) -> Int -> Year
forall a b. (a -> b) -> a -> b
$ (Int -> Int
forall a. Enum a => a -> a
pred Int
wy'' Int -> Int -> Int
forall a. Num a => a -> a -> a
* Int
7) Int -> Int -> Int
forall a. Num a => a -> a -> a
+ (DayOfWeek -> DayOfWeek -> Int
dayOfWeekDiff DayOfWeek
dw DayOfWeek
ws)) Day
d1
d1s :: Day
d1s = FirstWeekType -> DayOfWeek -> Year -> Day
firstDayOfWeekCalendar FirstWeekType
wt DayOfWeek
ws (Year -> Day) -> Year -> Day
forall a b. (a -> b) -> a -> b
$ Year -> Year
forall a. Enum a => a -> a
succ Year
y
day :: Day
day = Int -> Day
getday Int
wy'
in if Int
wy' Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
53 then if Day
day Day -> Day -> Bool
forall a. Ord a => a -> a -> Bool
>= Day
d1s then Int -> Day
getday Int
52 else Day
day else Day
day
fromWeekCalendarValid ::
FirstWeekType
-> DayOfWeek
-> Year -> WeekOfYear -> DayOfWeek -> Maybe Day
fromWeekCalendarValid :: FirstWeekType -> DayOfWeek -> Year -> Int -> DayOfWeek -> Maybe Day
fromWeekCalendarValid FirstWeekType
wt DayOfWeek
ws Year
y Int
wy DayOfWeek
dw = let
d :: Day
d = FirstWeekType -> DayOfWeek -> Year -> Int -> DayOfWeek -> Day
fromWeekCalendar FirstWeekType
wt DayOfWeek
ws Year
y Int
wy DayOfWeek
dw
in if FirstWeekType -> DayOfWeek -> Day -> (Year, Int, DayOfWeek)
toWeekCalendar FirstWeekType
wt DayOfWeek
ws Day
d (Year, Int, DayOfWeek) -> (Year, Int, DayOfWeek) -> Bool
forall a. Eq a => a -> a -> Bool
== (Year
y,Int
wy,DayOfWeek
dw) then Day -> Maybe Day
forall a. a -> Maybe a
Just Day
d else Maybe Day
forall a. Maybe a
Nothing
#if __GLASGOW_HASKELL__ >= 710
pattern YearWeekDay :: Year -> WeekOfYear -> DayOfWeek -> Day
pattern $bYearWeekDay :: Year -> Int -> DayOfWeek -> Day
$mYearWeekDay :: forall r.
Day -> (Year -> Int -> DayOfWeek -> r) -> (Void# -> r) -> r
YearWeekDay y wy dw <- (toWeekDate -> (y,wy,toEnum -> dw)) where
YearWeekDay Year
y Int
wy DayOfWeek
dw = Year -> Int -> Int -> Day
fromWeekDate Year
y Int
wy (DayOfWeek -> Int
forall a. Enum a => a -> Int
fromEnum DayOfWeek
dw)
#if __GLASGOW_HASKELL__ >= 802
{-# COMPLETE YearWeekDay #-}
#endif
#endif
#endif
#if !MIN_VERSION_time(1,9,0)
data DayOfWeek
= Monday
| Tuesday
| Wednesday
| Thursday
| Friday
| Saturday
| Sunday
deriving (Eq, Ord, Show, Read, Typeable, Data)
instance NFData DayOfWeek where
rnf !_ = ()
instance Hashable DayOfWeek where
hashWithSalt salt = hashWithSalt salt . fromEnum
instance Enum DayOfWeek where
toEnum i =
case mod i 7 of
0 -> Sunday
1 -> Monday
2 -> Tuesday
3 -> Wednesday
4 -> Thursday
5 -> Friday
_ -> Saturday
fromEnum Monday = 1
fromEnum Tuesday = 2
fromEnum Wednesday = 3
fromEnum Thursday = 4
fromEnum Friday = 5
fromEnum Saturday = 6
fromEnum Sunday = 7
enumFromTo wd1 wd2
| wd1 == wd2 = [wd1]
enumFromTo wd1 wd2 = wd1 : enumFromTo (succ wd1) wd2
enumFromThenTo wd1 wd2 wd3
| wd2 == wd3 = [wd1, wd2]
enumFromThenTo wd1 wd2 wd3 = wd1 : enumFromThenTo wd2 (toEnum $ (2 * fromEnum wd2) - (fromEnum wd1)) wd3
dayOfWeek :: Day -> DayOfWeek
dayOfWeek (ModifiedJulianDay d) = toEnum $ fromInteger $ d + 3
toSomeDay :: DayOfWeek -> Day
toSomeDay d = ModifiedJulianDay (fromIntegral $ fromEnum d + 4)
#if MIN_VERSION_time(1,8,0)
#define FORMAT_OPTS tl mpo i
#else
#define FORMAT_OPTS tl mpo
#endif
instance FormatTime DayOfWeek where
formatCharacter 'u' = fmap (\f FORMAT_OPTS d -> f FORMAT_OPTS (toSomeDay d)) (formatCharacter 'u')
formatCharacter 'w' = fmap (\f FORMAT_OPTS d -> f FORMAT_OPTS (toSomeDay d)) (formatCharacter 'w')
formatCharacter 'a' = fmap (\f FORMAT_OPTS d -> f FORMAT_OPTS (toSomeDay d)) (formatCharacter 'a')
formatCharacter 'A' = fmap (\f FORMAT_OPTS d -> f FORMAT_OPTS (toSomeDay d)) (formatCharacter 'A')
formatCharacter _ = Nothing
#endif
#if !MIN_VERSION_time(1,11,0)
dayOfWeekDiff :: DayOfWeek -> DayOfWeek -> Int
dayOfWeekDiff :: DayOfWeek -> DayOfWeek -> Int
dayOfWeekDiff DayOfWeek
a DayOfWeek
b = Int -> Int -> Int
forall a. Integral a => a -> a -> a
mod (DayOfWeek -> Int
forall a. Enum a => a -> Int
fromEnum DayOfWeek
a Int -> Int -> Int
forall a. Num a => a -> a -> a
- DayOfWeek -> Int
forall a. Enum a => a -> Int
fromEnum DayOfWeek
b) Int
7
firstDayOfWeekOnAfter :: DayOfWeek -> Day -> Day
firstDayOfWeekOnAfter :: DayOfWeek -> Day -> Day
firstDayOfWeekOnAfter DayOfWeek
dw Day
d = Year -> Day -> Day
addDays (Int -> Year
forall a. Integral a => a -> Year
toInteger (Int -> Year) -> Int -> Year
forall a b. (a -> b) -> a -> b
$ DayOfWeek -> DayOfWeek -> Int
dayOfWeekDiff DayOfWeek
dw (DayOfWeek -> Int) -> DayOfWeek -> Int
forall a b. (a -> b) -> a -> b
$ Day -> DayOfWeek
dayOfWeek Day
d) Day
d
#endif