須要知道的JS的日期知識,都在這了

爲了保證的可讀性,本文采用意譯而非直譯。前端

想閱讀更多優質文章請猛戳GitHub博客,一年百來篇優質文章等着你!git

JS中的 Date 很奇怪。當咱們須要處理日期和時間的時候比較麻煩,常常藉助像date-fnsMoment 這樣的庫。github

可是咱們並不老是須要使用庫。若是知道要注意一些老是,日期實際上能夠很是簡單。接下介紹有關Date對象的全部信息編程

時區

咱們的世界有數百個時區。 在JavaScript中,咱們只關心兩個, 本地時間協調世界時(UTC)。數組

  • 本地時間是指你的計算機所在的時區。
  • UTC其實是格林威治標準時間(GMT)的同義詞

默認狀況下,JS中的幾乎每一個日期方法(除了一個)都是本地時間。 只有指定UTC,才能得到 UTC 時間 。編程語言

建立日期

可使用 new Date() 來建立日期,傳入的參數一般有4種經常使用的方式:工具

  1. 使用日期字符串參數
  2. 使用一系列的參數
  3. 時間戳參數
  4. 不帶參數

使用日期字符串參數

new Date('1988-03-21')

這種方式方便且直觀。學習

若是如今寫的是21-03-1988,咱們能夠絕不費力想表達的是1988年3月21日。可是若是用JS 編寫21-03-1988,則會獲得無效的日期。ui

clipboard.png

這是有緣由的。spa

在世界的不一樣地方以不一樣的方式解釋日期字符串。 例如11-06-20192019年6月11日仍是 2019年11月6日。你不能肯定我指的是哪個,除非你知道我正在使用的日期系統。

在JS中,若是要使用日期字符串參數,則須要使用全球都能接受的格式,其中一種格式是ISO 8601擴展格式

// ISO 8601 Extended format
`YYYY-MM-DDTHH:mm:ss:sssZ`
  • YYYY:4位數年份
  • MM:兩位數月份(即 1月爲01,12月爲12)
  • DD:兩位數的日期(0到31)
  • -:日期分隔符
  • T:表示開始時間
  • HH:24位小時數(0到23)
  • mm:分鐘(0到59)
  • ss:秒(0到59)
  • sss:毫秒(0到999)
  • ::時間分隔符
  • Z:若是存在Z,則日期將設置爲UTC,若是Z不存在,則爲本地時間。

其中小時,分鐘,秒和毫秒是可選的,若是你想建立一個2019年6月11日的日期,能夠這樣寫:

new Date('2019-06-11')

在這裏要特別注意,使用日期字符串參數建立日期存在很大問題,把建立的日期打印出來就能夠發現問題。

若是你住在格林威治標準時間(GMT)晚的的地區,你會獲得一個日期是6月10日

clipboard.png

若是你住在比格林威治標準時間早的地區,纔會等獲得6月11日的日期。

clipboard.png

發生這種狀況是由於日期字符串參數的方法具備特殊行爲:若是建立日期(未指定時間),則會得到UTC格式設置的日期。

在上面的場景中,使用new Date('2019-06-11') 建立日期時,實際上建立的日期是2019年6月11日,UTC時間上午12點。這就是爲何住在格林尼治標準時間以後的地區的人獲得的是6月10日而不是6月11日

若是要使用日期字符串參數方法在「本地時間」中建立日期,則須要包括時間。若是包含時間,則須要至少寫入HHmm

new Date('2019-06-11T00:00')

clipboard.png

使用日期字符串參數的建立的本地時間與UTC的比較多是一個難以捕捉的錯誤。因此,建議不要使用日期字符串建立日期方式。

