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

Date/Time.toZonedDateTime #1129

Merged
merged 2 commits into from
Nov 5, 2020
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
35 changes: 28 additions & 7 deletions polyfill/lib/plaindate.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -329,17 +329,26 @@ export class PlainDate {
const calendar = ES.ConsolidateCalendars(dateCalendar, timeCalendar);
return new DateTime(year, month, day, hour, minute, second, millisecond, microsecond, nanosecond, calendar);
}
toZonedDateTime(timeZoneLike, temporalTime = undefined, options = undefined) {
toZonedDateTime(item) {
if (!ES.IsTemporalDate(this)) throw new TypeError('invalid receiver');
const timeZone = ES.ToTemporalTimeZone(timeZoneLike);
options = ES.NormalizeOptionsObject(options);
const disambiguation = ES.ToTemporalDisambiguation(options);

let timeZone, temporalTime;
if (ES.Type(item) === 'Object') {
let timeZoneLike = item.timeZone;
if (timeZoneLike === undefined) {
timeZone = ES.ToTemporalTimeZone(item);
} else {
timeZone = ES.ToTemporalTimeZone(timeZoneLike);
temporalTime = item.time;
}
} else {
timeZone = ES.ToTemporalTimeZone(item);
}

const year = GetSlot(this, ISO_YEAR);
const month = GetSlot(this, ISO_MONTH);
const day = GetSlot(this, ISO_DAY);
const calendar = GetSlot(this, CALENDAR);
const DateTime = GetIntrinsic('%Temporal.PlainDateTime%');

let hour = 0,
minute = 0,
Expand All @@ -357,8 +366,20 @@ export class PlainDate {
nanosecond = GetSlot(temporalTime, ISO_NANOSECOND);
}

const dt = new DateTime(year, month, day, hour, minute, second, millisecond, microsecond, nanosecond, calendar);
const instant = ES.GetTemporalInstantFor(timeZone, dt, disambiguation);
const PlainDateTime = GetIntrinsic('%Temporal.PlainDateTime%');
const dt = new PlainDateTime(
year,
month,
day,
hour,
minute,
second,
millisecond,
microsecond,
nanosecond,
calendar
);
const instant = ES.GetTemporalInstantFor(timeZone, dt, 'compatible');
const ZonedDateTime = GetIntrinsic('%Temporal.ZonedDateTime%');
return new ZonedDateTime(GetSlot(instant, EPOCHNANOSECONDS), timeZone, calendar);
}
Expand Down
37 changes: 30 additions & 7 deletions polyfill/lib/plaintime.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -399,12 +399,24 @@ export class PlainTime {
const DateTime = GetIntrinsic('%Temporal.PlainDateTime%');
return new DateTime(year, month, day, hour, minute, second, millisecond, microsecond, nanosecond, calendar);
}
toZonedDateTime(timeZoneLike, temporalDate, options = undefined) {
toZonedDateTime(item) {
if (!ES.IsTemporalTime(this)) throw new TypeError('invalid receiver');

if (ES.Type(item) !== 'Object') {
throw new TypeError('invalid argument');
}

const dateLike = item.date;
if (dateLike === undefined) {
throw new TypeError('missing date property');
}
const temporalDate = ES.ToTemporalDate(dateLike, GetIntrinsic('%Temporal.PlainDate%'));

const timeZoneLike = item.timeZone;
if (timeZoneLike === undefined) {
throw new TypeError('missing timeZone property');
}
const timeZone = ES.ToTemporalTimeZone(timeZoneLike);
temporalDate = ES.ToTemporalDate(temporalDate, GetIntrinsic('%Temporal.PlainDate%'));
options = ES.NormalizeOptionsObject(options);
const disambiguation = ES.ToTemporalDisambiguation(options);

const year = GetSlot(temporalDate, ISO_YEAR);
const month = GetSlot(temporalDate, ISO_MONTH);
Expand All @@ -416,10 +428,21 @@ export class PlainTime {
const millisecond = GetSlot(this, ISO_MILLISECOND);
const microsecond = GetSlot(this, ISO_MICROSECOND);
const nanosecond = GetSlot(this, ISO_NANOSECOND);
const DateTime = GetIntrinsic('%Temporal.PlainDateTime%');

const dt = new DateTime(year, month, day, hour, minute, second, millisecond, microsecond, nanosecond, calendar);
const instant = ES.GetTemporalInstantFor(timeZone, dt, disambiguation);
const PlainDateTime = GetIntrinsic('%Temporal.PlainDateTime%');
const dt = new PlainDateTime(
year,
month,
day,
hour,
minute,
second,
millisecond,
microsecond,
nanosecond,
calendar
);
const instant = ES.GetTemporalInstantFor(timeZone, dt, 'compatible');
const ZonedDateTime = GetIntrinsic('%Temporal.ZonedDateTime%');
return new ZonedDateTime(GetSlot(instant, EPOCHNANOSECONDS), timeZone, calendar);
}
Expand Down
42 changes: 13 additions & 29 deletions polyfill/test/plaindate.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -208,49 +208,33 @@ describe('Date', () => {
const date = PlainDate.from('2020-01-01');
const time = Temporal.PlainTime.from('12:00');
const tz = Temporal.TimeZone.from('America/Los_Angeles');
equal(`${date.toZonedDateTime(tz, time)}`, '2020-01-01T12:00:00-08:00[America/Los_Angeles]');
const zdt = date.toZonedDateTime({ timeZone: tz, time });
equal(`${zdt}`, '2020-01-01T12:00:00-08:00[America/Los_Angeles]');
});
it('works with time omitted', () => {
it('works with time omitted (timeZone argument)', () => {
const date = PlainDate.from('2020-01-01');
const tz = Temporal.TimeZone.from('America/Los_Angeles');
equal(`${date.toZonedDateTime(tz)}`, '2020-01-01T00:00:00-08:00[America/Los_Angeles]');
const zdt = date.toZonedDateTime(tz);
equal(`${zdt}`, '2020-01-01T00:00:00-08:00[America/Los_Angeles]');
});
it('works with disambiguation option', () => {
const date = PlainDate.from('2020-03-08');
const time = Temporal.PlainTime.from('02:00');
it('works with time omitted (timeZone property)', () => {
const date = PlainDate.from('2020-01-01');
const tz = Temporal.TimeZone.from('America/Los_Angeles');
const zdt = date.toZonedDateTime(tz, time, { disambiguation: 'earlier' });
equal(`${zdt}`, '2020-03-08T01:00:00-08:00[America/Los_Angeles]');
const zdt = date.toZonedDateTime({ timeZone: tz });
equal(`${zdt}`, '2020-01-01T00:00:00-08:00[America/Los_Angeles]');
});
it('casts first argument', () => {
it('casts timeZone property', () => {
const date = PlainDate.from('2020-07-08');
const time = Temporal.PlainTime.from('12:00');
const zdt = date.toZonedDateTime('America/Los_Angeles', time);
const zdt = date.toZonedDateTime({ timeZone: 'America/Los_Angeles', time });
equal(`${zdt}`, '2020-07-08T12:00:00-07:00[America/Los_Angeles]');
});
it('casts second argument', () => {
it('casts time property', () => {
const date = PlainDate.from('2020-07-08');
const tz = Temporal.TimeZone.from('America/Los_Angeles');
const zdt = date.toZonedDateTime(tz, '12:00');
const zdt = date.toZonedDateTime({ timeZone: tz, time: '12:00' });
equal(`${zdt}`, '2020-07-08T12:00:00-07:00[America/Los_Angeles]');
});
it('throws on bad disambiguation', () => {
['', 'EARLIER', 'xyz', 3, null].forEach((disambiguation) =>
throws(() => PlainDate.from('2019-10-29').toZonedDateTime('UTC', '12:00', { disambiguation }), RangeError)
);
});
it('options may only be an object or undefined', () => {
const date = PlainDate.from('2019-10-29');
[null, 1, 'hello', true, Symbol('foo'), 1n].forEach((badOptions) =>
throws(() => date.toZonedDateTime('America/Sao_Paulo', '10:46:38', badOptions), TypeError)
);
[{}, () => {}, undefined].forEach((options) =>
equal(
`${date.toZonedDateTime('America/Sao_Paulo', '10:46:38', options)}`,
'2019-10-29T10:46:38-03:00[America/Sao_Paulo]'
)
);
});
});
describe('date.until() works', () => {
const date = new PlainDate(1969, 7, 24);
Expand Down
35 changes: 6 additions & 29 deletions polyfill/test/plaintime.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -268,44 +268,21 @@ describe('Time', () => {
const time = PlainTime.from('12:00');
const date = Temporal.PlainDate.from('2020-01-01');
const tz = Temporal.TimeZone.from('America/Los_Angeles');
equal(`${time.toZonedDateTime(tz, date)}`, '2020-01-01T12:00:00-08:00[America/Los_Angeles]');
const zdt = time.toZonedDateTime({ timeZone: tz, date });
equal(`${zdt}`, '2020-01-01T12:00:00-08:00[America/Los_Angeles]');
});
it('works with disambiguation option', () => {
const time = PlainTime.from('02:00');
const date = Temporal.PlainDate.from('2020-03-08');
const tz = Temporal.TimeZone.from('America/Los_Angeles');
const zdt = time.toZonedDateTime(tz, date, { disambiguation: 'earlier' });
equal(`${zdt}`, '2020-03-08T01:00:00-08:00[America/Los_Angeles]');
});
it('casts first argument', () => {
it('casts timeZone property', () => {
const time = PlainTime.from('12:00');
const date = Temporal.PlainDate.from('2020-07-08');
const zdt = time.toZonedDateTime('America/Los_Angeles', date);
const zdt = time.toZonedDateTime({ timeZone: 'America/Los_Angeles', date });
equal(`${zdt}`, '2020-07-08T12:00:00-07:00[America/Los_Angeles]');
});
it('casts second argument', () => {
it('casts date property', () => {
const time = PlainTime.from('12:00');
const tz = Temporal.TimeZone.from('America/Los_Angeles');
const zdt = time.toZonedDateTime(tz, '2020-07-08');
const zdt = time.toZonedDateTime({ timeZone: tz, date: '2020-07-08' });
equal(`${zdt}`, '2020-07-08T12:00:00-07:00[America/Los_Angeles]');
});
it('throws on bad disambiguation', () => {
['', 'EARLIER', 'xyz', 3, null].forEach((disambiguation) =>
throws(() => PlainTime.from('12:00').toZonedDateTime('UTC', '2019-10-29', { disambiguation }), RangeError)
);
});
it('options may only be an object or undefined', () => {
const time = PlainTime.from('10:46:38');
[null, 1, 'hello', true, Symbol('foo'), 1n].forEach((badOptions) =>
throws(() => time.toZonedDateTime('America/Sao_Paulo', '2019-10-29', badOptions), TypeError)
);
[{}, () => {}, undefined].forEach((options) =>
equal(
`${time.toZonedDateTime('America/Sao_Paulo', '2019-10-29', options)}`,
'2019-10-29T10:46:38-03:00[America/Sao_Paulo]'
)
);
});
});
describe('time.until() works', () => {
const time = new PlainTime(15, 23, 30, 123, 456, 789);
Expand Down
22 changes: 16 additions & 6 deletions spec/plaindate.html
Original file line number Diff line number Diff line change
Expand Up @@ -523,23 +523,33 @@ <h1>Temporal.PlainDate.prototype.toPlainDateTime ( [ _temporalTime_ ] )</h1>
</emu-clause>

<emu-clause id="sec-temporal.date.prototype.tozoneddatetime">
<h1>Temporal.PlainDate.prototype.toZonedDateTime ( _timeZoneLike_ [ , _temporalTime_ [ , _options_ ] ] )</h1>
<h1>Temporal.PlainDate.prototype.toZonedDateTime ( _item_ )</h1>
<p>
The `toZonedDateTime` method takes three arguments, _timeZoneLike_, _temporalTime_, and _options_.
The `toZonedDateTime` method takes one argument _item_.
The following steps are taken:
</p>
<emu-alg>
1. Let _temporalDate_ be the *this* value.
1. Perform ? RequireInternalSlot(_temporalDate_, [[InitializedTemporalDate]]).
1. Let _timeZone_ be ? ToTemporalTimeZone(_temporalTimeZoneLike_).
1. Set _options_ to ? NormalizeOptionsObject(_options_).
1. Let _disambiguation_ be ? ToTemporalDisambiguation(_options_).
1. If Type(_item_) is Object, then
1. Let _timeZoneLike_ be ? Get(_item_, *"timeZone"*).
1. If _timeZoneLike_ is *undefined*, then
<!-- Treat _item_ itself as a TimeZone -->
1. Let _timeZone_ be ? ToTemporalTimeZone(_item_).
1. Let _temporalTime_ be *undefined*.
1. Else,
<!-- Treat _item_ as a property bag -->
1. Let _timeZone_ be ? ToTemporalTimeZone(_timeZoneLike_).
1. Let _temporalTime_ be ? Get(_item_, *"time"*).
1. Else,
1. Let _timeZone_ be ? ToTemporalTimeZone(_item_).
1. Let _temporalTime_ be *undefined*.
1. If _temporalTime_ is *undefined*, then
1. Let _temporalDateTime_ be ? CreateTemporalDateTime(_temporalDate_.[[ISOYear]], _temporalDate_.[[ISOMonth]], _temporalDate_.[[ISODay]], 0, 0, 0, 0, 0, 0, _temporalDate_.[[Calendar]]).
1. Else,
1. Set _temporalTime_ to ? ToTemporalTime(_temporalTime_).
1. Let _temporalDateTime_ be ? CreateTemporalDateTime(_temporalDate_.[[ISOYear]], _temporalDate_.[[ISOMonth]], _temporalDate_.[[ISODay]], _temporalTime_.[[Hour]], _temporalTime_.[[Minute]], _temporalTime_.[[Second]], _temporalTime_.[[Millisecond]], _temporalTime_.[[Microsecond]], _temporalTime_.[[Nanosecond]], _temporalDate_.[[Calendar]]).
1. Let _instant_ be ? GetTemporalInstantFor(_timeZone_, _temporalDateTime_, _disambiguation_).
1. Let _instant_ be ? GetTemporalInstantFor(_timeZone_, _temporalDateTime_, *"compatible"*).
1. Return ? CreateTemporalZonedDateTime(_instant_.[[Nanoseconds]], _timeZone_, _temporalDate_.[[Calendar]]).
</emu-alg>
</emu-clause>
Expand Down
16 changes: 10 additions & 6 deletions spec/plaintime.html
Original file line number Diff line number Diff line change
Expand Up @@ -404,20 +404,24 @@ <h1>Temporal.PlainTime.prototype.toPlainDateTime ( _temporalDate_ )</h1>
</emu-clause>

<emu-clause id="sec-temporal.time.prototype.tozoneddatetime">
<h1>Temporal.PlainTime.prototype.toZonedDateTime ( _timeZoneLike_, _temporalDate_ [ , _options_ ] )</h1>
<h1>Temporal.PlainTime.prototype.toZonedDateTime ( _item_ )</h1>
<p>
The `toZonedDateTime` method takes three arguments, _timeZoneLike_, _temporalDate_, and _options_.
The `toZonedDateTime` method takes one argument _item_.
The following steps are taken:
</p>
<emu-alg>
1. Let _temporalTime_ be the *this* value.
1. Perform ? RequireInternalSlot(_temporalTime_, [[InitializedTemporalTime]]).
1. Let _temporalDateLike_ be ? Get(_item_, *"date"*).
1. If _temporalDateLike_ is *undefined*, then
1. Throw a *TypeError* exception.
1. Let _temporalDate_ to ? ToTemporalTime(_temporalDateLike_).
1. Let _temporalTimeZoneLike_ be ? Get(_item_, *"timeZone"*).
1. If _temporalTimeZoneLike_ is *undefined*, then
1. Throw a *TypeError* exception.
1. Let _timeZone_ be ? ToTemporalTimeZone(_temporalTimeZoneLike_).
1. Set _temporalDate_ to ? ToTemporalTime(_temporalDate_).
1. Set _options_ to ? NormalizeOptionsObject(_options_).
1. Let _disambiguation_ be ? ToTemporalDisambiguation(_options_).
1. Let _temporalDateTime_ be ? CreateTemporalDateTime(_temporalDate_.[[ISOYear]], _temporalDate_.[[ISOMonth]], _temporalDate_.[[ISODay]], _temporalTime_.[[Hour]], _temporalTime_.[[Minute]], _temporalTime_.[[Second]], _temporalTime_.[[Millisecond]], _temporalTime_.[[Microsecond]], _temporalTime_.[[Nanosecond]], _temporalDate_.[[Calendar]]).
1. Let _instant_ be ? GetTemporalInstantFor(_timeZone_, _temporalDateTime_, _disambiguation_).
1. Let _instant_ be ? GetTemporalInstantFor(_timeZone_, _temporalDateTime_, *"compatible"*).
1. Return ? CreateTemporalZonedDateTime(_instant_.[[Nanoseconds]], _timeZone_, _temporalDate_.[[Calendar]]).
</emu-alg>
</emu-clause>
Expand Down