Skip to content

Commit 51b7480

Browse files
committed
add IsoDuration; use Map instead of List Tuple
1 parent 0a7b628 commit 51b7480

File tree

3 files changed

+58
-27
lines changed

3 files changed

+58
-27
lines changed

bower.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,8 @@
2020
"purescript-functions": "^3.0.0",
2121
"purescript-generics": "^4.0.0",
2222
"purescript-integers": "^3.0.0",
23-
"purescript-math": "^2.0.0"
23+
"purescript-math": "^2.0.0",
24+
"purescript-maps": "^3.0.0"
2425
},
2526
"devDependencies": {
2627
"purescript-assert": "^3.0.0",

src/Data/Interval/Interval.purs

Lines changed: 52 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,13 @@
11
-- TODO commiting this temporarly as depending on my fork of datetime is
22
-- not possibel as this module is not updated to [email protected]
33
module Data.Interval
4-
( Duration
5-
, Interval(..)
4+
( Interval(..)
65
, RecurringInterval(..)
6+
, IsoDuration
7+
, unIsoDuration
8+
, mkIsoDuration
9+
, isValidIsoDuration
10+
, Duration
711
, year
812
, month
913
, week
@@ -15,15 +19,19 @@ module Data.Interval
1519
) where
1620

1721
import Prelude
18-
import Control.Extend (class Extend)
19-
import Data.Bifunctor (class Bifunctor, bimap)
20-
import Data.Foldable (class Foldable, foldrDefault, foldMapDefaultL)
22+
import Control.Extend (class Extend, (=>>))
23+
import Data.Foldable (class Foldable, fold, foldMap, foldrDefault, foldMapDefaultL)
2124
import Data.Bifoldable (class Bifoldable, bifoldrDefault, bifoldMapDefaultL)
22-
import Data.List (List(..), (:))
23-
import Data.Maybe (Maybe)
25+
import Data.Bifunctor (class Bifunctor, bimap)
26+
import Data.List ((:), reverse)
27+
import Data.Maybe (Maybe(..))
28+
import Data.Map as Map
2429
import Data.Monoid (class Monoid, mempty)
30+
import Data.Monoid.Conj (Conj(..))
31+
import Data.Monoid.Additive (Additive(..))
2532
import Data.Traversable (class Traversable, sequenceDefault)
26-
import Data.Tuple (Tuple(..))
33+
import Data.Tuple (Tuple(..), snd)
34+
import Math as Math
2735

2836

2937
data RecurringInterval d a = RecurringInterval (Maybe Int) (Interval d a)
@@ -79,30 +87,51 @@ instance extendInterval ∷ Extend (Interval d) where
7987
extend f (JustDuration d) = JustDuration d
8088

8189

82-
data Duration = Duration DurationIn
83-
type DurationIn = List (Tuple DurationComponent Number)
90+
mkIsoDuration Duration Maybe IsoDuration
91+
mkIsoDuration d | isValidIsoDuration d = Just $ IsoDuration d
92+
mkIsoDuration _ = Nothing
93+
94+
isFractional Number Boolean
95+
isFractional a = Math.floor a /= a
96+
97+
-- allow only last number to be fractional
98+
isValidIsoDuration Duration Boolean
99+
isValidIsoDuration (Duration m) = Map.toAscUnfoldable m
100+
# reverse
101+
=>> (validateFractionalUse >>> Conj)
102+
# fold
103+
# unConj
104+
where
105+
unConj (Conj a) = a
106+
validateFractionalUse = case _ of
107+
(Tuple _ n):as | isFractional n → foldMap (snd >>> Additive) as == mempty
108+
_ → true
109+
110+
unIsoDuration IsoDuration Duration
111+
unIsoDuration (IsoDuration a) = a
112+
113+
data IsoDuration = IsoDuration Duration
114+
derive instance eqIsoDurationEq IsoDuration
115+
instance showIsoDurationShow IsoDuration where
116+
show (IsoDuration d)= "(IsoDuration " <> show d <> ")"
117+
84118

119+
data Duration = Duration (Map.Map DurationComponent Number)
85120
-- TODO `day 1 == hours 24`
86121
derive instance eqDurationEq Duration
122+
87123
instance showDurationShow Duration where
88124
show (Duration d)= "(Duration " <> show d <> ")"
89125

90126
instance semigroupDurationSemigroup Duration where
91-
append (Duration a) (Duration b) = Duration (appendComponents a b)
127+
append (Duration a) (Duration b) = Duration $ Map.unionWith (+) a b
92128

93129
instance monoidDurationMonoid Duration where
94130
mempty = Duration mempty
95131

96-
appendComponents DurationIn DurationIn DurationIn
97-
appendComponents Nil x = x
98-
appendComponents x Nil = x
99-
appendComponents ass@(a:as) bss@(b:bs) = case a, b of
100-
Tuple aC aV, Tuple bC bV
101-
| aC > bC → a : appendComponents as bss
102-
| aC < bC → b : appendComponents ass bs
103-
| otherwise → Tuple aC (aV + bV) : appendComponents as bs
104-
105132
data DurationComponent = Seconds | Minutes | Hours | Day | Month | Year
133+
derive instance eqDurationComponentEq DurationComponent
134+
derive instance ordDurationComponentOrd DurationComponent
106135

107136
instance showDurationComponentShow DurationComponent where
108137
show Year = "Year"
@@ -112,9 +141,6 @@ instance showDurationComponent ∷ Show DurationComponent where
112141
show Minutes = "Minutes"
113142
show Seconds = "Seconds"
114143

115-
derive instance eqDurationComponentEq DurationComponent
116-
derive instance ordDurationComponentOrd DurationComponent
117-
118144

119145
week Number Duration
120146
week = durationFromComponent Day <<< (_ * 7.0)
@@ -140,6 +166,6 @@ seconds = durationFromComponent Seconds
140166
milliseconds Number Duration
141167
milliseconds = durationFromComponent Seconds <<< (_ / 1000.0)
142168

143-
durationFromComponent DurationComponent Number Duration
144-
durationFromComponent c 0.0 = mempty
145-
durationFromComponent c n = Duration $ pure $ Tuple c n
169+
durationFromComponent DurationComponent Number Duration
170+
-- durationFromComponent _ 0.0 = mempty
171+
durationFromComponent k v= Duration $ Map.singleton k v

test/Test/Main.purs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,10 @@ main = do
3030
assert $ Interval.year 1.0 == mempty <> Interval.year 2.0 <> Interval.year 1.0 <> Interval.year (-2.0)
3131
assert $ Interval.seconds 0.5 == Interval.milliseconds 500.0
3232
assert $ Interval.week 1.0 == Interval.day 7.0
33+
assert $ Interval.mkIsoDuration (Interval.week 1.2 <> mempty) /= Nothing
34+
assert $ Interval.mkIsoDuration (Interval.week 1.2 <> Interval.seconds 0.0) /= Nothing
35+
assert $ Interval.mkIsoDuration (Interval.year 2.0 <> Interval.week 1.0) /= Nothing
36+
assert $ Interval.mkIsoDuration (Interval.year 2.5 <> Interval.week 1.0) == Nothing
3337
-- time --------------------------------------------------------------------
3438

3539
log "Check that Hour is a good BoundedEnum"

0 commit comments

Comments
 (0)