格林威治標準時間GMT
十七世紀,格林威治皇家天文臺爲了海上霸權的擴張計畫而進行天體觀測。1675年舊皇家觀測所(Old Royal Observatory) 正式成立,到了1884年決定以經過格林威治的子午線做爲劃分地球東西兩半球的經度零度。觀測所門口牆上有一個標誌24小時的時鐘,顯示當下的時間,對全球而言,這裏所設定的時間是世界時間參考點,全球都以格林威治的時間做爲標準來設定時間,這就是咱們耳熟能詳的「格林威治標準時間(Greenwich Mean Time,簡稱G.M.T.)的由來,標示在手錶上,則表明此表具備兩地時間功能,也就是同時能夠顯示原居地和另外一個國度的時間。

世界協調時間UTC
多數的兩地時間表都以GMT來表示,但也有些兩地時間表上看不到GMT字樣,出現的反而是UTC這3個英文字母,究竟何謂UTC?事實上,UTC指的是Coordinated Universal Time- 世界協調時間(又稱世界標準時間、世界統一時間),是通過平均太陽時(以格林威治時間GMT爲準)、地軸運動修正後的新時標以及以「秒」爲單位的國際原子時所綜合精算而成的時間,計算過程至關嚴謹精密,所以若以「世界標準時間」的角度來講,UTC比GMT來得更加精準。其偏差值必須保持在0.9秒之內,若大於0.9秒則由位於巴黎的國際地球自轉事務中央局發佈閏秒,使UTC與地球自轉週期一致。因此基本上UTC的本質強調的是比GMT更爲精確的世界時間標準,不過對於現行錶款來講,GMT與UTC的功能與精確度是沒有差異的。

使用一系列的參數建立

最多能夠傳入七個參數來建立日期/時間。

  1. Year:4位數年份
  2. Month:一年中的某月(0-11)
  3. Day:每個月的某天(1-31),若是省略,則默認爲1。
  4. Hour:一天中的小時(0-23),若是省略,則默認爲0。
  5. Minutes:分鐘(0-59),若是省略,則默認爲0。
  6. Seconds:秒(0-59),若是省略,則默認爲0。
  7. Milliseconds:毫秒(0-999),若是省略,則默認爲0。
// 11th June 2019, 5:23:59am, Local Time
new Date(2019, 5, 11, 5, 23, 59)

許多開發人員比較少用這種方式,由於它看起來很複雜,但它實際上很是簡單。能夠從左到右記憶:年、月、日、小時、分鐘、秒和毫秒。

Date 中須要注意的地方Month是從0開始的,如1月=== 0,2月=== 1,3月=== 2,依此類推。

再來一些事件熟悉一下多個參數的用法

// 21st March 1988, 12am, Local Time.
new Date(1988, 2, 21)

// 25th December 2019, 8am, Local Time.
new Date(2019, 11, 25, 8)

// 6th November 2023, 2:20am, Local Time
new Date(2023, 10, 6, 2, 20)

// 11th June 2019, 5:23:59am, Local Time
new Date(2019, 5, 11, 5, 23, 59)

注意,使用參數建立的日期都是用本地時間

使用參數的還有一個好處是不會在本地時間和UTC之間混淆,若是須要UTC時間,請以這種方式建立UTC 日期:

// 11th June 2019, 12am, UTC.
new Date(Date.UTC(2019, 5, 11))

使用時間戳來建立日期

在JS中,時間戳是自1970年1月1日以來通過的毫秒數(1970年1月1日也稱爲Unix紀元時間)。 根據個人經驗,不多使用時間戳來建立日期,通常使用時間戳來比較不一樣的日期或者格式化日期,後面在討論。

不帶參數的形式建立日期

若是建立沒有任何參數的日期,則會將日期設置爲當前時間(以本地時間爲單位)。

new Date()

clipboard.png

小結一波

  1. 使用 new Date() 建立日期
  2. 有四種可能的語法:

    • 使用字符串日期值
    • 使用一系列參數
    • 使用時間戳
    • 不帶參數
  3. 最好不要使用字符串日期值的方法建立日期
  4. 最好使用一系列參數方式建立日期
  5. 記住月份是從0開始的

格式化日期

