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))