## 40.日期(`Date`)
> 原文: [http://exploringjs.com/impatient-js/ch_dates.html](http://exploringjs.com/impatient-js/ch_dates.html)
>
> 貢獻者:[facebesidewyj](https://github.com/facebesidewyj)
本章介紹 JavaScript 用于處理日期的 API - `Date`。
### 40.1。最佳實踐:不要使用當前的內置 API
JavaScript `Date` API 使用起來很麻煩。因此,最好依靠第三方庫來處理與日期相關的任何事情。熱門第三方庫包括:
* [Moment.js](https://momentjs.com)
* [Day.js](https://github.com/iamkun/dayjs)
* [Luxon](https://moment.github.io/luxon/)
* [js-joda](https://js-joda.github.io/js-joda/)
* [date-fns](https://github.com/date-fns/date-fns)
請參閱博客文章[“為什么你不應該使用 Moment.js ......”](https://inventi.studio/en/blog/why-you-shouldnt-use-moment-js)了解這些第三方庫的優缺點。
此外,TC39(技術委員會(Technical Committee)第 39 號,它是 ECMA 的一部分,ECMA 是 “ECMAScript” 規范下的 JavaScript 語言標準化的機構。) 正在開發 JavaScript 的新日期 API: [`temporal`](https://github.com/maggiepint/proposal-temporal) 。
#### 41.1.1。一些要在日期庫中尋找的內容
要記住兩件很重要的事:
* [`Tree-shaking`](https://webpack.docschina.org/guides/tree-shaking/) 可以幫助減少庫的大小,是一種僅將庫的導出部署到Web服務器的技術,可以在某處導入。Tree-shaking對函數的影響比類更大。
* 支持時區:Date對象默認不支持時區,這會帶來一些問題并且這是一個關鍵的弱點。確保您的日期庫支持時區。
### 40.2。時區
#### 41.2.1。背景:UTC與GMT
UTC(協調世界時)和 GMT(格林威治標準時間)具有相同的當前時間,但它們是不同的東西:
* UTC:是所有時區所基于的時間標準。它們是相對于它指定的。也就是說,沒有狀態或地區將 UTC 作為其本地時區。
* GMT:是一些歐洲和非洲國家使用的時區。它是UTC加零小時,因此與UTC的時間相同。
資料來源:[“TimeTndDate.com 上的 GMT 和 UTC 之間的差異”](https://www.timeanddate.com/time/gmt-utc-time.html)
#### 41.2.2。JavaScript日期對象僅支持UTC和本地時區
我們無法為JavaScript日期指定任意時區。
它使用兩個時間系統:
* UTC(協調世界時)
* 本地時區(從操作系統自動獲取)
Date實例將其時間存儲在UTC中。無論何時在日期和其他數據之間進行轉換,我們都需要注意是否使用了UTC或本地時區。例如:`new Date()`使用本地時區,而`.toISOString()`使用UTC
```javascript
new Date(2077, 0, 27).toISOString()
'2077-01-26T23:00:00.000Z'
```
JavaScript日期對象將0解釋為1月。本地時區的當月是27日,但UTC是26日。
> 日期操作:UTC與本地時區
>
> 對于本章中記錄的每個操作,它在日期和其他數據之間進行轉換,請注意是使用UTC還是本地時區。
#### 41.2.3?無法指定時區的缺點
無法指定時區,存在兩個問題:
* 無法支持多個時區。
* 可能導致特定位置的bug。例如,前面的示例會根據執行的位置生成不同的結果。在這種特殊情況下,輸入為CET,而輸出則是UTC。這就是為什么這個月的日期不同(27對26)。
### 40.3。背景:日期時間格式(ISO)
日期時間格式描述:
* 接受的字符串:
* `Date.parse()`
* `new Date()`
* 返回的字符串(總是最長的格式):
* `Date.prototype.toISOString()`
以下是`.toISOString()`返回的日期時間字符串的示例:
```js
'2033-05-28T15:59:59.123Z'
```
日期時間格式具有以下結構:
* 日期格式:Y =年份; M =月; d =天
```js
YYYY-MM-DD
YYYY-MM
YYYY
```
* 時間格式:T =分隔符(字符串`'T'`); H =小時; M =分鐘; s =秒和毫秒; Z =時區是 UTC(字符串`'Z'`)
```js
THH:mm:ss.sss
THH:mm:ss.sssZ
THH:mm:ss
THH:mm:ssZ
THH:mm
THH:mmZ
```
* 日期時間格式:日期格式后跟時間格式。
* 例如(最長):`YYYY-MM-DDTHH:mm:ss.sssZ`
`Z`的替代方案 - 相對于 UTC 的時區:
* `+hh:mm`
* `-hh:mm`
### 40.4。時間值
_ 時間值 _ 表示自 1970 年 1 月 1 日 00:00:00 UTC 以來的毫秒數的日期。
時間值可用于創建日期:
```js
const timeValue = 0;
assert.equal(
new Date(timeValue).toISOString(),
'1970-01-01T00:00:00.000Z');
```
將日期強制轉換為數字會返回其時間值:
```js
> Number(new Date(123))
123
```
比較運算符將他們的操作數強制轉換為數字。因此,您可以使用這些運算符來比較日期:
```js
assert.equal(new Date('1972-05-03') < new Date('2001-12-23'), true);
// Internally:
assert.equal(73699200000 < 1009065600000, true);
```
#### 40.4.1。創建時間值
以下方法創建時間值:
* `Date.now(): number`
返回當前時間作為時間值。
* `Date.parse(dateTimeString): number`(當地時區)
解析`dateTimeString`并返回相應的時間值。
* `Date.UTC(year, month, date?, hours?, minutes?, seconds?, milliseconds?): number`
返回指定的 UTC 日期時間的時間值。
#### 40.4.2。獲取和設置時間值
* `Date.prototype.getTime(): number`
返回與 Date 對應的時間值。
* `Date.prototype.setTime(timeValue)`
將`this`設置為`timeValue`編碼的日期。
### 40.5。創建日期
* `new Date(year: number, month: number, date?: number, hours?: number, minutes?: number, seconds?: number, milliseconds?: number)`(當地時區)
```js
> new Date(2077,0,27, 21,49,58, 888).toISOString() // CET (UTC+1)
'2077-01-27T20:49:58.888Z'
```
* `new Date(dateTimeStr: string)`(UTC)
```js
> new Date('2077-01-27').toISOString()
'2077-01-27T00:00:00.000Z'
```
* `new Date(timeValue: number)`
```js
> new Date(0).toISOString()
'1970-01-01T00:00:00.000Z'
```
* `new Date()`(與`new Date(Date.now())`相同)
#### 41.5.1?構造函數的陷阱
`new Date()`的構造函數會產生兩個問題:
* 對于month,0是一月
* 如果0≤year≤99,則為1900+yaer
```js
> new Date(12, 1, 22, 19, 11).getFullYear()
1912
```
這就是為什么,在本章的其他地方,我們總是使用時間單位fullYear。但在這種情況下,我們別無選擇。
### 40.6。Getters 和 Setters
#### 40.6.1。時間單位Getters和Setters
日期有時間單位的 getter 和 setter。例如:
* `Date.prototype.getFullYear()`
* `Date.prototype.setFullYear(num)`
這些 getter 和 setter 符合以下模式:
* 當地時間:
* `Date.prototype.get?Unit?()`
* `Date.prototype.set?Unit?(num)`
* 世界時間:
* `Date.prototype.getUTC?Unit?()`
* `Date.prototype.setUTC?Unit?(num)`
這些是支持的時間單位:
* 日期
* `FullYear`
* `Month`:月(0-11)。 **陷阱:** 0 是 1 月等
* `Date`:每月的某一天(1-31)
* `Day`(僅限吸氣劑):星期幾(0-6); 0 是星期天
* 時間
* `Hours`:小時(0-23)
* `Minutes`:分鐘(0-59)
* `Seconds`:秒(0-59)
* `Milliseconds`:毫秒(0-999)
還有一個getter不符合前面提到的模式:
* `Date.prototype.getTimezoneOffset()`
返回本地時間和 UTC 之間的時差,以分鐘為單位。例如,對于 CET,它返回`-60`。
### 40.7。將日期轉換為字符串
示例日期:
```js
const d = new Date(0);
```
#### 40.7.1。帶時間的字符串
* `Date.prototype.toTimeString()`(當地時區)
```js
> d.toTimeString()
'01:00:00 GMT+0100 (Central European Standard Time)'
```
* `Date.prototype.toLocaleTimeString()`(參見 [ECMAScript 國際化 API](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl) )
#### 40.7.2。帶日期的字符串
* `Date.prototype.toDateString()`(當地時區)
```js
> d.toDateString()
'Thu Jan 01 1970'
```
* `Date.prototype.toLocaleDateString()`( [ECMAScript 國際化 API](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl) )
#### 40.7.3。帶有日期和時間的字符串
* `Date.prototype.toString()`(當地時區)
```js
> d.toString()
'Thu Jan 01 1970 01:00:00 GMT+0100 (Central European Standard Time)
```
* `Date.prototype.toLocaleString()`(參見 [ECMAScript 國際化 API](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl) )
* `Date.prototype.toUTCString()`(UTC)
```js
> d.toUTCString()
'Thu, 01 Jan 1970 00:00:00 GMT'
```
* `Date.prototype.toISOString()`(UTC)
```js
> d.toISOString()
'1970-01-01T00:00:00.000Z'
```
 **練習:創建日期字符串**
`exercises/dates/create_date_string_test.js`
- I.背景
- 1.關于本書(ES2019 版)
- 2.常見問題:本書
- 3. JavaScript 的歷史和演變
- 4.常見問題:JavaScript
- II.第一步
- 5.概覽
- 6.語法
- 7.在控制臺上打印信息(console.*)
- 8.斷言 API
- 9.測驗和練習入門
- III.變量和值
- 10.變量和賦值
- 11.值
- 12.運算符
- IV.原始值
- 13.非值undefined和null
- 14.布爾值
- 15.數字
- 16. Math
- 17. Unicode - 簡要介紹(高級)
- 18.字符串
- 19.使用模板字面值和標記模板
- 20.符號
- V.控制流和數據流
- 21.控制流語句
- 22.異常處理
- 23.可調用值
- VI.模塊化
- 24.模塊
- 25.單個對象
- 26.原型鏈和類
- 七.集合
- 27.同步迭代
- 28.數組(Array)
- 29.類型化數組:處理二進制數據(高級)
- 30.映射(Map)
- 31. WeakMaps(WeakMap)
- 32.集(Set)
- 33. WeakSets(WeakSet)
- 34.解構
- 35.同步生成器(高級)
- 八.異步
- 36. JavaScript 中的異步編程
- 37.異步編程的 Promise
- 38.異步函數
- IX.更多標準庫
- 39.正則表達式(RegExp)
- 40.日期(Date)
- 41.創建和解析 JSON(JSON)
- 42.其余章節在哪里?