summaryrefslogtreecommitdiffstats
path: root/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/round/smallest-unit-day-rounding-modes.js
blob: f6947124578e1156863500fb68daccc380798ccd (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally
// Copyright (C) 2022 André Bargull. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.

/*---
esid: sec-temporal.zoneddatetime.prototype.round
description: >
  Round smallestUnit "day" with various rounding modes.
info: |
  Temporal.ZonedDateTime.prototype.round ( roundTo )
  ...
  18. Let dayLengthNs be ℝ(endNs - startNs).
  ...
  20. Let roundResult be ! RoundISODateTime(temporalDateTime.[[ISOYear]],
      temporalDateTime.[[ISOMonth]], temporalDateTime.[[ISODay]], temporalDateTime.[[ISOHour]],
      temporalDateTime.[[ISOMinute]], temporalDateTime.[[ISOSecond]],
      temporalDateTime.[[ISOMillisecond]], temporalDateTime.[[ISOMicrosecond]],
      temporalDateTime.[[ISONanosecond]], roundingIncrement, smallestUnit, roundingMode,
      dayLengthNs).
  ...

  RoundISODateTime ( year, month, day, hour, minute, second, millisecond, microsecond, nanosecond,
                     increment, unit, roundingMode [ , dayLength ] )
  ...
  4. Let roundedTime be ! RoundTime(hour, minute, second, millisecond, microsecond, nanosecond,
     increment, unit, roundingMode, dayLength).
  ...

  RoundTime ( hour, minute, second, millisecond, microsecond, nanosecond, increment, unit,
              roundingMode [ , dayLengthNs ] )
  ...
  4. If unit is "day", then
    ...
    b. Let quantity be (((((hour × 60 + minute) × 60 + second) × 1000 + millisecond) × 1000 +
       microsecond) × 1000 + nanosecond) / dayLengthNs.
  ...
features: [Temporal]
---*/

class TimeZone extends Temporal.TimeZone {
  #count = 0;
  #nanoseconds;

  constructor(nanoseconds) {
    super("UTC");
    this.#nanoseconds = nanoseconds;
  }
  getPossibleInstantsFor(dateTime) {
    if (++this.#count === 2) {
      return [new Temporal.Instant(this.#nanoseconds)];
    }
    return super.getPossibleInstantsFor(dateTime);
  }
}

function test(epochNanoseconds, tomorrowEpochNanoseconds, testCases) {
  for (let [roundingMode, expected] of Object.entries(testCases)) {
    let timeZone = new TimeZone(tomorrowEpochNanoseconds);
    let zoned = new Temporal.ZonedDateTime(epochNanoseconds, timeZone);
    let result = zoned.round({ smallestUnit: "days", roundingMode });
    assert.sameValue(result.epochNanoseconds, expected);
  }
}

const oneDay = 24n * 60n * 60n * 1000n * 1000n * 1000n;

// Test positive divisor (dayLengthNs).
test(3n, 10n, {
  ceil: oneDay,
  floor: 0n,
  trunc: 0n,
  halfExpand: 0n,
});

test(-3n, 10n, {
  ceil: 0n,
  floor: -oneDay,
  trunc: -oneDay,
  halfExpand: 0n,
});

test(-3n, -10n, {
  ceil: oneDay,
  floor: 0n,
  trunc: 0n,
  halfExpand: 0n,
});

// Test values at int64 boundaries.
test(3n, /*INT64_MAX=*/ 9223372036854775807n, {
  ceil: oneDay,
  floor: 0n,
  trunc: 0n,
  halfExpand: 0n,
});

reportCompare(0, 0);