@@ -9,16 +9,18 @@ module Data.Date
9
9
, diff
10
10
, isLeapYear
11
11
, lastDayOfMonth
12
+ , adjust
12
13
, module Data.Date.Component
13
14
) where
14
15
15
16
import Prelude
16
17
17
18
import Data.Date.Component (Day , Month (..), Weekday (..), Year )
18
- import Data.Enum (toEnum , fromEnum )
19
+ import Data.Enum (class Enum , toEnum , fromEnum , succ , pred )
19
20
import Data.Function.Uncurried (Fn3 , runFn3 , Fn4 , runFn4 , Fn6 , runFn6 )
20
- import Data.Maybe (Maybe (..), fromJust )
21
- import Data.Time.Duration (class Duration , Milliseconds , toDuration )
21
+ import Data.Int (fromNumber )
22
+ import Data.Maybe (Maybe (..), fromJust , fromMaybe , isNothing )
23
+ import Data.Time.Duration (class Duration , Days (..), Milliseconds , toDuration )
22
24
import Partial.Unsafe (unsafePartial )
23
25
24
26
-- | A date value in the Gregorian calendar.
@@ -51,6 +53,24 @@ instance boundedDate :: Bounded Date where
51
53
instance showDate :: Show Date where
52
54
show (Date y m d) = " (Date " <> show y <> " " <> show m <> " " <> show d <> " )"
53
55
56
+ instance enumDate :: Enum Date where
57
+ succ (Date y m d) = Date <$> y' <*> pure m' <*> d'
58
+ where
59
+ d' = if isNothing sd then toEnum 1 else sd
60
+ m' = if isNothing sd then fromMaybe January sm else m
61
+ y' = if isNothing sd && isNothing sm then succ y else Just y
62
+ sd = let v = succ d in if v > Just l then Nothing else v
63
+ sm = succ m
64
+ l = lastDayOfMonth y m
65
+ pred (Date y m d) = Date <$> y' <*> pure m' <*> d'
66
+ where
67
+ d' = if isNothing pd then Just l else pd
68
+ m' = if isNothing pd then fromMaybe December pm else m
69
+ y' = if isNothing pd && isNothing pm then pred y else Just y
70
+ pd = pred d
71
+ pm = pred m
72
+ l = lastDayOfMonth y m'
73
+
54
74
-- | The year component of a date value.
55
75
year :: Date -> Year
56
76
year (Date y _ _) = y
@@ -69,6 +89,26 @@ weekday = unsafePartial \(Date y m d) ->
69
89
let n = runFn3 calcWeekday y (fromEnum m) d
70
90
in if n == 0 then fromJust (toEnum 7 ) else fromJust (toEnum n)
71
91
92
+ -- | Adjusts a date with a Duration in days. The number of days must
93
+ -- | already be an integer and fall within the valid range of values
94
+ -- | for the Int type.
95
+ adjust :: Days -> Date -> Maybe Date
96
+ adjust (Days n) date = fromNumber n >>= flip adj date
97
+ where
98
+ adj 0 dt = Just dt
99
+ adj i (Date y m d) = adj i' =<< dt'
100
+ where
101
+ i' | low = j
102
+ | hi = j - fromEnum l - 1
103
+ | otherwise = 0
104
+ dt' | low = pred =<< Date y m <$> toEnum 1
105
+ | hi = succ (Date y m l)
106
+ | otherwise = Date y m <$> toEnum j
107
+ j = i + fromEnum d
108
+ low = j < 1
109
+ hi = j > fromEnum l
110
+ l = lastDayOfMonth y (if low then fromMaybe December (pred m) else m)
111
+
72
112
-- | Calculates the difference between two dates, returning the result as a
73
113
-- | duration.
74
114
diff :: forall d . Duration d => Date -> Date -> d
0 commit comments