Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fixes #848

Merged
merged 6 commits into from
Sep 1, 2020
Merged

Fixes #848

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: 23 additions & 0 deletions docs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,29 @@ Most code will use the ISO 8601 calendar, but other calendar systems are availab

See [Temporal.Calendar Documentation](./calendar.md) for more detailed documentation.

## Other Documentation

### **Key Concepts**

- [Ambiguity](./ambiguity.md) — Explanation of missing times and double times due to daylight saving and time zone changes.
- [Balancing](./balancing.md) — Explanation of when `Temporal.Duration` units wrap around to 0 and when they don't.

### **Design drafts**

- [Calendar Draft](./calendar-draft.md) — Draft design document for calendar support in Temporal.
Mostly superseded by the documentation of [Temporal.Calendar](./calendar.md), but also contains some discussion about whether to have a default calendar.
- [ISO string extensions](./iso-string-ext.md) — Discussion of extensions to the ISO 8601 standard which are used by Temporal and intended to be put on a standards track.
- [Parse Draft](./parse-draft.md) — Draft design document for a `Temporal.parse` API, which is not currently planned to be implemented.
- [Zoned Date/Time Type Draft](./localdatetime-draft.md) — Explanation of `Temporal.LocalDateTime` (not the final name) which is a new type combining an absolute time with a time zone.
Currently in progress.

### Obsolete Pages

- [Calendar Subclassing Draft](./calendar-subclass.md) — Draft design document for alternative approach for calendar support.
(**Obsolete;** rejected.)
- [Custom Time Zone Draft](./timezone-draft.md) — Draft design document for custom time zone support in Temporal.
(**Obsolete;** superseded by the documentation of [Temporal.TimeZone](./timezone.md).)

## Object Relationship

