Skip to content

Commit

Permalink
Add clarifications about TimeZone and Calendar protocols
Browse files Browse the repository at this point in the history
Emphasize that inheriting from the built-in objects is the recommended way
to create custom time zones and calendars, and give details about what the
default implementations of each of the optional methods do.

Closes: #1040
  • Loading branch information
ptomato committed Oct 22, 2020
1 parent df5d81c commit 8563374
Show file tree
Hide file tree
Showing 2 changed files with 30 additions and 0 deletions.
8 changes: 8 additions & 0 deletions docs/calendar.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,12 @@ The object must implement all of the `Temporal.Calendar` methods except for `fie
It must not have a `calendar` property, so that it can be distinguished in `Temporal.Calendar.from()` from other Temporal objects that have a calendar.
It is possible to pass such an object into any Temporal API that would normally take a built-in `Temporal.Calendar`.

Any implementation of the protocol with the required methods will return the correct output from any Temporal property or method.
However, most other code will assume that custom calendars act like built-in `Temporal.Calendar` objects.
If you want to interoperate with libraries or other code that you didn't write, then you should implement the `id` property and the `fields()` method as well.

Creating a class that inherits from a built-in `Temporal.Calendar` and overriding the methods you need to override, instead of using a plain object that implements the calendar protocol, is by far the easiest (and recommended) way to achieve this.

## Constructor

### **new Temporal.Calendar**(_calendarIdentifier_: string) : Temporal.Calendar
Expand Down Expand Up @@ -121,6 +127,8 @@ cal = Temporal.Calendar.from({id: 'mycalendar'});
The `id` property gives an unambiguous identifier for the calendar.
Effectively, this is whatever `calendarIdentifier` was passed as a parameter to the constructor.

The default implementation of this property gives the result of calling `toString()`.

## Methods

### calendar.**year**(_date_: Temporal.Date) : number
Expand Down
22 changes: 22 additions & 0 deletions docs/timezone.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,12 @@ The object must have `getOffsetNanosecondsFor()`, `getPossibleInstantsFor()`, an
It must not have a `timeZone` property, so that it can be distinguished in `Temporal.TimeZone.from()` from other Temporal objects that have a time zone.
It is possible to pass such an object into any Temporal API that would normally take a built-in `Temporal.TimeZone`.

Any implementation of the protocol with those three methods will return the correct output from any Temporal property or method.
However, most other code will assume that custom time zones act like built-in `Temporal.TimeZone` objects.
If you want to interoperate with libraries or other code that you didn't write, then you should implement all the other `Temporal.TimeZone` methods and properties described below as well: `id`, `getOffsetStringFor()`, `getDateTimeFor()`, `getZonedDateTimeFor()`, `getInstantFor()`, `getNextTransition()`, `getPreviousTransition()`, and `toJSON()`.

Creating a class that inherits from the built-in `Temporal.TimeZone` and overriding the methods you need to override, instead of using a plain object that implements the time zone protocol, is by far the easiest (and recommended) way to achieve this.

## Constructor

### **new Temporal.TimeZone**(_timeZoneIdentifier_: string) : Temporal.TimeZone
Expand Down Expand Up @@ -127,6 +133,8 @@ tz2 = Temporal.TimeZone.from(tz);
The `id` property gives an unambiguous identifier for the time zone.
Effectively, this is the canonicalized version of whatever `timeZoneIdentifier` was passed as a parameter to the constructor.

The default implementation of this property gives the result of calling `toString()`.

## Methods

### timeZone.**getOffsetNanosecondsFor**(_instant_: Temporal.Instant | string) : number
Expand Down Expand Up @@ -179,6 +187,8 @@ If `timeZone` is a UTC offset time zone, the return value of this method is effe

If `instant` is not a `Temporal.Instant` object, then it will be converted to one as if it were passed to `Temporal.Instant.from()`.

The default implementation of this method creates an offset string using the result of calling `timeZone.getOffsetNanosecondsFor()`.

Example usage:

```javascript
Expand Down Expand Up @@ -206,6 +216,8 @@ This method is one way to convert a `Temporal.Instant` to a `Temporal.ZonedDateT

If `instant` is not a `Temporal.Instant` object, then it will be converted to one as if it were passed to `Temporal.Instant.from()`.

The default implementation of this method gives a result equivalent to calling `new Temporal.ZonedDateTime(instant.epochNanoseconds, timeZone, calendar)`.

Example usage:

```javascript
Expand Down Expand Up @@ -234,6 +246,8 @@ This method is one way to convert a `Temporal.Instant` to a `Temporal.DateTime`.

If `instant` is not a `Temporal.Instant` object, then it will be converted to one as if it were passed to `Temporal.Instant.from()`.

The default implementation of this method creates a `Temporal.DateTime` from `instant` using a UTC offset which is the result of calling `timeZone.getOffsetNanosecondsFor()`.

Example usage:

```javascript
Expand Down Expand Up @@ -283,6 +297,8 @@ For usage examples and a more complete explanation of how this disambiguation wo

If the result is earlier or later than the range that `Temporal.Instant` can represent (approximately half a million years centered on the [Unix epoch](https://en.wikipedia.org/wiki/Unix_time)), then a `RangeError` will be thrown, no matter the value of `disambiguation`.

The default implementation of this method calls `timeZone.getPossibleInstantsFor()`, and if there is more than one possible instant, uses `disambiguation` to pick which one to return.

### timeZone.**getPossibleInstantsFor**(_dateTime_: Temporal.DateTime | object | string) : array<Temporal.Instant>

**Parameters:**
Expand Down Expand Up @@ -316,6 +332,8 @@ In that case, this method will return `null`.

If `instant` is not a `Temporal.Instant` object, then it will be converted to one as if it were passed to `Temporal.Instant.from()`.

The default implementation of this method returns `null`.

Example usage:

```javascript
Expand All @@ -342,6 +360,8 @@ In that case, this method will return `null`.

If `instant` is not a `Temporal.Instant` object, then it will be converted to one as if it were passed to `Temporal.Instant.from()`.

The default implementation of this method returns `null`.

Example usage:

```javascript
Expand Down Expand Up @@ -370,6 +390,8 @@ The reverse operation, recovering a `Temporal.TimeZone` object from a string, is
If you need to rebuild a `Temporal.TimeZone` object from a JSON string, then you need to know the names of the keys that should be interpreted as `Temporal.TimeZone`s.
In that case you can build a custom "reviver" function for your use case.

The default implementation of this method returns the result of calling `timeZone.toString()`.

Example usage:

```js
Expand Down

0 comments on commit 8563374

Please sign in to comment.