Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 16 additions & 7 deletions polyfill/lib/calendar.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,19 @@ function calendarDateWeekOfYear(id, isoDate) {
return { week: woy, year: yow };
}

function ISODateSurpasses(sign, y1, m1, d1, isoDate2) {
function ISODateSurpasses(sign, baseDate, isoDate2, years, months, weeks, days) {
const yearMonth = ES.BalanceISOYearMonth(baseDate.year + years, baseDate.month + months);
let y1 = yearMonth.year;
let m1 = yearMonth.month;
let d1 = baseDate.day;
if (weeks !== 0 || days !== 0) {
const regulatedDate = ES.RegulateISODate(y1, m1, d1, 'constrain');
({
year: y1,
month: m1,
day: d1
} = ES.BalanceISODate(regulatedDate.year, regulatedDate.month, regulatedDate.day + 7 * weeks + days));
}
if (y1 !== isoDate2.year) {
if (sign * (y1 - isoDate2.year) > 0) return true;
} else if (m1 !== isoDate2.month) {
Expand Down Expand Up @@ -192,25 +204,22 @@ impl['iso8601'] = {

let years = 0;
let months = 0;
let intermediate;
if (largestUnit === 'year' || largestUnit === 'month') {
// We can skip right to the neighbourhood of the correct number of years,
// it'll be at least one less than two.year - one.year (unless it's zero)
let candidateYears = two.year - one.year;
if (candidateYears !== 0) candidateYears -= sign;
// loops at most twice
while (!ISODateSurpasses(sign, one.year + candidateYears, one.month, one.day, two)) {
while (!ISODateSurpasses(sign, one, two, candidateYears, 0, 0, 0)) {
years = candidateYears;
candidateYears += sign;
}

let candidateMonths = sign;
intermediate = ES.BalanceISOYearMonth(one.year + years, one.month + candidateMonths);
// loops at most 12 times
while (!ISODateSurpasses(sign, intermediate.year, intermediate.month, one.day, two)) {
while (!ISODateSurpasses(sign, one, two, years, candidateMonths, 0, 0)) {
months = candidateMonths;
candidateMonths += sign;
intermediate = ES.BalanceISOYearMonth(intermediate.year, intermediate.month + sign);
}

if (largestUnit === 'month') {
Expand All @@ -219,7 +228,7 @@ impl['iso8601'] = {
}
}

intermediate = ES.BalanceISOYearMonth(one.year + years, one.month + months);
const intermediate = ES.BalanceISOYearMonth(one.year + years, one.month + months);
const constrained = ES.ConstrainISODate(intermediate.year, intermediate.month, one.day);

let weeks = 0;
Expand Down
16 changes: 4 additions & 12 deletions spec/calendar.html
Original file line number Diff line number Diff line change
Expand Up @@ -563,34 +563,26 @@ <h1>
1. Let _years_ be 0.
1. If _largestUnit_ is ~year~, then
1. Let _candidateYears_ be _sign_.
1. Repeat, while ISODateSurpasses(_sign_, _one_.[[Year]] + _candidateYears_, _one_.[[Month]], _one_.[[Day]], _two_) is *false*,
1. Repeat, while ISODateSurpasses(_sign_, _one_, _two_, _candidateYears_, 0, 0, 0) is *false*,
1. Set _years_ to _candidateYears_.
1. Set _candidateYears_ to _candidateYears_ + _sign_.
1. Let _months_ be 0.
1. If _largestUnit_ is ~year~ or _largestUnit_ is ~month~, then
1. Let _candidateMonths_ be _sign_.
1. Let _intermediate_ be BalanceISOYearMonth(_one_.[[Year]] + _years_, _one_.[[Month]] + _candidateMonths_).
1. Repeat, while ISODateSurpasses(_sign_, _intermediate_.[[Year]], _intermediate_.[[Month]], _one_.[[Day]], _two_) is *false*,
1. Repeat, while ISODateSurpasses(_sign_, _one_, _two_, _years_, _candidateMonths_, 0, 0) is *false*,
1. Set _months_ to _candidateMonths_.
1. Set _candidateMonths_ to _candidateMonths_ + _sign_.
1. Set _intermediate_ to BalanceISOYearMonth(_intermediate_.[[Year]], _intermediate_.[[Month]] + _sign_).
1. Set _intermediate_ to BalanceISOYearMonth(_one_.[[Year]] + _years_, _one_.[[Month]] + _months_).
1. Let _constrained_ be ! RegulateISODate(_intermediate_.[[Year]], _intermediate_.[[Month]], _one_.[[Day]], ~constrain~).
1. Let _weeks_ be 0.
1. If _largestUnit_ is ~week~, then
1. Let _candidateWeeks_ be _sign_.
1. Set _intermediate_ to BalanceISODate(_constrained_.[[Year]], _constrained_.[[Month]], _constrained_.[[Day]] + 7 × _candidateWeeks_).
1. Repeat, while ISODateSurpasses(_sign_, _intermediate_.[[Year]], _intermediate_.[[Month]], _intermediate_.[[Day]], _two_) is *false*,
1. Repeat, while ISODateSurpasses(_sign_, _one_, _two_, _years_, _months_, _candidateWeeks_, 0) is *false*,
1. Set _weeks_ to _candidateWeeks_.
1. Set _candidateWeeks_ to _candidateWeeks_ + sign.
1. Set _intermediate_ to BalanceISODate(_intermediate_.[[Year]], _intermediate_.[[Month]], _intermediate_.[[Day]] + 7 × _sign_).
1. Let _days_ be 0.
1. Let _candidateDays_ be _sign_.
1. Set _intermediate_ to BalanceISODate(_constrained_.[[Year]], _constrained_.[[Month]], _constrained_.[[Day]] + 7 × _weeks_ + _candidateDays_).
1. Repeat, while ISODateSurpasses(_sign_, _intermediate_.[[Year]], _intermediate_.[[Month]], _intermediate_.[[Day]], _two_) is *false*,
1. Repeat, while ISODateSurpasses(_sign_, _one_, _two_, _years_, _months_, _weeks_, _candidateDays_) is *false*,
1. Set _days_ to _candidateDays_.
1. Set _candidateDays_ to _candidateDays_ + _sign_.
1. Set _intermediate_ to BalanceISODate(_intermediate_.[[Year]], _intermediate_.[[Month]], _intermediate_.[[Day]] + _sign_).
1. Return ! CreateDateDurationRecord(_years_, _months_, _weeks_, _days_).
1. Return NonISODateUntil(_calendar_, _one_, _two_, _largestUnit_).
</emu-alg>
Expand Down
23 changes: 18 additions & 5 deletions spec/plaindate.html
Original file line number Diff line number Diff line change
Expand Up @@ -694,21 +694,34 @@ <h1>
<h1>
ISODateSurpasses (
_sign_: -1 or 1,
_y1_: an integer,
_m1_: an integer,
_d1_: an integer,
_baseDate_: an ISO Date Record,
_isoDate2_: an ISO Date Record,
_years_: an integer,
_months_: an integer,
_weeks_: an integer,
_days_: an integer,
): a Boolean
</h1>
<dl class="header">
<dt>description</dt>
<dd>
The return value indicates whether the date denoted by _y1_, _m1_, _d1_ surpasses that denoted by _isoDate2_ in the direction denoted by _sign_.
The former date does not have to exist.
The return value indicates whether the date _isoDate1_, the result of adding the duration denoted by _years_, _months_, _weeks_, and _days_ to _baseDate_, surpasses _isoDate2_ in the direction denoted by _sign_.
If _weeks_ and _days_ are both zero, then _isoDate1_ need not exist (for example, it could be February 30).
Note that this operation is specific to date difference calculations and is not the same as CompareISODate.
</dd>
</dl>
<emu-alg>
1. Let _yearMonth_ be BalanceISOYearMonth(_baseDate_.[[Year]] + _years_, _baseDate_.[[Month]] + _months_).
1. If _weeks_ is not 0 or _days_ is not 0, then
1. Let _regulatedDate_ be ! RegulateISODate(_yearMonth_.[[Year]], _yearMonth_.[[Month]], _baseDate_.[[Day]], ~constrain~).
1. Let _balancedDate_ be BalanceISODate(_regulatedDate_.[[Year]], _regulatedDate_.[[Month]], _regulatedDate_.[[Day]] + 7 * _weeks_ + _days_).
1. Let _y1_ be _balancedDate_.[[Year]].
1. Let _m1_ be _balancedDate_.[[Month]].
1. Let _d1_ be _balancedDate_.[[Day]].
1. Else,
1. Let _y1_ be _yearMonth_.[[Year]].
1. Let _m1_ be _yearMonth_.[[Month]].
1. Let _d1_ be _baseDate_.[[Day]].
1. If _y1_ ≠ _isoDate2_.[[Year]], then
1. If _sign_ × (_y1_ - _isoDate2_.[[Year]]) > 0, return *true*.
1. Else if _m1_ ≠ _isoDate2_.[[Month]], then
Expand Down