week.bend
bend-datetime@0.4.0.0 · 150 lines · 0 definitions
1import Base
2import bend-datetime@0.4.0.0/date.bend as D
3
4type IsoWeek is Data:
5 IsoWeek{year: U32, week: U32}
6
7def IsoWeek.start(d: D.Date) -> Result<&2, &2, D.Date.Error, D.Date>:
8 D.Date.previous_or_same_weekday(d, D.Mon{})
9
10def IsoWeek.from_date.week(
11 +d: D.Date, +year: U32, r: Result<&2, &2, D.Date.Error, D.Date>
12) -> Result<&2, &2, D.Date.Error, IsoWeek>:
13 match r:
14 case Fail{e}:
15 Fail{e}
16 case Done{mon1}:
17 Done{
18 IsoWeek{
19 year,
20 U32.add(
21 1, U32.div(U32.sub(D.Date.to_days(d), D.Date.to_days(mon1)), 7)
22 )
23 }
24 }
25
26def IsoWeek.from_date.mon1(
27 +d: D.Date, +year: U32, r: Result<&2, &2, D.Date.Error, D.Date>
28) -> Result<&2, &2, D.Date.Error, IsoWeek>:
29 match r:
30 case Fail{e}:
31 Fail{e}
32 case Done{jan4}:
33 IsoWeek.from_date.week(d, year, IsoWeek.start(jan4))
34
35def IsoWeek.from_date.year(
36 +d: D.Date, r: Result<&2, &2, D.Date.Error, D.Date>
37) -> Result<&2, &2, D.Date.Error, IsoWeek>:
38 match r:
39 case Fail{e}:
40 Fail{e}
41 case Done{D.Date{+y, _, _}}:
42 IsoWeek.from_date.mon1(d, y, D.Date.from(y, 1, 4))
43
44def IsoWeek.from_date.thu(
45 +d: D.Date, r: Result<&2, &2, D.Date.Error, D.Date>
46) -> Result<&2, &2, D.Date.Error, IsoWeek>:
47 match r:
48 case Fail{e}:
49 Fail{e}
50 case Done{mon}:
51 IsoWeek.from_date.year(d, D.Date.add_days(mon, 3))
52
53def IsoWeek.from_date(+d: D.Date) -> Result<&2, &2, D.Date.Error, IsoWeek>:
54 IsoWeek.from_date.thu(d, IsoWeek.start(d))
55
56def IsoWeek.from.ok(
57 got: D.Date, eq: Bool
58) -> Result<&2, &2, D.Date.Error, D.Date>:
59 match eq:
60 case True{}:
61 Done{got}
62 case False{}:
63 Fail{D.OutOfRange{}}
64
65def IsoWeek.from.eq(
66 +year: U32, +week: U32, +got: D.Date,
67 r: Result<&2, &2, D.Date.Error, IsoWeek>
68) -> Result<&2, &2, D.Date.Error, D.Date>:
69 match r:
70 case Fail{e}:
71 Fail{e}
72 case Done{IsoWeek{+y2, +w2}}:
73 IsoWeek.from.ok(
74 got, Bool.and(U32.is_eq(y2, year), U32.is_eq(w2, week))
75 )
76
77def IsoWeek.from.chk(
78 +year: U32, +week: U32, r: Result<&2, &2, D.Date.Error, D.Date>
79) -> Result<&2, &2, D.Date.Error, D.Date>:
80 match r:
81 case Fail{e}:
82 Fail{e}
83 case Done{+got}:
84 IsoWeek.from.eq(year, week, got, IsoWeek.from_date(got))
85
86def IsoWeek.from.add(
87 +year: U32, +week: U32, weekday: D.Weekday, mon1: D.Date
88) -> Result<&2, &2, D.Date.Error, D.Date>:
89 IsoWeek.from.chk(
90 year, week,
91 D.Date.add_days(
92 mon1,
93 U32.add(U32.mul(U32.sub(week, 1), 7), D.Weekday.to_u32(weekday))
94 )
95 )
96
97def IsoWeek.from.le(
98 +year: U32, +week: U32, weekday: D.Weekday, mon1: D.Date, ok: Bool
99) -> Result<&2, &2, D.Date.Error, D.Date>:
100 match ok:
101 case False{}:
102 Fail{D.OutOfRange{}}
103 case True{}:
104 IsoWeek.from.add(year, week, weekday, mon1)
105
106def IsoWeek.from.mon1(
107 +year: U32, +week: U32, weekday: D.Weekday,
108 r: Result<&2, &2, D.Date.Error, D.Date>
109) -> Result<&2, &2, D.Date.Error, D.Date>:
110 match r:
111 case Fail{e}:
112 Fail{e}
113 case Done{mon1}:
114 IsoWeek.from.le(
115 year, week, weekday, mon1,
116 U32.is_le(U32.sub(week, 1), U32.div(U32.not(0), 7))
117 )
118
119def IsoWeek.from.jan4(
120 +year: U32, +week: U32, weekday: D.Weekday,
121 r: Result<&2, &2, D.Date.Error, D.Date>
122) -> Result<&2, &2, D.Date.Error, D.Date>:
123 match r:
124 case Fail{e}:
125 Fail{e}
126 case Done{jan4}:
127 IsoWeek.from.mon1(year, week, weekday, IsoWeek.start(jan4))
128
129def IsoWeek.from.hi(
130 +year: U32, +week: U32, weekday: D.Weekday, hi: Bool
131) -> Result<&2, &2, D.Date.Error, D.Date>:
132 match hi:
133 case True{}:
134 Fail{D.OutOfRange{}}
135 case False{}:
136 IsoWeek.from.jan4(year, week, weekday, D.Date.from(year, 1, 4))
137
138def IsoWeek.from.ge(
139 +year: U32, +week: U32, weekday: D.Weekday, z: Bool
140) -> Result<&2, &2, D.Date.Error, D.Date>:
141 match z:
142 case True{}:
143 Fail{D.OutOfRange{}}
144 case False{}:
145 IsoWeek.from.hi(year, week, weekday, U32.is_ge(week, 54))
146
147def IsoWeek.from(
148 +year: U32, +week: U32, weekday: D.Weekday
149) -> Result<&2, &2, D.Date.Error, D.Date>:
150 IsoWeek.from.ge(year, week, weekday, U32.is_eq(week, 0))