diff --git a/std/assembly/date.ts b/std/assembly/date.ts index 230f995c6d..0e1fb889d1 100644 --- a/std/assembly/date.ts +++ b/std/assembly/date.ts @@ -6,7 +6,12 @@ import { Date as Date_binding } from "./bindings/dom"; MILLIS_PER_DAY = 1000 * 60 * 60 * 24, MILLIS_PER_HOUR = 1000 * 60 * 60, MILLIS_PER_MINUTE = 1000 * 60, - MILLIS_PER_SECOND = 1000; + MILLIS_PER_SECOND = 1000, + + YEARS_PER_EPOCH = 400, + DAYS_PER_EPOCH = 146097, + EPOCH_OFFSET = 719468, // Jan 1, 1970 + MILLIS_LIMIT = 8640000000000000; // ymdFromEpochDays returns values via globals to avoid allocations // @ts-ignore: decorator @@ -94,7 +99,7 @@ export class Date { // instead throwing exception. if (invalidDate(epochMillis)) throw new RangeError(E_INVALIDDATE); - this.year = ymdFromEpochDays(i32(floorDiv(epochMillis, MILLIS_PER_DAY))); + this.year = dateFromEpoch(epochMillis); this.month = _month; this.day = _day; } @@ -107,7 +112,7 @@ export class Date { if (invalidDate(time)) throw new RangeError(E_INVALIDDATE); this.epochMillis = time; - this.year = ymdFromEpochDays(i32(floorDiv(time, MILLIS_PER_DAY))); + this.year = dateFromEpoch(time); this.month = _month; this.day = _day; @@ -306,7 +311,7 @@ function epochMillis( // @ts-ignore: decorator @inline function floorDiv(a: T, b: T): T { - return (a >= 0 ? a : a - b + 1) / b as T; + return (a - (a < 0 ? b - 1 : 0)) / b as T; } // @ts-ignore: decorator @@ -317,33 +322,34 @@ function epochMillis( function invalidDate(millis: i64): bool { // @ts-ignore - return (millis < -8640000000000000) | (millis > 8640000000000000); + return (millis < -MILLIS_LIMIT) | (millis > MILLIS_LIMIT); } -// see: http://howardhinnant.github.io/date_algorithms.html#civil_from_days -function ymdFromEpochDays(z: i32): i32 { - z += 719468; - var era = floorDiv(z, 146097); - var doe = z - era * 146097; // [0, 146096] - var yoe = (doe - doe / 1460 + doe / 36524 - doe / 146096) / 365; // [0, 399] - var year = yoe + era * 400; - var doy = doe - (365 * yoe + yoe / 4 - yoe / 100); // [0, 365] - var mo = (5 * doy + 2) / 153; // [0, 11] - _day = doy - (153 * mo + 2) / 5 + 1; // [1, 31] - mo += mo < 10 ? 3 : -9; // [1, 12] - _month = mo; - year += u32(mo <= 2); +// Based on "Euclidean Affine Functions and Applications to Calendar Algorithms" +// Paper: https://arxiv.org/pdf/2102.06959.pdf +function dateFromEpoch(ms: i64): i32 { + var da = (floorDiv(ms, MILLIS_PER_DAY) * 4 + EPOCH_OFFSET * 4) | 3; + var q0 = floorDiv(da, DAYS_PER_EPOCH); // [0, 146096] + var r1 = da - q0 * DAYS_PER_EPOCH; + var u1 = u64(r1 | 3) * 2939745; + var dm1 = u1 / 11758980; + var n1 = 2141 * dm1 + 197913; + var year = 100 * q0 + i32(u1 >>> 32); + var mo = n1 >>> 16; + _day = (n1 & 0xFFFF) / 2141 + 1; // [1, 31] + if (dm1 >= 306) { mo -= 12; ++year; } + _month = mo; // [1, 12] return year; } // http://howardhinnant.github.io/date_algorithms.html#days_from_civil function daysSinceEpoch(y: i32, m: i32, d: i32): i32 { y -= i32(m <= 2); - var era = floorDiv(y, 400); - var yoe = y - era * 400; // [0, 399] + var era = floorDiv(y, YEARS_PER_EPOCH); + var yoe = y - era * YEARS_PER_EPOCH; // [0, 399] var doy = (153 * (m + (m > 2 ? -3 : 9)) + 2) / 5 + d - 1; // [0, 365] var doe = yoe * 365 + yoe / 4 - yoe / 100 + doy; // [0, 146096] - return era * 146097 + doe - 719468; + return era * 146097 + doe - EPOCH_OFFSET; } // TomohikoSakamoto algorithm from https://en.wikipedia.org/wiki/Determination_of_the_day_of_the_week @@ -351,7 +357,7 @@ function dayOfWeek(year: i32, month: i32, day: i32): i32 { const tab = memory.data([0, 3, 2, 5, 0, 3, 5, 1, 4, 6, 2, 4]); year -= i32(month < 3); - year += floorDiv(year, 4) - floorDiv(year, 100) + floorDiv(year, 400); + year += floorDiv(year, 4) - floorDiv(year, 100) + floorDiv(year, YEARS_PER_EPOCH); month = load(tab + month - 1); return euclidRem(year + month + day, 7); } diff --git a/tests/compiler/std/date.debug.wat b/tests/compiler/std/date.debug.wat index 311477d807..60790f24a4 100644 --- a/tests/compiler/std/date.debug.wat +++ b/tests/compiler/std/date.debug.wat @@ -7,8 +7,8 @@ (type $i32_i32_i32_=>_none (func (param i32 i32 i32))) (type $none_=>_none (func)) (type $i32_i32_i32_i32_=>_none (func (param i32 i32 i32 i32))) - (type $i32_i32_i32_i32_i32_i32_i32_=>_i64 (func (param i32 i32 i32 i32 i32 i32 i32) (result i64))) (type $i64_=>_i32 (func (param i64) (result i32))) + (type $i32_i32_i32_i32_i32_i32_i32_=>_i64 (func (param i32 i32 i32 i32 i32 i32 i32) (result i64))) (type $none_=>_i32 (func (result i32))) (type $i32_i64_=>_none (func (param i32 i64))) (type $i32_i64_=>_i64 (func (param i32 i64) (result i64))) @@ -172,17 +172,17 @@ i32.const 400 local.set $3 local.get $4 + local.get $4 i32.const 0 - i32.ge_s + i32.lt_s if (result i32) - local.get $4 - else - local.get $4 local.get $3 - i32.sub i32.const 1 - i32.add + i32.sub + else + i32.const 0 end + i32.sub local.get $3 i32.div_s local.set $5 @@ -265,127 +265,137 @@ ) (func $~lib/date/invalidDate (param $0 i64) (result i32) local.get $0 - i64.const -8640000000000000 + i64.const 0 + i64.const 8640000000000000 + i64.sub i64.lt_s local.get $0 i64.const 8640000000000000 i64.gt_s i32.or ) - (func $~lib/date/ymdFromEpochDays (param $0 i32) (result i32) - (local $1 i32) - (local $2 i32) + (func $~lib/date/dateFromEpoch (param $0 i64) (result i32) + (local $1 i64) + (local $2 i64) (local $3 i32) (local $4 i32) (local $5 i32) (local $6 i32) (local $7 i32) - (local $8 i32) - local.get $0 - i32.const 719468 - i32.add - local.set $0 + (local $8 i64) + (local $9 i32) + (local $10 i32) + (local $11 i32) + (local $12 i32) local.get $0 local.set $2 - i32.const 146097 + i32.const 86400000 + i64.extend_i32_s local.set $1 local.get $2 - i32.const 0 - i32.ge_s - if (result i32) - local.get $2 - else - local.get $2 + local.get $2 + i64.const 0 + i64.lt_s + if (result i64) local.get $1 - i32.sub - i32.const 1 - i32.add + i64.const 1 + i64.sub + else + i64.const 0 end + i64.sub local.get $1 - i32.div_s + i64.div_s + i32.wrap_i64 + i32.const 4 + i32.mul + i32.const 719468 + i32.const 4 + i32.mul + i32.add + i32.const 3 + i32.or local.set $3 - local.get $0 local.get $3 + local.set $5 i32.const 146097 - i32.mul - i32.sub local.set $4 - local.get $4 - local.get $4 - i32.const 1460 - i32.div_u + local.get $5 + local.get $5 + i32.const 0 + i32.lt_s + if (result i32) + local.get $4 + i32.const 1 + i32.sub + else + i32.const 0 + end i32.sub local.get $4 - i32.const 36524 - i32.div_u - i32.add - local.get $4 - i32.const 146096 - i32.div_u - i32.sub - i32.const 365 - i32.div_u - local.set $5 - local.get $5 - local.get $3 - i32.const 400 - i32.mul - i32.add + i32.div_s local.set $6 - local.get $4 - i32.const 365 - local.get $5 + local.get $3 + local.get $6 + i32.const 146097 i32.mul - local.get $5 - i32.const 4 - i32.div_u - i32.add - local.get $5 - i32.const 100 - i32.div_u - i32.sub i32.sub local.set $7 - i32.const 5 local.get $7 - i32.mul - i32.const 2 - i32.add - i32.const 153 - i32.div_s + i32.const 3 + i32.or + i64.extend_i32_u + i64.const 2939745 + i64.mul local.set $8 - local.get $7 - i32.const 153 local.get $8 + i32.wrap_i64 + i32.const 11758980 + i32.div_u + local.set $9 + i32.const 2141 + local.get $9 i32.mul - i32.const 2 + i32.const 197913 i32.add - i32.const 5 - i32.div_u - i32.sub + local.set $10 + i32.const 100 + local.get $6 + i32.mul + local.get $8 + i64.const 32 + i64.shr_u + i32.wrap_i64 + i32.add + local.set $11 + local.get $10 + i32.const 16 + i32.shr_u + local.set $12 + local.get $10 + i32.const 65535 + i32.and + i32.const 2141 + i32.div_s i32.const 1 i32.add global.set $~lib/date/_day - local.get $8 - local.get $8 - i32.const 10 - i32.lt_s - if (result i32) - i32.const 3 - else - i32.const -9 + local.get $9 + i32.const 306 + i32.ge_u + if + local.get $12 + i32.const 12 + i32.sub + local.set $12 + local.get $11 + i32.const 1 + i32.add + local.set $11 end - i32.add - local.set $8 - local.get $8 + local.get $12 global.set $~lib/date/_month - local.get $6 - local.get $8 - i32.const 2 - i32.le_s - i32.add - local.set $6 - local.get $6 + local.get $11 ) (func $~lib/date/Date#set:year (param $0 i32) (param $1 i32) local.get $0 @@ -2480,14 +2490,12 @@ i64.store offset=16 ) (func $~lib/date/Date#setTime (param $0 i32) (param $1 i64) (result i64) - (local $2 i64) - (local $3 i64) local.get $1 call $~lib/date/invalidDate if i32.const 32 i32.const 80 - i32.const 107 + i32.const 112 i32.const 28 call $~lib/builtins/abort unreachable @@ -2497,26 +2505,7 @@ call $~lib/date/Date#set:epochMillis local.get $0 local.get $1 - local.set $3 - i32.const 86400000 - i64.extend_i32_s - local.set $2 - local.get $3 - i64.const 0 - i64.ge_s - if (result i64) - local.get $3 - else - local.get $3 - local.get $2 - i64.sub - i64.const 1 - i64.add - end - local.get $2 - i64.div_s - i32.wrap_i64 - call $~lib/date/ymdFromEpochDays + call $~lib/date/dateFromEpoch call $~lib/date/Date#set:year local.get $0 global.get $~lib/date/_month @@ -2880,17 +2869,17 @@ i32.const 4 local.set $3 local.get $4 + local.get $4 i32.const 0 - i32.ge_s + i32.lt_s if (result i32) - local.get $4 - else - local.get $4 local.get $3 - i32.sub i32.const 1 - i32.add + i32.sub + else + i32.const 0 end + i32.sub local.get $3 i32.div_s local.get $0 @@ -2898,17 +2887,17 @@ i32.const 100 local.set $3 local.get $4 + local.get $4 i32.const 0 - i32.ge_s + i32.lt_s if (result i32) - local.get $4 - else - local.get $4 local.get $3 - i32.sub i32.const 1 - i32.add + i32.sub + else + i32.const 0 end + i32.sub local.get $3 i32.div_s i32.sub @@ -2917,17 +2906,17 @@ i32.const 400 local.set $3 local.get $4 + local.get $4 i32.const 0 - i32.ge_s + i32.lt_s if (result i32) - local.get $4 - else - local.get $4 local.get $3 - i32.sub i32.const 1 - i32.add + i32.sub + else + i32.const 0 end + i32.sub local.get $3 i32.div_s i32.add @@ -5832,7 +5821,7 @@ if i32.const 32 i32.const 80 - i32.const 45 + i32.const 50 i32.const 33 call $~lib/builtins/abort unreachable @@ -5898,7 +5887,7 @@ if i32.const 32 i32.const 80 - i32.const 62 + i32.const 67 i32.const 21 call $~lib/builtins/abort unreachable @@ -6127,7 +6116,7 @@ if i32.const 32 i32.const 80 - i32.const 31 + i32.const 36 i32.const 26 call $~lib/builtins/abort unreachable @@ -6190,7 +6179,7 @@ if i32.const 32 i32.const 80 - i32.const 31 + i32.const 36 i32.const 26 call $~lib/builtins/abort unreachable @@ -6253,7 +6242,7 @@ if i32.const 32 i32.const 80 - i32.const 31 + i32.const 36 i32.const 26 call $~lib/builtins/abort unreachable @@ -6316,7 +6305,7 @@ if i32.const 32 i32.const 80 - i32.const 31 + i32.const 36 i32.const 26 call $~lib/builtins/abort unreachable @@ -6379,7 +6368,7 @@ if i32.const 32 i32.const 80 - i32.const 31 + i32.const 36 i32.const 26 call $~lib/builtins/abort unreachable @@ -6442,7 +6431,7 @@ if i32.const 32 i32.const 80 - i32.const 31 + i32.const 36 i32.const 26 call $~lib/builtins/abort unreachable @@ -6505,7 +6494,7 @@ if i32.const 32 i32.const 80 - i32.const 31 + i32.const 36 i32.const 26 call $~lib/builtins/abort unreachable @@ -9253,9 +9242,7 @@ global.set $~lib/memory/__stack_pointer ) (func $~lib/date/Date#constructor (param $0 i32) (param $1 i64) (result i32) - (local $2 i64) - (local $3 i64) - (local $4 i32) + (local $2 i32) global.get $~lib/memory/__stack_pointer i32.const 4 i32.sub @@ -9291,33 +9278,14 @@ if i32.const 32 i32.const 80 - i32.const 95 + i32.const 100 i32.const 35 call $~lib/builtins/abort unreachable end local.get $0 local.get $1 - local.set $3 - i32.const 86400000 - i64.extend_i32_s - local.set $2 - local.get $3 - i64.const 0 - i64.ge_s - if (result i64) - local.get $3 - else - local.get $3 - local.get $2 - i64.sub - i64.const 1 - i64.add - end - local.get $2 - i64.div_s - i32.wrap_i64 - call $~lib/date/ymdFromEpochDays + call $~lib/date/dateFromEpoch call $~lib/date/Date#set:year local.get $0 global.get $~lib/date/_month @@ -9326,12 +9294,12 @@ global.get $~lib/date/_day call $~lib/date/Date#set:day local.get $0 - local.set $4 + local.set $2 global.get $~lib/memory/__stack_pointer i32.const 4 i32.add global.set $~lib/memory/__stack_pointer - local.get $4 + local.get $2 ) (func $~lib/util/number/itoa32 (param $0 i32) (param $1 i32) (result i32) (local $2 i32) diff --git a/tests/compiler/std/date.release.wat b/tests/compiler/std/date.release.wat index dd4b00d71a..75b03bab44 100644 --- a/tests/compiler/std/date.release.wat +++ b/tests/compiler/std/date.release.wat @@ -4,6 +4,7 @@ (type $i32_i32_=>_i32 (func (param i32 i32) (result i32))) (type $none_=>_none (func)) (type $i32_=>_none (func (param i32))) + (type $i64_=>_i32 (func (param i64) (result i32))) (type $i32_i32_i32_=>_none (func (param i32 i32 i32))) (type $i32_i32_i32_=>_i32 (func (param i32 i32 i32) (result i32))) (type $i32_i32_i32_i32_i32_i32_i32_=>_i64 (func (param i32 i32 i32 i32 i32 i32 i32) (result i64))) @@ -11,7 +12,6 @@ (type $none_=>_i32 (func (result i32))) (type $i32_i64_=>_none (func (param i32 i64))) (type $i32_i32_i32_i32_=>_i32 (func (param i32 i32 i32 i32) (result i32))) - (type $i64_=>_i32 (func (param i64) (result i32))) (import "env" "abort" (func $~lib/builtins/abort (param i32 i32 i32 i32))) (global $~lib/date/_day (mut i32) (i32.const 0)) (global $~lib/date/_month (mut i32) (i32.const 0)) @@ -254,13 +254,13 @@ i32.le_s i32.sub local.tee $0 - local.get $0 i32.const 399 - i32.sub + i32.const 0 local.get $0 i32.const 0 - i32.ge_s + i32.lt_s select + i32.sub i32.const 400 i32.div_s local.set $3 @@ -311,97 +311,96 @@ i64.add i64.add ) - (func $~lib/date/ymdFromEpochDays (param $0 i32) (result i32) + (func $~lib/date/dateFromEpoch (param $0 i64) (result i32) (local $1 i32) (local $2 i32) (local $3 i32) + (local $4 i32) local.get $0 - i32.const 719468 + i64.const 86399999 + i64.const 0 + local.get $0 + i64.const 0 + i64.lt_s + select + i64.sub + i64.const 86400000 + i64.div_s + i32.wrap_i64 + i32.const 2 + i32.shl + i32.const 2877872 i32.add + i32.const 3 + i32.or local.tee $1 - local.get $1 i32.const 146096 - i32.sub + i32.const 0 local.get $1 i32.const 0 - i32.ge_s + i32.lt_s select + i32.sub i32.const 146097 i32.div_s - local.set $0 + local.set $2 local.get $1 - local.get $0 + local.get $2 i32.const 146097 i32.mul i32.sub - local.tee $1 - local.get $1 - i32.const 1460 - i32.div_u - i32.sub - local.get $1 - i32.const 36524 - i32.div_u - i32.add - local.get $1 - i32.const 146096 - i32.div_u - i32.sub - i32.const 365 + i32.const 3 + i32.or + i64.extend_i32_u + i64.const 2939745 + i64.mul + local.tee $0 + i32.wrap_i64 + i32.const 11758980 i32.div_u - local.set $2 - local.get $1 - local.get $2 - i32.const 365 + local.tee $4 + i32.const 2141 i32.mul - local.get $2 - i32.const 2 - i32.shr_u + i32.const 197913 i32.add + local.set $3 + local.get $0 + i64.const 32 + i64.shr_u + i32.wrap_i64 local.get $2 i32.const 100 - i32.div_u - i32.sub - i32.sub - local.tee $3 - i32.const 5 i32.mul - i32.const 2 i32.add - i32.const 153 - i32.div_s local.set $1 local.get $3 - local.get $1 - i32.const 153 - i32.mul - i32.const 2 - i32.add - i32.const 5 + i32.const 16 + i32.shr_u + local.set $2 + local.get $3 + i32.const 65535 + i32.and + i32.const 2141 i32.div_u - i32.sub i32.const 1 i32.add global.set $~lib/date/_day - local.get $1 - i32.const 3 - i32.const -9 - local.get $1 - i32.const 10 - i32.lt_s - select - i32.add - local.tee $1 - global.set $~lib/date/_month + local.get $4 + i32.const 306 + i32.ge_u + if + local.get $2 + i32.const 12 + i32.sub + local.set $2 + local.get $1 + i32.const 1 + i32.add + local.set $1 + end local.get $2 - local.get $0 - i32.const 400 - i32.mul - i32.add + global.set $~lib/date/_month local.get $1 - i32.const 2 - i32.le_s - i32.add ) (func $~lib/rt/itcms/visitRoots (local $0 i32) @@ -1888,7 +1887,7 @@ if i32.const 1056 i32.const 1104 - i32.const 107 + i32.const 112 i32.const 28 call $~lib/builtins/abort unreachable @@ -1898,17 +1897,7 @@ i64.store offset=16 local.get $0 local.get $1 - local.get $1 - i64.const 86399999 - i64.sub - local.get $1 - i64.const 0 - i64.ge_s - select - i64.const 86400000 - i64.div_s - i32.wrap_i64 - call $~lib/date/ymdFromEpochDays + call $~lib/date/dateFromEpoch i32.store local.get $0 global.get $~lib/date/_month @@ -2062,13 +2051,13 @@ i32.le_s i32.sub local.tee $3 - local.get $3 i32.const 399 - i32.sub + i32.const 0 local.get $3 i32.const 0 - i32.ge_s + i32.lt_s select + i32.sub i32.const 400 i32.div_s local.set $0 @@ -2165,13 +2154,13 @@ i32.le_s i32.sub local.tee $0 - local.get $0 i32.const 399 - i32.sub + i32.const 0 local.get $0 i32.const 0 - i32.ge_s + i32.lt_s select + i32.sub i32.const 400 i32.div_s local.set $4 @@ -2240,13 +2229,13 @@ i32.le_s i32.sub local.tee $3 - local.get $3 i32.const 399 - i32.sub + i32.const 0 local.get $3 i32.const 0 - i32.ge_s + i32.lt_s select + i32.sub i32.const 400 i32.div_s local.set $1 @@ -3734,31 +3723,31 @@ i32.load8_u local.get $6 local.get $6 - local.get $6 i32.const 3 - i32.sub + i32.const 0 local.get $6 i32.const 0 - i32.ge_s + i32.lt_s local.tee $0 select + i32.sub i32.const 4 i32.div_s local.get $6 - local.get $6 i32.const 99 - i32.sub + i32.const 0 local.get $0 select + i32.sub i32.const 100 i32.div_s i32.sub local.get $6 - local.get $6 i32.const 399 - i32.sub + i32.const 0 local.get $0 select + i32.sub i32.const 400 i32.div_s i32.add @@ -4099,31 +4088,31 @@ i32.load8_u local.get $1 local.get $1 - local.get $1 i32.const 3 - i32.sub + i32.const 0 local.get $1 i32.const 0 - i32.ge_s + i32.lt_s local.tee $8 select + i32.sub i32.const 4 i32.div_s local.get $1 - local.get $1 i32.const 99 - i32.sub + i32.const 0 local.get $8 select + i32.sub i32.const 100 i32.div_s i32.sub local.get $1 - local.get $1 i32.const 399 - i32.sub + i32.const 0 local.get $8 select + i32.sub i32.const 400 i32.div_s i32.add @@ -4702,7 +4691,7 @@ if i32.const 1056 i32.const 1104 - i32.const 45 + i32.const 50 i32.const 33 call $~lib/builtins/abort unreachable @@ -4753,7 +4742,7 @@ if i32.const 1056 i32.const 1104 - i32.const 62 + i32.const 67 i32.const 21 call $~lib/builtins/abort unreachable @@ -6361,31 +6350,31 @@ i32.load8_u local.get $3 local.get $3 - local.get $3 i32.const 3 - i32.sub + i32.const 0 local.get $3 i32.const 0 - i32.ge_s + i32.lt_s local.tee $0 select + i32.sub i32.const 4 i32.div_s local.get $3 - local.get $3 i32.const 99 - i32.sub + i32.const 0 local.get $0 select + i32.sub i32.const 100 i32.div_s i32.sub local.get $3 - local.get $3 i32.const 399 - i32.sub + i32.const 0 local.get $0 select + i32.sub i32.const 400 i32.div_s i32.add @@ -6434,31 +6423,31 @@ i32.load8_u local.get $3 local.get $3 - local.get $3 i32.const 3 - i32.sub + i32.const 0 local.get $3 i32.const 0 - i32.ge_s + i32.lt_s local.tee $0 select + i32.sub i32.const 4 i32.div_s local.get $3 - local.get $3 i32.const 99 - i32.sub + i32.const 0 local.get $0 select + i32.sub i32.const 100 i32.div_s i32.sub local.get $3 - local.get $3 i32.const 399 - i32.sub + i32.const 0 local.get $0 select + i32.sub i32.const 400 i32.div_s i32.add @@ -6507,31 +6496,31 @@ i32.load8_u local.get $3 local.get $3 - local.get $3 i32.const 3 - i32.sub + i32.const 0 local.get $3 i32.const 0 - i32.ge_s + i32.lt_s local.tee $0 select + i32.sub i32.const 4 i32.div_s local.get $3 - local.get $3 i32.const 99 - i32.sub + i32.const 0 local.get $0 select + i32.sub i32.const 100 i32.div_s i32.sub local.get $3 - local.get $3 i32.const 399 - i32.sub + i32.const 0 local.get $0 select + i32.sub i32.const 400 i32.div_s i32.add @@ -6580,31 +6569,31 @@ i32.load8_u local.get $3 local.get $3 - local.get $3 i32.const 3 - i32.sub + i32.const 0 local.get $3 i32.const 0 - i32.ge_s + i32.lt_s local.tee $0 select + i32.sub i32.const 4 i32.div_s local.get $3 - local.get $3 i32.const 99 - i32.sub + i32.const 0 local.get $0 select + i32.sub i32.const 100 i32.div_s i32.sub local.get $3 - local.get $3 i32.const 399 - i32.sub + i32.const 0 local.get $0 select + i32.sub i32.const 400 i32.div_s i32.add @@ -6653,31 +6642,31 @@ i32.load8_u local.get $3 local.get $3 - local.get $3 i32.const 3 - i32.sub + i32.const 0 local.get $3 i32.const 0 - i32.ge_s + i32.lt_s local.tee $0 select + i32.sub i32.const 4 i32.div_s local.get $3 - local.get $3 i32.const 99 - i32.sub + i32.const 0 local.get $0 select + i32.sub i32.const 100 i32.div_s i32.sub local.get $3 - local.get $3 i32.const 399 - i32.sub + i32.const 0 local.get $0 select + i32.sub i32.const 400 i32.div_s i32.add @@ -6726,31 +6715,31 @@ i32.load8_u local.get $3 local.get $3 - local.get $3 i32.const 3 - i32.sub + i32.const 0 local.get $3 i32.const 0 - i32.ge_s + i32.lt_s local.tee $0 select + i32.sub i32.const 4 i32.div_s local.get $3 - local.get $3 i32.const 99 - i32.sub + i32.const 0 local.get $0 select + i32.sub i32.const 100 i32.div_s i32.sub local.get $3 - local.get $3 i32.const 399 - i32.sub + i32.const 0 local.get $0 select + i32.sub i32.const 400 i32.div_s i32.add @@ -6799,31 +6788,31 @@ i32.load8_u local.get $3 local.get $3 - local.get $3 i32.const 3 - i32.sub + i32.const 0 local.get $3 i32.const 0 - i32.ge_s + i32.lt_s local.tee $0 select + i32.sub i32.const 4 i32.div_s local.get $3 - local.get $3 i32.const 99 - i32.sub + i32.const 0 local.get $0 select + i32.sub i32.const 100 i32.div_s i32.sub local.get $3 - local.get $3 i32.const 399 - i32.sub + i32.const 0 local.get $0 select + i32.sub i32.const 400 i32.div_s i32.add @@ -6872,31 +6861,31 @@ i32.load8_u local.get $3 local.get $3 - local.get $3 i32.const 3 - i32.sub + i32.const 0 local.get $3 i32.const 0 - i32.ge_s + i32.lt_s local.tee $0 select + i32.sub i32.const 4 i32.div_s local.get $3 - local.get $3 i32.const 99 - i32.sub + i32.const 0 local.get $0 select + i32.sub i32.const 100 i32.div_s i32.sub local.get $3 - local.get $3 i32.const 399 - i32.sub + i32.const 0 local.get $0 select + i32.sub i32.const 400 i32.div_s i32.add @@ -8191,7 +8180,7 @@ end i32.const 1056 i32.const 1104 - i32.const 31 + i32.const 36 i32.const 26 call $~lib/builtins/abort unreachable @@ -8245,24 +8234,14 @@ if i32.const 1056 i32.const 1104 - i32.const 95 + i32.const 100 i32.const 35 call $~lib/builtins/abort unreachable end local.get $1 local.get $0 - local.get $0 - i64.const 86399999 - i64.sub - local.get $0 - i64.const 0 - i64.ge_s - select - i64.const 86400000 - i64.div_s - i32.wrap_i64 - call $~lib/date/ymdFromEpochDays + call $~lib/date/dateFromEpoch i32.store local.get $1 global.get $~lib/date/_month