多數編程語言都提供了一種格式工具來創您想要的任何日期格式 例如,在PHP中,能夠將date("d M Y")格式化成23 1月 2019這樣的日期。

可是在JS 中格式化日期並不容易。

原生 Date 對象提供了七種格式化方法,這七種方法中的每一種都會給你一個特定的價值,並且它們毫無用處。

const date = new Date(2019, 0, 23, 17, 23, 42)
  1. toString:格式化成 "Wed Jan 23 2019 17:23:42 GMT+0800 (中國標準時間)"
  2. toDateString: 格式化成 "Wed Jan 23 2019"
  3. toLocaleString:格式化成 "2019/1/23 下午5:23:42"
  4. toLocaleDateString:格式化成 "2019/1/23"
  5. toGMTString:格式化成 "Wed, 23 Jan 2019 09:23:42 GMT"
  6. toUTCString:格式化成 "Wed, 23 Jan 2019 09:23:42 GMT"
  7. toISOString :格式化成 "2019-01-23T09:23:42.000Z"

若是須要自定義格式,則要本身建立。

編寫自定義日期格式

假設想要 2019年1月23日 星期四這樣的日期格式。須要知道 Date對象日期方法。

要獲取這樣的格式,用到 Date 中的四個方法:

  1. getFullYear:獲取當地時間4位數的年份
  2. getMonth:獲取當時時間的月份,注意從 0 開始
  3. getDate:獲取當地時間月中的某一天(1-31)
  4. getDay:獲取當地時間的星期幾(0-6),星期日(0)開始,到星期六(6)結束。
const d = new Date(2019, 0, 23)
const year = d.getFullYear() // 2019
const date = d.getDate() // 23

由於星期和月份是從0開始的,因此咱們能夠建立一個映射表:

const months = {
  0: '1月',
  1: '2月',
  2: '3月',
  3: '4月',
  4: '5月',
  5: '6月',
  6: '7月',
  7: '8月',
  8: '9月',
  9: '10月',
  10: '11月',
  11: '12月'
}

因爲月份是0開始的的,咱們可使用數組代替對象,結果同樣:

const months = [
  '1月',
  '2月',
  '3月',
  '4月',
  '5月',
  '6月',
  '7月',
  '8月',
  '9月',
  '10月',
  '11月',
  '12月'
}

要獲得1月份,你須要

const monthIndex = d.getMonth()
const monthName = months[monthIndex]
console.log(monthName) // 1月

簡化一下:

const monthName = months(d.getMonth())
console.log(monthName) // 1月

爲了獲取 星期四,還須要 作一樣的事情:

const days = [
  '星期日',
  '星期一',
  '星期二',
  '星期三',
  '星期四',
  '星期五',
  '星期六'
]

獲取方式:

const dayName = days[d.getDay()] // 星期四

接着就產拼接起來。這是相對乏味的。

若是須要建立自定義格式的時間,可使用如下方法

  1. getHours:獲取當地時間獲取小時數(0-23)。
  2. getMinutes:獲取本地時間獲取分鐘(0-59)。
  3. getSeconds:獲取本地時間獲取秒數(0-59)。
  4. getMilliseconds:獲取本地時間獲取毫秒(0-999)。

日期的比較

比較日期的先後,能夠直接使用>, <, >=<= 時行比較。

const earlier = new Date(2019, 0, 26)
const later = new Date(2019, 0, 27)

console.log(earlier < later) // true

比較兩個日期是否同樣,就比較麻煩,不能直接用 =====

const a = new Date(2019, 0, 26)
const b = new Date(2019, 0, 26)

console.log(a == b) // false
console.log(a === b) // false

能夠getTime獲取它們的時間戳,用時間戳進行比較。

const isSameTime = (a, b) => {
  return a.getTime() === b.getTime()
}

const a = new Date(2019, 0, 26)
const b = new Date(2019, 0, 26)
console.log(isSameTime(a, b)) // true

