Skip to content

Commit

Permalink
Make calendar required in Instant.toDateTime()
Browse files Browse the repository at this point in the history
See: #292
  • Loading branch information
ptomato committed Oct 14, 2020
1 parent 5834941 commit be743d3
Show file tree
Hide file tree
Showing 10 changed files with 67 additions and 52 deletions.
8 changes: 5 additions & 3 deletions docs/cookbook/getLocalizedArrival.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,19 @@
* @param {Temporal.Duration} flightTime - Duration of the flight
* @param {Temporal.TimeZone} destinationTimeZone - Time zone in which the
* flight's destination is located
* @param {Temporal.Calendar|string} calendar - Calendar system used for output
* @returns {Temporal.DateTime} Local arrival time
*/
function getLocalizedArrival(parseableDeparture, flightTime, destinationTimeZone) {
function getLocalizedArrival(parseableDeparture, flightTime, destinationTimeZone, calendar) {
const departure = Temporal.Instant.from(parseableDeparture);
const arrival = departure.add(flightTime);
return arrival.toDateTime(destinationTimeZone);
return arrival.toDateTime(destinationTimeZone, calendar);
}

const arrival = getLocalizedArrival(
'2020-03-08T11:55:00+08:00[Asia/Hong_Kong]',
Temporal.Duration.from({ minutes: 775 }),
'America/Los_Angeles'
'America/Los_Angeles',
'iso8601'
);
assert.equal(arrival.toString(), '2020-03-08T09:50');
3 changes: 2 additions & 1 deletion docs/cookbook/meetingPlanner.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ const timeZones = [
];

// Start the table at midnight local time
const calendarNow = now.toDateTime(here);
const browserCalendar = new Intl.DateTimeFormat().resolvedOptions().calendar;
const calendarNow = now.toDateTime(here, browserCalendar);
const startTime = calendarNow
.with(Temporal.Time.from('00:00')) // midnight
.toInstant(here);
Expand Down
52 changes: 30 additions & 22 deletions docs/instant.md
Original file line number Diff line number Diff line change
Expand Up @@ -225,13 +225,12 @@ Same as `getEpochSeconds()`, but with nanosecond (10<sup>&minus;9</sup> second)

The value returned from this method is suitable to be passed to `new Temporal.Instant()`.

### instant.**toZonedDateTime**(_timeZone_: object | string, _calendar_?: object | string) : Temporal.ZonedDateTime
### instant.**toZonedDateTime**(_timeZone_: object | string, _calendar_: object | string) : Temporal.ZonedDateTime

**Parameters:**

- `timeZone` (object or string): A `Temporal.TimeZone` object, or an object implementing the [time zone protocol](./timezone.md#protocol), or a string description of the time zone; either its IANA name or UTC offset.
- `calendar` (optional object or string): A `Temporal.Calendar` object, or a plain object, or a calendar identifier.
The default is to use the ISO 8601 calendar.
- `calendar` (object or string): A `Temporal.Calendar` object, or a plain object, or a calendar identifier.

**Returns:** a `Temporal.ZonedDateTime` object representing the calendar date, wall-clock time, time zone offset, and `timeZone`, according to the reckoning of `calendar`, at the exact time indicated by `instant`.

Expand All @@ -240,28 +239,32 @@ A convenient list is also available [on Wikipedia](https://en.wikipedia.org/wiki

For a list of calendar identifiers, see the documentation for [Intl.DateTimeFormat](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/DateTimeFormat/DateTimeFormat#Parameters).

If you only want to use the ISO 8601 calendar, use `toDateTimeISO()`.

Example usage:

```js
// Converting a specific exact time to a calendar date / wall-clock time
timestamp = Temporal.Instant.fromEpochSeconds(1553993100);
timestamp.toDateTime('Europe/Berlin'); // => 2019-03-31T01:45+02:00[Europe/Berlin]
timestamp.toDateTime('UTC'); // => 2019-03-31T00:45+00:00[UTC]
timestamp.toDateTime('-08:00'); // => 2019-03-30T16:45-08:00[-08:00]

// What time was the Unix epoch (timestamp 0) in Bell Labs (Murray Hill, New Jersey, USA)?
// What time was the Unix epoch (timestamp 0) in Bell Labs (Murray Hill, New Jersey, USA) in the Gregorian calendar?
epoch = Temporal.Instant.fromEpochSeconds(0);
tz = Temporal.TimeZone.from('America/New_York');
epoch.toZonedDateTime(tz); // => 1969-12-31T19:00-05:00[America/New_York]
epoch.toZonedDateTime(tz, 'gregory');
// => 1969-12-31T19:00-05:00[America/New_York][c=gregory]

// What time was the Unix epoch in Tokyo in the Japanese calendar?
tz = Temporal.TimeZone.from('Asia/Tokyo');
cal = Temporal.Calendar.from('japanese');
zdt = epoch.toZonedDateTime(tz, cal);
// => 1970-01-01T09:00+09:00[Asia/Tokyo][c=japanese]
console.log(zdt.year, zdt.era);
// => 45 showa
```

### instant.**toDateTime**(_timeZone_: object | string, _calendar_?: object | string) : Temporal.DateTime
### instant.**toDateTime**(_timeZone_: object | string, _calendar_: object | string) : Temporal.DateTime

**Parameters:**

- `timeZone` (object or string): A `Temporal.TimeZone` object, or an object implementing the [time zone protocol](./timezone.md#protocol), or a string description of the time zone; either its IANA name or UTC offset.
- `calendar` (optional object or string): A `Temporal.Calendar` object, or a plain object, or a calendar identifier.
The default is to use the ISO 8601 calendar.
- `calendar` (object or string): A `Temporal.Calendar` object, or a plain object, or a calendar identifier.

**Returns:** a `Temporal.DateTime` object indicating the calendar date and wall-clock time in `timeZone`, according to the reckoning of `calendar`, at the instant time indicated by `instant`.

Expand All @@ -272,19 +275,24 @@ For a list of calendar identifiers, see the documentation for [Intl.DateTimeForm

This method is one way to convert a `Temporal.Instant` to a `Temporal.DateTime`.

If you only want to use the ISO 8601 calendar, use `toDateTimeISO()`.

Example usage:

```js
// Converting a specific instant time to a calendar date / wall-clock time
timestamp = Temporal.Instant.fromEpochSeconds(1553993100);
timestamp.toDateTime('Europe/Berlin'); // => 2019-03-31T01:45
timestamp.toDateTime('UTC'); // => 2019-03-31T00:45
timestamp.toDateTime('-08:00'); // => 2019-03-30T16:45

// What time was the Unix epoch (timestamp 0) in Bell Labs (Murray Hill, New Jersey, USA)?
// What time was the Unix epoch (timestamp 0) in Bell Labs (Murray Hill, New Jersey, USA) in the Gregorian calendar?
epoch = Temporal.Instant.fromEpochSeconds(0);
tz = Temporal.TimeZone.from('America/New_York');
epoch.toDateTime(tz); // => 1969-12-31T19:00
epoch.toDateTime(tz, 'gregory');
// => 1969-12-31T19:00[c=gregory]

// What time was the Unix epoch in Tokyo in the Japanese calendar?
tz = Temporal.TimeZone.from('Asia/Tokyo');
cal = Temporal.Calendar.from('japanese');
dt = epoch.toDateTime(tz, cal);
// => 1970-01-01T09:00[c=japanese]
console.log(dt.year, dt.era);
// => 45 showa
```

### instant.**add**(_duration_: object) : Temporal.Instant
Expand Down
2 changes: 1 addition & 1 deletion polyfill/lib/instant.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -235,7 +235,7 @@ export class Instant {
valueOf() {
throw new TypeError('use compare() or equals() to compare Temporal.Instant');
}
toDateTime(temporalTimeZoneLike, calendarLike = GetDefaultCalendar()) {
toDateTime(temporalTimeZoneLike, calendarLike) {
if (!ES.IsTemporalInstant(this)) throw new TypeError('invalid receiver');
const timeZone = ES.ToTemporalTimeZone(temporalTimeZoneLike);
const calendar = ES.ToTemporalCalendar(calendarLike);
Expand Down
2 changes: 1 addition & 1 deletion polyfill/test/Instant/prototype/toDateTime/length.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ includes: [propertyHelper.js]
---*/

verifyProperty(Temporal.Instant.prototype.toDateTime, "length", {
value: 1,
value: 2,
writable: false,
enumerable: false,
configurable: true,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ const expected = [

const instant = Temporal.Instant.from("1975-02-02T14:25:36.123456789Z");
const dateTime = Temporal.DateTime.from("1963-07-02T12:00:00.987654321");
const calendar = Temporal.Calendar.from("iso8601");
const timeZone = new Proxy({
getDateTimeFor(instantArg) {
actual.push("call timeZone.getDateTimeFor");
Expand All @@ -31,7 +32,7 @@ const timeZone = new Proxy({
},
});

const result = instant.toDateTime(timeZone);
const result = instant.toDateTime(timeZone, calendar);
assert.sameValue(result, dateTime);

assert.compareArray(actual, expected);
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ esid: sec-temporal.instant.prototype.todatetime
---*/

const instant = Temporal.Instant.from("1975-02-02T14:25:36.123456789Z");
const calendar = Temporal.Calendar.from("iso8601");

const invalidValues = [
undefined,
Expand All @@ -22,14 +23,14 @@ const invalidValues = [

for (const dateTime of invalidValues) {
const timeZone = {
getDateTimeFor(instantArg, calendar) {
getDateTimeFor(instantArg, calendarArg) {
assert.sameValue(instantArg instanceof Temporal.Instant, true, "Instant");
assert.sameValue(instantArg, instant);
assert.sameValue(calendar instanceof Temporal.Calendar, true, "Calendar");
assert.sameValue(calendar.id, "iso8601");
assert.sameValue(calendarArg instanceof Temporal.Calendar, true, "Calendar");
assert.sameValue(calendarArg, calendar);
return dateTime;
},
};

assert.throws(TypeError, () => instant.toDateTime(timeZone));
assert.throws(TypeError, () => instant.toDateTime(timeZone, calendar));
}
25 changes: 15 additions & 10 deletions polyfill/test/instant.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,9 @@ describe('Instant', () => {
it('Instant.prototype.round is a Function', () => {
equal(typeof Instant.prototype.round, 'function');
});
it('Instant.prototype.toDateTime is a Function', () => {
equal(typeof Instant.prototype.toDateTime, 'function');
});
});
it('Instant.fromEpochSeconds is a Function', () => {
equal(typeof Instant.fromEpochSeconds, 'function');
Expand Down Expand Up @@ -870,22 +873,24 @@ describe('Instant', () => {
});
});
describe('Instant.toDateTime works', () => {
const iso = '1976-11-18T14:23:30.123456789Z';
const abs = Instant.from(iso);
it('without parameter', () => {
throws(() => abs.toDateTime(), RangeError);
const inst = Instant.from('1976-11-18T14:23:30.123456789Z');
it('throws without parameter', () => {
throws(() => inst.toDateTime(), RangeError);
});
it('throws with only one parameter', () => {
throws(() => inst.toDateTime('Asia/Singapore'));
});
it('time zone parameter UTC', () => {
const tz = Temporal.TimeZone.from('UTC');
const dt = abs.toDateTime(tz);
equal(abs.getEpochNanoseconds(), dt.toInstant(tz).getEpochNanoseconds());
equal(`${dt}`, '1976-11-18T14:23:30.123456789');
const dt = inst.toDateTime(tz, 'gregory');
equal(inst.getEpochNanoseconds(), dt.toInstant(tz).getEpochNanoseconds());
equal(`${dt}`, '1976-11-18T14:23:30.123456789[c=gregory]');
});
it('time zone parameter non-UTC', () => {
const tz = Temporal.TimeZone.from('America/New_York');
const dt = abs.toDateTime(tz);
equal(abs.getEpochNanoseconds(), dt.toInstant(tz).getEpochNanoseconds());
equal(`${dt}`, '1976-11-18T09:23:30.123456789');
const dt = inst.toDateTime(tz, 'gregory');
equal(inst.getEpochNanoseconds(), dt.toInstant(tz).getEpochNanoseconds());
equal(`${dt}`, '1976-11-18T09:23:30.123456789[c=gregory]');
});
});
});
Expand Down
8 changes: 4 additions & 4 deletions polyfill/test/usertimezone.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ describe('Userland time zone', () => {
it('has offset string +00:00', () => equal(obj.getOffsetStringFor(abs), '+00:00'));
it('converts to DateTime', () => {
equal(`${obj.getDateTimeFor(abs)}`, '1970-01-01T00:00');
equal(`${abs.toDateTime(obj)}`, '1970-01-01T00:00');
equal(`${abs.toDateTime(obj, 'gregory')}`, '1970-01-01T00:00[c=gregory]');
});
it('converts to Instant', () => {
equal(`${obj.getInstantFor(dt)}`, '1976-11-18T15:23:30.123456789Z');
Expand Down Expand Up @@ -103,7 +103,7 @@ describe('Userland time zone', () => {
});
it('works for Instant.toDateTime', () => {
const abs = Temporal.Instant.fromEpochSeconds(0);
equal(`${abs.toDateTime('Etc/Custom_UTC_Subclass')}`, '1970-01-01T00:00');
equal(`${abs.toDateTime('Etc/Custom_UTC_Subclass', 'gregory')}`, '1970-01-01T00:00[c=gregory]');
});
it('works for DateTime.toInstant', () => {
const dt = Temporal.DateTime.from('1970-01-01T00:00');
Expand Down Expand Up @@ -145,7 +145,7 @@ describe('Userland time zone', () => {
equal(Temporal.TimeZone.prototype.getOffsetStringFor.call(obj, abs), '+00:00'));
it('converts to DateTime', () => {
equal(`${Temporal.TimeZone.prototype.getDateTimeFor.call(obj, abs)}`, '1970-01-01T00:00');
equal(`${abs.toDateTime(obj)}`, '1970-01-01T00:00');
equal(`${abs.toDateTime(obj, 'gregory')}`, '1970-01-01T00:00[c=gregory]');
});
it('converts to Instant', () => {
equal(`${Temporal.TimeZone.prototype.getInstantFor.call(obj, dt)}`, '1976-11-18T15:23:30.123456789Z');
Expand Down Expand Up @@ -193,7 +193,7 @@ describe('Userland time zone', () => {
});
it('works for Instant.toDateTime', () => {
const abs = Temporal.Instant.fromEpochSeconds(0);
equal(`${abs.toDateTime('Etc/Custom_UTC_Protocol')}`, '1970-01-01T00:00');
equal(`${abs.toDateTime('Etc/Custom_UTC_Protocol', 'gregory')}`, '1970-01-01T00:00[c=gregory]');
});
it('works for DateTime.toInstant', () => {
const dt = Temporal.DateTime.from('1970-01-01T00:00');
Expand Down
7 changes: 2 additions & 5 deletions spec/instant.html
Original file line number Diff line number Diff line change
Expand Up @@ -429,7 +429,7 @@ <h1>Temporal.Instant.prototype.valueOf ( )</h1>
</emu-clause>

<emu-clause id="sec-temporal.instant.prototype.todatetime">
<h1>Temporal.Instant.prototype.toDateTime ( _temporalTimeZoneLike_ [ , _calendarLike_ ] )</h1>
<h1>Temporal.Instant.prototype.toDateTime ( _temporalTimeZoneLike_, _calendarLike_ )</h1>
<p>
The `toDateTime` method takes two arguments, _temporalTimeZoneLike_ and _calendar_.
The following steps are taken:
Expand All @@ -438,10 +438,7 @@ <h1>Temporal.Instant.prototype.toDateTime ( _temporalTimeZoneLike_ [ , _calendar
1. Let _instant_ be the *this* value.
1. Perform ? RequireInternalSlot(_instant_, [[InitializedTemporalInstant]]).
1. Let _timeZone_ be ? ToTemporalTimeZone(_temporalTimeZoneLike_).
1. If _calendarLike_ is *undefined*, then
1. Let _calendar_ be ! GetDefaultCalendar().
1. Else,
1. Let _calendar_ be ? ToTemporalCalendar(_calendarLike_).
1. Let _calendar_ be ? ToTemporalCalendar(_calendarLike_).
1. Return ? GetTemporalDateTimeFor(_timeZone_, _instant_, _calendar_).
</emu-alg>
</emu-clause>
Expand Down

0 comments on commit be743d3

Please sign in to comment.