1 import Base 2 import ./date.bend as D 3 4 type IsoWeek is Data: 5 IsoWeek{year: U32, week: U32} 6 7 def IsoWeek.start(d: D.Date) -> Result<&2, &2, D.Date.Error, D.Date>: 8 D.Date.previous_or_same_weekday(d, D.Mon{}) 9 10 def 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 26 def 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 35 def 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 44 def 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 53 def IsoWeek.from_date(+d: D.Date) -> Result<&2, &2, D.Date.Error, IsoWeek>: 54 IsoWeek.from_date.thu(d, IsoWeek.start(d)) 55 56 def 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 65 def 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 77 def 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 86 def 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 97 def 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 106 def 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 119 def 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 129 def 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 138 def 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 147 def 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))