<div class="mermaid">
Expand Down
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,8 @@
"codecov:test262": "cd polyfill && npm install && npm run codecov:test262",
"test-cookbook": "cd polyfill && npm install && npm run test-cookbook",
"test262": "cd polyfill && npm install && npm run test262",
"lint": "eslint . --ext js,mjs,.d.ts --max-warnings 0 --cache && npm run tscheck",
"lint": "eslint . --ext js,mjs,.d.ts --max-warnings 0 --cache",
"postlint": "npm run tscheck",
"tscheck": "tsc polyfill/index.d.ts --noEmit --strict --lib ESNext",
"build:polyfill": "cd polyfill && npm install && npm run build",
"build:docs": "cd docs && npm install && npm run build",
Expand Down
2 changes: 1 addition & 1 deletion polyfill/lib/ecmascript.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ export const ES = ObjectAssign({}, ES2019, {
const microsecond = ES.ToInteger(fraction.slice(3, 6));
const nanosecond = ES.ToInteger(fraction.slice(6, 9));
const offsetSign = match[14] === '-' || match[14] === '\u2212' ? '-' : '+';
const offset = `${offsetSign}${match[15]}:${match[16] || '00'}`;
const offset = `${offsetSign}${match[15] || '00'}:${match[16] || '00'}`;
let ianaName = match[17];
if (ianaName) {
try {
Expand Down
1 change: 1 addition & 0 deletions polyfill/lib/timezone.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,7 @@ export class TimeZone {
GetSlot(dateTime, MICROSECOND),
GetSlot(dateTime, NANOSECOND)
);
if (epochNs === null) throw new RangeError('DateTime outside of supported range');
ptomato marked this conversation as resolved.
Show resolved Hide resolved
return [new Absolute(epochNs.minus(offsetNs))];
}

Expand Down
5 changes: 5 additions & 0 deletions polyfill/test/datetime.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -538,6 +538,11 @@ describe('DateTime', () => {
equal(`${dt.toAbsolute('America/Los_Angeles', { disambiguation: 'later' })}`, '2020-03-08T10:30Z');
throws(() => dt.toAbsolute('America/Los_Angeles', { disambiguation: 'reject' }), RangeError);
});
it('outside of Absolute range', () => {
const max = Temporal.DateTime.from('+275760-09-13T23:59:59.999999999');
throws(() => max.toAbsolute('-01:00'), RangeError);
throws(() => max.toAbsolute('America/Godthab'), RangeError);
});
it('throws on bad disambiguation', () => {
['', 'EARLIER', 'xyz', 3, null].forEach((disambiguation) =>
throws(() => DateTime.from('2019-10-29T10:46').toAbsolute('UTC', { disambiguation }), RangeError)
Expand Down
2 changes: 1 addition & 1 deletion polyfill/test/intl.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ describe('Intl', () => {
const us = new Intl.DateTimeFormat('en-US', { timeZone: 'America/New_York' });
const at = new Intl.DateTimeFormat('de-AT', { timeZone: 'Europe/Vienna' });
const t1 = '1976-11-18T14:23:30Z';
const t2 = '2020-02-20T15:44:56-08:00[America/New_York]';
const t2 = '2020-02-20T15:44:56-05:00[America/New_York]';
const start = new Date('1922-12-30'); // ☭
const end = new Date('1991-12-26');

Expand Down
18 changes: 18 additions & 0 deletions polyfill/test/timezone.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -235,6 +235,15 @@ describe('TimeZone', () => {
const tz = Temporal.TimeZone.from('Europe/London');
equal(`${tz.getAbsoluteFor(dt)}`, '+000000-02-29T00:01:15Z');
});
it('outside of Absolute range', () => {
const max = Temporal.DateTime.from('+275760-09-13T23:59:59.999999999');

const offsetTz = Temporal.TimeZone.from('-01:00');
throws(() => offsetTz.getAbsoluteFor(max), RangeError);

const namedTz = Temporal.TimeZone.from('America/Godthab');
throws(() => namedTz.getAbsoluteFor(max), RangeError);
});
});
describe('getAbsoluteFor disambiguation', () => {
const dtm = new Temporal.DateTime(2019, 2, 16, 23, 45);
Expand Down Expand Up @@ -290,6 +299,15 @@ describe('TimeZone', () => {
['2019-02-17T01:45Z', '2019-02-17T02:45Z']
);
});
it('outside of Absolute range', () => {
const max = Temporal.DateTime.from('+275760-09-13T23:59:59.999999999');

const offsetTz = Temporal.TimeZone.from('-01:00');
throws(() => offsetTz.getPossibleAbsolutesFor(max), RangeError);

const namedTz = Temporal.TimeZone.from('America/Godthab');
throws(() => namedTz.getPossibleAbsolutesFor(max), RangeError);
});
});
describe('getNextTransition works as expected', () => {
it('should not have bug #510', () => {
Expand Down
2 changes: 1 addition & 1 deletion spec/absolute.html
Original file line number Diff line number Diff line change
Expand Up @@ -454,7 +454,7 @@ <h1>ParseTemporalAbsolute ( _isoString_ )</h1>
1. Let _possibleAbsolutes_ be ? GetPossibleAbsolutesFor(_timeZone_, _dateTime_).
1. If _possibleAbsolutes_'s length is 1, then
1. Return _possibleAbsolutes_[0].[[Nanoseconds]].
1. <mark>TODO: Disambiguate using _result_.[[TimeZoneOffsetHour]] and _result_.[[TimeZoneOffsetMinute]].</mark>
1. <mark>TODO: Disambiguate using _result_.[[TimeZoneOffsetSign]], _result_.[[TimeZoneOffsetHour]] and _result_.[[TimeZoneOffsetMinute]].</mark>
1. Return <mark>TODO</mark>.
</emu-alg>
</emu-clause>
Expand Down
14 changes: 8 additions & 6 deletions spec/abstractops.html
Original file line number Diff line number Diff line change
Expand Up @@ -518,6 +518,7 @@ <h1>ParseTemporalAbsoluteString ( _isoString_ )</h1>
[[Millisecond]]: _result_.[[Millisecond]],
[[Microsecond]]: _result_.[[Microsecond]],
[[Nanosecond]]: _result_.[[Nanosecond]],
[[TimeZoneOffsetSign]]: _timeZoneResult_.[[OffsetSign]],
[[TimeZoneOffsetHour]]: _timeZoneResult_.[[OffsetHour]],
[[TimeZoneOffsetMinute]]: _timeZoneResult_.[[OffsetMinute]],
[[TimeZoneName]]: _timeZoneResult_.[[Name]]
Expand Down Expand Up @@ -662,9 +663,9 @@ <h1>ParseTemporalTimeZoneString ( _isoString_ )</h1>
1. Let _z_, _sign_, _hour_, _minute_, and _name_ be the parts of _isoString_ produced respectively by the |UTCDesignator|, |TimeZoneUTCOffsetSign|, |TimeZoneUTCOffsetHour|, |TimeZoneUTCOffsetMinute| and |TimeZoneIANAName| productions, or *undefined* if not present.
1. If _z_ is not *undefined*, then
1. Return the new Record: {
[[OffsetSign]]: *undefined*,
[[OffsetHour]]: *undefined*,
[[OffsetMinute]]: *undefined*,
[[OffsetSign]]: 1,
[[OffsetHour]]: +0,
[[OffsetMinute]]: +0,
[[Name]]: `"UTC"`
}.
1. If _hour_ is not *undefined*, then
ptomato marked this conversation as resolved.
Show resolved Hide resolved
Expand All @@ -675,9 +676,10 @@ <h1>ParseTemporalTimeZoneString ( _isoString_ )</h1>
1. Else,
1. Set _sign_ to 1.
1. Set _minute_ to ! ToInteger(_minute_).
1. If _name_ is not *undefined*, then
1. Assert ! IsValidTimeZoneName(_name_).
1. Let _name_ be ! CanonicalizeTimeZoneName(_name_).
1. Let _offsetNanoseconds_ be _sign_ × (_hour_ × 60 + _minute_) × 60 × 10<sup>9</sup>.
1. Let _name_ be ! FormatTimeZoneOffsetString(_offsetNanoseconds_).
1. Assert ! IsValidTimeZoneName(_name_).
1. Let _name_ be ! CanonicalizeTimeZoneName(_name_).
1. Return the new Record: {
[[OffsetSign]]: _sign_,
[[OffsetHour]]: _hour_,
Expand Down
9 changes: 1 addition & 8 deletions spec/timezone.html
Original file line number Diff line number Diff line change
Expand Up @@ -319,14 +319,7 @@ <h1>ParseTemporalTimeZone ( _string_ )</h1>
<emu-alg>
1. Assert: Type(_string_) is String.
1. Let _result_ be ? ParseTemporalTimeZoneString(_string_).
1. If any of _result_.[[OffsetSign]], _result_.[[OffsetHour]], or _result_.[[OffsetMinute]] are *undefined*, then
1. Let _offset_ be *undefined*.
1. Else,
1. Let _offsetNanoseconds_ be _result_.[[OffsetSign]] × (_result_.[[OffsetHour]] × 60 + _result_.[[OffsetMinute]]) × 60 × 10<sup>9</sup>.
1. Let _offset_ be ! FormatTimeZoneOffsetString(_offsetNanoseconds_).
1. Let _identifier_ be the first one of _result_.[[TimeZoneName]], _offset_, or *"UTC"* that is not *undefined*.
1. If ! IsValidTimeZoneName(_identifier_) is *false*, throw a *TypeError* exception.
1. Return ! CanonicalizeTimeZoneName(_identifier_).
1. Return _result_.[[TimeZoneName]].
</emu-alg>
</emu-clause>

Expand Down