譯者:前端小智javascript
爲了保證的可讀性,本文采用意譯而非直譯。html
阿里雲最近在作活動,低至2折,有興趣能夠看看:promotion.aliyun.com/ntms/yunpar…前端
JS中的 Date 很奇怪。當咱們須要處理日期和時間的時候比較麻煩,常常藉助像date-fns和 Moment 這樣的庫。java
可是咱們並不老是須要使用庫。若是知道要注意一些老是,日期實際上能夠很是簡單。接下介紹有關Date
對象的全部信息git
咱們的世界有數百個時區。 在JavaScript中,咱們只關心兩個, 本地時間和協調世界時(UTC)。github
本地時間是指你的計算機所在的時區。編程
UTC其實是格林威治標準時間(GMT)的同義詞數組
默認狀況下,JS中的幾乎每一個日期方法(除了一個)都是本地時間。 只有指定UTC,才能得到 UTC 時間 。編程語言
可使用 new Date()
來建立日期,傳入的參數一般有4種經常使用的方式:
new Date('1988-03-21')
複製代碼
這種方式方便且直觀。
若是如今寫的是21-03-1988
,咱們能夠絕不費力想表達的是1988年3月21日。可是若是用JS 編寫21-03-1988,則會獲得無效的日期。
這是有緣由的。
在世界的不一樣地方以不一樣的方式解釋日期字符串。 例如11-06-2019
是2019年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日
。
若是你住在比格林威治標準時間早的地區,纔會等獲得6月11日
的日期。
發生這種狀況是由於日期字符串參數的方法具備特殊行爲:若是建立日期(未指定時間),則會得到UTC格式設置的日期。
在上面的場景中,使用new Date('2019-06-11')
建立日期時,實際上建立的日期是2019年6月11日,UTC時間上午12點。這就是爲何住在格林尼治標準時間以後的地區的人獲得的是6月10日
而不是6月11日
。
若是要使用日期字符串參數方法在「本地時間」中建立日期,則須要包括時間。若是包含時間,則須要至少寫入HH
和mm
new Date('2019-06-11T00:00')
複製代碼
使用日期字符串參數的建立的本地時間與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的功能與精確度是沒有差異的。
最多能夠傳入七個參數來建立日期/時間。
Year:4位數年份
Month:一年中的某月(0-11)
Day:每個月的某天(1-31),若是省略,則默認爲1。
Hour:一天中的小時(0-23),若是省略,則默認爲0。
Minutes:分鐘(0-59),若是省略,則默認爲0。
Seconds:秒(0-59),若是省略,則默認爲0。
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()
複製代碼
多數編程語言都提供了一種格式工具來創您想要的任何日期格式 例如,在PHP中,能夠將date("d M Y")
格式化成23 1月 2019
這樣的日期。
可是在JS 中格式化日期並不容易。
原生 Date
對象提供了七種格式化方法,這七種方法中的每一種都會給你一個特定的價值,並且它們毫無用處。
const date = new Date(2019, 0, 23, 17, 23, 42)
複製代碼
toString
:格式化成 "Wed Jan 23 2019 17:23:42 GMT+0800 (中國標準時間)"
toDateString
: 格式化成 "Wed Jan 23 2019"
toLocaleString
:格式化成 "2019/1/23 下午5:23:42"
toLocaleDateString
:格式化成 "2019/1/23"
toGMTString
:格式化成 "Wed, 23 Jan 2019 09:23:42 GMT"
toUTCString
:格式化成 "Wed, 23 Jan 2019 09:23:42 GMT"
toISOString
:格式化成 "2019-01-23T09:23:42.000Z"
若是須要自定義格式,則要本身建立。
假設想要 2019年1月23日 星期四
這樣的日期格式。須要知道 Date
對象日期方法。
要獲取這樣的格式,用到 Date
中的四個方法:
getFullYear
:獲取當地時間4位數的年份
getMonth
:獲取當時時間的月份,注意從 0 開始
getDate
:獲取當地時間月中的某一天(1-31)
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()] // 星期四
複製代碼
接着就產拼接起來。這是相對乏味的。
若是須要建立自定義格式的時間,可使用如下方法
getHours
:獲取當地時間獲取小時數(0-23)。
getMinutes
:獲取本地時間獲取分鐘(0-59)。
getSeconds
:獲取本地時間獲取秒數(0-59)。
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
複製代碼
若是隻想檢查兩個日期是否在同一天,能夠比較他們的getFullYear
,getMonth
和getDate
值。
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
複製代碼
有兩種可能的狀況,但願從另外一個日期得到一個日期。
可使用如下方法設置另外一個日期的日期/時間:
setFullYear
: 設置年份setMonth
:設置月份setDate
:設置每個月的某一天setHours
:設置時setMinutes
:設置分setSeconds
:設置秒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
複製代碼
使用getFullYear
,getMonth
,getDate
方法,更改對應的值, 而後,咱們使用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日
。
這意味着在建立增量時無需擔憂計算分鐘,小時,天,月等,JavaScript會自動處理。
代碼部署後可能存在的BUG無法實時知道,過後爲了解決這些BUG,花了大量的時間進行log 調試,這邊順便給你們推薦一個好用的BUG監控工具 Fundebug。
爲了回饋讀者,《大遷世界》不按期舉行(每月一到三次),現金抽獎活動,保底200,外加用戶讚揚,但願你能成爲大遷世界的小錦鯉,快來試試吧
乾貨系列文章彙總以下,以爲不錯點個Star,歡迎 加羣 互相學習。
我是小智,公衆號「大遷世界」做者,對前端技術保持學習愛好者。我會常常分享本身所學所看的乾貨,在進階的路上,共勉!
關注公衆號,後臺回覆福利,便可看到福利,你懂的。
每次整理文章,通常都到2點才睡覺,一週4次左右,挺苦的,還望支持,給點鼓勵