Skip to content

Commit

Permalink
Avoid using non-standard date string format, better date string descr…
Browse files Browse the repository at this point in the history
…iption (#27005)

* Avoid using non-standard date string format, better date string description

* Fixes

* Apply suggestions from code review

Co-authored-by: Florian Scholz <[email protected]>

---------

Co-authored-by: Florian Scholz <[email protected]>
  • Loading branch information
Josh-Cena and Elchi3 authored Jun 1, 2023
1 parent 972033b commit 3e2369d
Show file tree
Hide file tree
Showing 27 changed files with 199 additions and 373 deletions.
10 changes: 5 additions & 5 deletions files/en-us/web/javascript/guide/numbers_and_dates/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -331,9 +331,9 @@ Calling `Date` without the `new` keyword returns a string representing the curre
The `parameters` in the preceding syntax can be any of the following:

- Nothing: creates today's date and time. For example, `today = new Date();`.
- A string representing a date in the following form: "Month day, year hours:minutes:seconds." For example, `let Xmas95 = new Date("December 25, 1995 13:30:00")`. If you omit hours, minutes, or seconds, the value will be set to zero.
- A set of integer values for year, month, and day. For example, `let Xmas95 = new Date(1995, 11, 25)`.
- A set of integer values for year, month, day, hour, minute, and seconds. For example, `let Xmas95 = new Date(1995, 11, 25, 9, 30, 0);`.
- A string representing a date, in many different forms. The exact forms supported differ among engines, but the following form is always supported: `YYYY-MM-DDTHH:mm:ss.sssZ`. For example, `xmas95 = new Date("1995-12-25")`. If you omit hours, minutes, or seconds, the value will be set to zero.
- A set of integer values for year, month, and day. For example, `xmas95 = new Date(1995, 11, 25)`.
- A set of integer values for year, month, day, hour, minute, and seconds. For example, `xmas95 = new Date(1995, 11, 25, 9, 30, 0);`.

### Methods of the Date object

Expand All @@ -356,10 +356,10 @@ With the "get" and "set" methods you can get and set seconds, minutes, hours, da
For example, suppose you define the following date:

```js
const Xmas95 = new Date("December 25, 1995");
const xmas95 = new Date("1995-12-25");
```

Then `Xmas95.getMonth()` returns 11, and `Xmas95.getFullYear()` returns 1995.
Then `xmas95.getMonth()` returns 11, and `xmas95.getFullYear()` returns 1995.

The `getTime` and `setTime` methods are useful for comparing dates. The `getTime` method returns the number of milliseconds since the epoch for a `Date` object.

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,58 +7,50 @@ browser-compat: javascript.builtins.Date.@@toPrimitive

{{JSRef}}

The **`[@@toPrimitive]()`** method converts a `Date`
object to a primitive value.
The **`[@@toPrimitive]()`** method of {{jsxref("Date")}} instances returns a primitive value representing this date. It may either be a string or a number, depending on the hint given.

{{EmbedInteractiveExample("pages/js/date-toprimitive.html")}}

## Syntax

```js-nolint
Date()[Symbol.toPrimitive](hint)
date[Symbol.toPrimitive](hint)
```

### Parameters

- `hint`
- : A string representing the type of the primitive value to return. The following values are valid:
- `"string"` or `"default"`: The method should return a string.
- `"number"`: The method should return a number.

### Return value

The primitive value of the given {{jsxref("Date")}} object. Depending on the argument,
the method can return either a string or a number.
If `hint` is `"string"` or `"default"`, this method returns a string by [coercing the `this` value to a string](/en-US/docs/Web/JavaScript/Reference/Global_Objects/String#string_coercion) (first trying `toString()` then trying `valueOf()`).

## Description
If `hint` is `"number"`, this method returns a number by [coercing the `this` value to a number](/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number#number_coercion) (first trying `valueOf()` then trying `toString()`).

The `[@@toPrimitive]()` method of the {{jsxref("Date")}} object returns a
primitive value, that is either of type number or of type string.
### Exceptions

If `hint` is `string` or `default`,
`[@@toPrimitive]()` tries to call the {{jsxref("Object.prototype.toString()",
"toString")}} method. If the `toString` property does not exist, it tries to
call the {{jsxref("Object.prototype.valueOf()", "valueOf")}} method and if the
`valueOf` does not exist either, `[@@toPrimitive]()` throws a
{{jsxref("TypeError")}}.
- {{jsxref("TypeError")}}
- : Thrown if the `hint` argument is not one of the three valid values.

If `hint` is `number`, `[@@toPrimitive]()` first tries
to call `valueOf`, and if that fails, it calls `toString`.
## Description

JavaScript calls the `[@@toPrimitive]()` method to convert an object to a
primitive value. You rarely need to invoke the `[@@toPrimitive]()` method
yourself; JavaScript automatically invokes it when encountering an object where a
primitive value is expected.
The `[@@toPrimitive]()` method is part of the [type coercion protocol](/en-US/docs/Web/JavaScript/Data_structures#type_coercion). JavaScript always calls the `[@@toPrimitive]()` method in priority to convert an object to a primitive value. You rarely need to invoke the `[@@toPrimitive]()` method yourself; JavaScript automatically invokes it when encountering an object where a primitive value is expected.

The `[@@toPrimitive]()` method of the {{jsxref("Date")}} object returns a primitive value by either invoking {{jsxref("Date/valueOf", "this.valueOf()")}} and returning a number, or invoking {{jsxref("Date/toString", "this.toString()")}} and returning a string. It exists to override the default [primitive coercion](/en-US/docs/Web/JavaScript/Data_structures#primitive_coercion) process to return a string instead of a number, because primitive coercion, by default, calls {{jsxref("Date/valueOf", "valueOf()")}} before {{jsxref("Date/toString", "toString()")}}. With the custom `[@@toPrimitive]()`, `new Date(0) + 1` returns `"Thu Jan 01 1970 00:00:00 GMT+0000 (Coordinated Universal Time)1"` (a string) instead of `1` (a number).

## Examples

### Returning date primitives
### Using \[@@toPrimitive]()

```js
const testDate = new Date(1590757517834);
// "Date Fri May 29 2020 14:05:17 GMT+0100 (British Summer Time)"

testDate[Symbol.toPrimitive]("string");
// Returns "Date Fri May 29 2020 14:05:17 GMT+0100 (British Summer Time)"

testDate[Symbol.toPrimitive]("number");
// Returns "1590757517834"
const d = new Date(0); // 1970-01-01T00:00:00.000Z

testDate[Symbol.toPrimitive]("default");
// Returns "Date Fri May 29 2020 14:05:17 GMT+0100 (British Summer Time)"
d[Symbol.toPrimitive]("string"); // "Thu Jan 01 1970 00:00:00 GMT+0000 (Coordinated Universal Time)"
d[Symbol.toPrimitive]("number"); // 0
d[Symbol.toPrimitive]("default"); // "Thu Jan 01 1970 00:00:00 GMT+0000 (Coordinated Universal Time)"
```

## Specifications
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ When no parameters are provided, the newly-created `Date` object represents the
#### Date string

- `dateString`
- : A string value representing a date, in a format recognized by the {{jsxref("Date.parse()")}} method. The only specified format is the [date time string format](/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date#date_time_string_format), but other formats can be implementation-defined, which commonly include [IETF-compliant RFC 2822 timestamps](https://datatracker.ietf.org/doc/html/rfc2822#page-14). See [date time string format](/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date#date_time_string_format) for caveats on using different formats.
- : A string value representing a date, parsed and interpreted using the same algorithm implemented by {{jsxref("Date.parse()")}}. See [date time string format](/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date#date_time_string_format) for caveats on using different formats.

#### Date object

Expand All @@ -69,15 +69,15 @@ Similarly, if any parameter underflows, it "borrows" from the higher positions.
- `monthIndex`
- : Integer value representing the month, beginning with `0` for January to `11` for December.
- `day` {{optional_inline}}
- : Integer value representing the day of the month. The default is `1`.
- : Integer value representing the day of the month. Defaults to `1`.
- `hours` {{optional_inline}}
- : Integer value between `0` and `23` representing the hour of the day. Defaults to `0`.
- `minutes` {{optional_inline}}
- : Integer value representing the minute segment of a time. The default is `0` minutes past the hour.
- : Integer value representing the minute segment of a time. Defaults to `0`.
- `seconds` {{optional_inline}}
- : Integer value representing the second segment of a time. The default is `0` seconds past the minute.
- : Integer value representing the second segment of a time. Defaults to `0`.
- `milliseconds` {{optional_inline}}
- : Integer value representing the millisecond segment of a time. The default is `0` milliseconds past the second.
- : Integer value representing the millisecond segment of a time. Defaults to `0`.

### Return value

Expand All @@ -94,7 +94,7 @@ The following examples show several ways to create JavaScript dates:
```js
const today = new Date();
const birthday = new Date("December 17, 1995 03:24:00"); // DISCOURAGED: may not work in all runtimes
const birthday = new Date("1995-12-17T03:24:00"); // This is ISO-8601-compliant and will work reliably
const birthday = new Date("1995-12-17T03:24:00"); // This is standardized and will work reliably
const birthday = new Date(1995, 11, 17); // the month is 0-indexed
const birthday = new Date(1995, 11, 17, 3, 24, 0);
const birthday = new Date(628021800000); // passing epoch timestamp
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ An integer, between 1 and 31, representing the day of the month for the given da
The `day` variable has value `25`, based on the value of the {{jsxref("Date")}} object `xmas95`.

```js
const xmas95 = new Date("December 25, 1995 23:15:30");
const xmas95 = new Date("1995-12-25T23:15:30");
const day = xmas95.getDate();

console.log(day); // 25
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ console.log(new Intl.DateTimeFormat("de-DE", options).format(valentines));
The `weekday` variable has value `1`, based on the value of the {{jsxref("Date")}} object `xmas95`, because December 25, 1995 is a Monday.

```js
const xmas95 = new Date("December 25, 1995 23:15:30");
const xmas95 = new Date("1995-12-25T23:15:30");
const weekday = xmas95.getDay();

console.log(weekday); // 1
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ Unlike {{jsxref("Date/getYear", "getYear()")}}, the value returned by `getFullYe
The `fullYear` variable has value `1995`, based on the value of the {{jsxref("Date")}} object `xmas95`.

```js
const xmas95 = new Date("December 25, 1995 23:15:30");
const xmas95 = new Date("1995-12-25T23:15:30");
const fullYear = xmas95.getFullYear();

console.log(fullYear); // 1995
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ An integer, between 0 and 23, representing the hours for the given date accordin
The `hours` variable has value `23`, based on the value of the {{jsxref("Date")}} object `xmas95`.

```js
const xmas95 = new Date("December 25, 1995 23:15:30");
const xmas95 = new Date("1995-12-25T23:15:30");
const hours = xmas95.getHours();

console.log(hours); // 23
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ An integer, between 0 and 999, representing the milliseconds for the given date
The `milliseconds` variable has value `0`, based on the value of the {{jsxref("Date")}} object `xmas95`, which doesn't specify the milliseconds component, so it defaults to 0.

```js
const xmas95 = new Date("December 25, 1995 23:15:30");
const xmas95 = new Date("1995-12-25T23:15:30");
const milliseconds = xmas95.getMilliseconds();

console.log(milliseconds); // 0
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ An integer, between 0 and 59, representing the minutes for the given date accord
The `minutes` variable has value `15`, based on the value of the {{jsxref("Date")}} object `xmas95`.

```js
const xmas95 = new Date("December 25, 1995 23:15:30");
const xmas95 = new Date("1995-12-25T23:15:30");
const minutes = xmas95.getMinutes();

console.log(minutes); // 15
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ console.log(new Intl.DateTimeFormat("de-DE", options).format(valentines));
The `month` variable has value `11`, based on the value of the {{jsxref("Date")}} object `xmas95`.

```js
const xmas95 = new Date("December 25, 1995 23:15:30");
const xmas95 = new Date("1995-12-25T23:15:30");
const month = xmas95.getMonth();

console.log(month); // 11
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ An integer, between 0 and 59, representing the seconds for the given date accord
The `seconds` variable has value `30`, based on the value of the {{jsxref("Date")}} object `xmas95`.

```js
const xmas95 = new Date("December 25, 1995 23:15:30");
const xmas95 = new Date("1995-12-25T23:15:30");
const seconds = xmas95.getSeconds();

console.log(seconds); // 30
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ A number representing the [timestamp](/en-US/docs/Web/JavaScript/Reference/Globa

`Date` objects are fundamentally represented by a [timestamp](/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date#the_epoch_timestamps_and_invalid_date), and this method allows you to retrieve the timestamp. You can use this method to help assign a date and time to another {{jsxref("Date")}} object. This method is functionally equivalent to the {{jsxref("Date/valueof", "valueOf()")}} method.

### Return time precision
### Reduced time precision

To offer protection against timing attacks and [fingerprinting](/en-US/docs/Glossary/Fingerprinting), the precision of `new Date().getTime()` might get rounded depending on browser settings. In Firefox, the `privacy.reduceTimerPrecision` preference is enabled by default and defaults to 2ms. You can also enable `privacy.resistFingerprinting`, in which case the precision will be 100ms or the value of `privacy.resistFingerprinting.reduceTimerPrecision.microseconds`, whichever is larger.

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ This method essentially returns the value of {{jsxref("Date/getFullYear", "getFu
The second statement assigns the value 95 to the variable `year`.

```js
const xmas = new Date("December 25, 1995 23:15:00");
const xmas = new Date("1995-12-25");
const year = xmas.getYear(); // returns 95
```

Expand All @@ -43,7 +43,7 @@ const year = xmas.getYear(); // returns 95
The second statement assigns the value 100 to the variable `year`.

```js
const xmas = new Date("December 25, 2000 23:15:00");
const xmas = new Date("2000-12-25");
const year = xmas.getYear(); // returns 100
```

Expand All @@ -52,7 +52,7 @@ const year = xmas.getYear(); // returns 100
The second statement assigns the value -100 to the variable `year`.

```js
const xmas = new Date("December 25, 1800 23:15:00");
const xmas = new Date("1800-12-25");
const year = xmas.getYear(); // returns -100
```

Expand All @@ -61,7 +61,7 @@ const year = xmas.getYear(); // returns -100
The third statement assigns the value 95 to the variable `year`, representing the year 1995.

```js
const xmas = new Date("December 25, 2015 23:15:00");
const xmas = new Date("2015-12-25");
xmas.setYear(95);
const year = xmas.getYear(); // returns 95
```
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -157,9 +157,11 @@ When the time zone offset is absent, **date-only forms are interpreted as a UTC

{{jsxref("Date.parse()")}} and the {{jsxref("Date/Date", "Date()")}} constructor both accept strings in the date time string format as input. Furthermore, implementations are allowed to support other date formats when the input fails to match this format.

The {{jsxref("Date/toISOString", "toISOString()")}} method returns a string representation of the date in the date time string format, with the time zone offset always set to `Z` (UTC).

> **Note:** You are encouraged to make sure your input conforms to the date time string format above for maximum compatibility, because support for other formats is not guaranteed. However, there are some formats that are supported in all major implementations — like {{rfc(2822)}} format — in which case their usage can be acceptable. Always conduct [cross-browser tests](/en-US/docs/Learn/Tools_and_testing/Cross_browser_testing) to ensure your code works in all target browsers. A library can help if many different formats are to be accommodated.
The {{jsxref("Date/toISOString", "toISOString()")}} method returns a string representation of the date in the date time string format, with the time zone offset always set to `Z` (UTC).
Non-standard strings can be parsed in any way as desired by the implementation, including the time zone — most implementations use the local time zone by default. Implementations are not required to return invalid date for out-of-bounds date components, although they usually do. A string may have in-bounds date components (with the bounds defined above), but does not represent a date in reality (for example, "February 30"). Implementations behave inconsistently in this case. The [`Date.parse()`](/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/parse#examples) page offers more examples about these non-standard cases.

### Other ways to format a date

Expand Down Expand Up @@ -292,12 +294,12 @@ These properties are defined on `Date.prototype` and shared by all `Date` instan

The following examples show several ways to create JavaScript dates:

> **Note:** When parsing date strings with the `Date` constructor (and `Date.parse`, they are equivalent), always make sure that the input conforms to the [ISO 8601 format](https://tc39.es/ecma262/#sec-date-time-string-format) (`YYYY-MM-DDTHH:mm:ss.sssZ`) — the parsing behavior with other formats is implementation-defined and may not work across all browsers. A library can help if many different formats are to be accommodated.
> **Note:** Creating a date from a string has a lot of behavior inconsistencies. See [date time string format](#date_time_string_format) for caveats on using different formats.
```js
const today = new Date();
const birthday = new Date("December 17, 1995 03:24:00"); // DISCOURAGED: may not work in all runtimes
const birthday2 = new Date("1995-12-17T03:24:00"); // This is ISO8601-compliant and will work reliably
const birthday2 = new Date("1995-12-17T03:24:00"); // This is standardized and will work reliably
const birthday3 = new Date(1995, 11, 17); // the month is 0-indexed
const birthday4 = new Date(1995, 11, 17, 3, 24, 0);
const birthday5 = new Date(628021800000); // passing epoch timestamp
Expand Down
Loading

0 comments on commit 3e2369d

Please sign in to comment.