若是隻想檢查兩個日期是否在同一天,能夠比較他們的getFullYeargetMonthgetDate值。

const isSameDay = (a, b) => {
  return a.getFullYear() === b.getFullYear() &&
    a.getMonth() === b.getMonth() &&
    a.getDate()=== b.getDate()
}

const a = new Date(2019, 0, 26, 10) // 26 Jan 2019, 10am
const b = new Date(2019, 0, 26, 12) // 26 Jan 2019, 12pm
console.log(isSameDay(a, b)) // true

從另外一個日期獲取日期

有兩種可能的狀況,但願從另外一個日期得到一個日期。

  1. 設置另外一個日期特定的日期/時間值
  2. 從另外一個日期添加/減去增量

設置另外一個日期特定的日期/時間值

可使用如下方法設置另外一個日期的日期/時間:

  1. setFullYear: 設置年份
  2. setMonth:設置月份
  3. setDate:設置每個月的某一天
  4. setHours:設置時
  5. setNubytes:設置分
  6. setSeconds:設置秒
  7. setMilliseconds:設置毫秒

例如,若是想將日期設置爲每個月15日,可使用setDate(15)

const d = new Date(2019, 0, 10)
d.setDate(15)

console.log(d) // 15 January 2019
注意:上面的 setter方法會改變原始日期對象。 在實際中,咱們不該該改變對象,應該在新的日期對象上執行這些操做。
const d = new Date(2019, 0, 10)
const newDate = new Date(d)
newDate.setMonth(5)

console.log(d) // 10 January 2019
console.log(newDate) // 10 June 2019

從另外一個日期添加/減去增量

添加/減去增量有兩種通用方法。 第一種方法在Stack Overflow上更受歡迎,它簡潔,但更難掌握。 第二種方法更冗長,但更容易理解。

假設但願得到從今天起三天的日期。 對於這個例子,假設今天是2019年3月28日

第一種方法

const today = new Date(2019, 2, 28)

首先,咱們建立一個新的Date對象,這樣就不會改變原始日期

const finalDate = new Date(today)

接下來,咱們須要知道要更改的值。由於咱們要改變日期,因此咱們能夠用getDate得到日期

const currentDate = today.getDate()

由於獲取三天後的日期,因此須要在獲得的日期加3

setDate(currentDate + 3)

完整代碼:

const today = new Date(2019, 2, 28)
const finalDate = new Date(today)
finalDate.setDate(today.getDate() + 3)

console.log(finalDate) // 31 March 2019

第二種方法

使用getFullYeargetMonthgetDate方法,更改對應的值, 而後,咱們使用new Date建立最終日期。

const today = new Date(2019, 2, 28)

// Getting required values
const year = today.getFullYear()
const month = today.getMonh()
const day = today.getDate()

// Creating a new Date (with the delta)
const finalDate = new Date(year, month, day + 3)

console.log(finalDate) // 31 March 2019

自動日期校訂

若是爲Date提供一個超出其可接受範圍的值,JS 將自動從新計算日期。

以下所示,假設咱們把日期定在2019年3月33日,日曆上沒有33日,JS 會自動將3月33日調整爲4月2日

clipboard.png

這意味着在建立增量時無需擔憂計算分鐘,小時,天,月等,JavaScript會自動處理。

clipboard.png

代碼部署後可能存在的BUG無法實時知道,過後爲了解決這些BUG,花了大量的時間進行log 調試,這邊順便給你們推薦一個好用的BUG監控工具 Fundebug

交流

乾貨系列文章彙總以下,以爲不錯點個Star,歡迎 加羣 互相學習。

https://github.com/qq44924588...

我是小智,公衆號「大遷世界」做者,對前端技術保持學習愛好者。我會常常分享本身所學所看的乾貨,在進階的路上,共勉!

關注公衆號,後臺回覆福利,便可看到福利,你懂的。

clipboard.png

相關文章
相關標籤/搜索