Skip to content

Commit

Permalink
Enable parsing of strings without offsets per tc39#933
Browse files Browse the repository at this point in the history
  • Loading branch information
justingrant committed Oct 21, 2020
1 parent 8777de8 commit 5511474
Show file tree
Hide file tree
Showing 5 changed files with 46 additions and 10 deletions.
8 changes: 8 additions & 0 deletions polyfill/lib/poc/ZonedDateTime.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,14 @@ describe('ZonedDateTime', () => {
const zdt = Temporal.ZonedDateTime.from('2020-03-08T01:00-08:00[America/Los_Angeles]');
equal(zdt.toString(), '2020-03-08T01:00-08:00[America/Los_Angeles]');
});
it('parses with an IANA zone but no offset', () => {
const zdt = Temporal.ZonedDateTime.from('2020-03-08T01:00[America/Los_Angeles]');
equal(zdt.toString(), '2020-03-08T01:00-08:00[America/Los_Angeles]');
});
it('parses with an IANA zone but no offset (with disambiguation)', () => {
const zdt = Temporal.ZonedDateTime.from('2020-03-08T02:30[America/Los_Angeles]', { disambiguation: 'earlier' });
equal(zdt.toString(), '2020-03-08T01:30-08:00[America/Los_Angeles]');
});
it('parses with an offset in brackets', () => {
const zdt = Temporal.ZonedDateTime.from('2020-03-08T01:00-08:00[-08:00]');
equal(zdt.toString(), '2020-03-08T01:00-08:00[-08:00]');
Expand Down
13 changes: 11 additions & 2 deletions polyfill/lib/poc/ZonedDateTime.ts
Original file line number Diff line number Diff line change
Expand Up @@ -119,9 +119,18 @@ function fromIsoString(isoString: string, options?: ZonedDateTimeAssignmentOptio
// > time zone. (So you can't tell what the local time will be one minute
// > later, for example.)
const isZ = absString.trimEnd().toUpperCase().endsWith('Z');
const abs = Temporal.Instant.from(absString);
let abs: Temporal.Instant;
let ignoreOffsetOption = isZ;
try {
abs = Temporal.Instant.from(absString);
} catch (e) {
// presumably, parsing to Instant failed because offset is missing,
// so we'll just infer the offset from the time zone.
abs = dt.toInstant(tz, { disambiguation });
ignoreOffsetOption = true;
}
const offsetNs = dt.difference(abs.toDateTime('UTC', dt.calendar), { largestUnit: 'nanoseconds' }).nanoseconds;
return fromCommon(dt.withCalendar(cal), tz, offsetNs, disambiguation, isZ ? 'use' : offsetOption);
return fromCommon(dt.withCalendar(cal), tz, offsetNs, disambiguation, ignoreOffsetOption ? 'use' : offsetOption);
}

/** Shared logic for the object and string forms of `from` */
Expand Down
13 changes: 11 additions & 2 deletions polyfill/lib/zoneddatetime.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -79,9 +79,18 @@ function fromIsoString(isoString, options) {
// > time zone. (So you can't tell what the local time will be one minute
// > later, for example.)
const isZ = absString.trimEnd().toUpperCase().endsWith('Z');
const abs = Temporal.Instant.from(absString);
let abs;
let ignoreOffsetOption = isZ;
try {
abs = Temporal.Instant.from(absString);
} catch (e) {
// presumably, parsing to Instant failed because offset is missing,
// so we'll just infer the offset from the time zone.
abs = dt.toInstant(tz, { disambiguation });
ignoreOffsetOption = true;
}
const offsetNs = dt.difference(abs.toDateTime('UTC', dt.calendar), { largestUnit: 'nanoseconds' }).nanoseconds;
return fromCommon(dt.withCalendar(cal), tz, offsetNs, disambiguation, isZ ? 'use' : offsetOption);
return fromCommon(dt.withCalendar(cal), tz, offsetNs, disambiguation, ignoreOffsetOption ? 'use' : offsetOption);
}

/** Shared logic for the object and string forms of `from` */
Expand Down
14 changes: 8 additions & 6 deletions polyfill/poc.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -348,6 +348,7 @@ export namespace Temporal {

export interface CalendarProtocol {
id: string;
calendar?: never;
year(date: Temporal.Date): number;
month(date: Temporal.Date): number;
day(date: Temporal.Date): number;
Expand Down Expand Up @@ -410,7 +411,7 @@ export namespace Temporal {
*
* See https://tc39.es/proposal-temporal/docs/calendar.html for more details.
*/
export class Calendar implements Required<CalendarProtocol> {
export class Calendar implements Omit<Required<CalendarProtocol>, 'calendar'> {
static from(item: CalendarProtocol | string): Temporal.Calendar;
constructor(calendarIdentifier: string);
readonly id: string;
Expand Down Expand Up @@ -519,7 +520,7 @@ export namespace Temporal {
readonly monthsInYear: number;
readonly isLeapYear: boolean;
equals(other: Temporal.Date): boolean;
with(dateLike: DateLike, options?: AssignmentOptions): Temporal.Date;
with(dateLike: DateLike | string, options?: AssignmentOptions): Temporal.Date;
withCalendar(calendar: CalendarProtocol | string): Temporal.Date;
add(durationLike: Temporal.Duration | DurationLike, options?: ArithmeticOptions): Temporal.Date;
subtract(durationLike: Temporal.Duration | DurationLike, options?: ArithmeticOptions): Temporal.Date;
Expand Down Expand Up @@ -636,7 +637,7 @@ export namespace Temporal {
readonly monthsInYear: number;
readonly isLeapYear: boolean;
equals(other: Temporal.DateTime): boolean;
with(dateTimeLike: DateTimeLike, options?: AssignmentOptions): Temporal.DateTime;
with(dateTimeLike: DateTimeLike | string, options?: AssignmentOptions): Temporal.DateTime;
withCalendar(calendar: CalendarProtocol | string): Temporal.DateTime;
add(durationLike: Temporal.Duration | DurationLike, options?: ArithmeticOptions): Temporal.DateTime;
subtract(durationLike: Temporal.Duration | DurationLike, options?: ArithmeticOptions): Temporal.DateTime;
Expand Down Expand Up @@ -781,7 +782,7 @@ export namespace Temporal {
readonly microsecond: number;
readonly nanosecond: number;
equals(other: Temporal.Time): boolean;
with(timeLike: Temporal.Time | TimeLike, options?: AssignmentOptions): Temporal.Time;
with(timeLike: TimeLike | string, options?: AssignmentOptions): Temporal.Time;
add(durationLike: Temporal.Duration | DurationLike, options?: ArithmeticOptions): Temporal.Time;
subtract(durationLike: Temporal.Duration | DurationLike, options?: ArithmeticOptions): Temporal.Time;
difference(
Expand Down Expand Up @@ -834,6 +835,7 @@ export namespace Temporal {
*/
export interface TimeZoneProtocol {
id: string;
timeZone?: never;
getOffsetNanosecondsFor(instant: Temporal.Instant): number;
getOffsetStringFor(instant: Temporal.Instant): string;
getZonedDateTimeFor(instant: Temporal.Instant, calendar?: CalendarProtocol | string): Temporal.ZonedDateTime;
Expand All @@ -859,8 +861,8 @@ export namespace Temporal {
*
* See https://tc39.es/proposal-temporal/docs/timezone.html for more details.
*/
export class TimeZone implements Required<TimeZoneProtocol> {
static from(timeZone: Temporal.TimeZoneProtocol | string): Temporal.TimeZone;
export class TimeZone implements Omit<Required<TimeZoneProtocol>, 'timeZone'> {
static from(timeZone: Temporal.TimeZone | string): Temporal.TimeZone;
constructor(timeZoneIdentifier: string);
readonly id: string;
getOffsetNanosecondsFor(instant: Temporal.Instant): number;
Expand Down
8 changes: 8 additions & 0 deletions polyfill/test/zoneddatetime.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,14 @@ describe('ZonedDateTime', () => {
const zdt = Temporal.ZonedDateTime.from('2020-03-08T01:00-08:00[America/Los_Angeles]');
equal(zdt.toString(), '2020-03-08T01:00-08:00[America/Los_Angeles]');
});
it('parses with an IANA zone but no offset', () => {
const zdt = Temporal.ZonedDateTime.from('2020-03-08T01:00[America/Los_Angeles]');
equal(zdt.toString(), '2020-03-08T01:00-08:00[America/Los_Angeles]');
});
it('parses with an IANA zone but no offset (with disambiguation)', () => {
const zdt = Temporal.ZonedDateTime.from('2020-03-08T02:30[America/Los_Angeles]', { disambiguation: 'earlier' });
equal(zdt.toString(), '2020-03-08T01:30-08:00[America/Los_Angeles]');
});
it('parses with an offset in brackets', () => {
const zdt = Temporal.ZonedDateTime.from('2020-03-08T01:00-08:00[-08:00]');
equal(zdt.toString(), '2020-03-08T01:00-08:00[-08:00]');
Expand Down

0 comments on commit 5511474

Please sign in to comment.