讓我們來學(xué)習(xí)一個新的內(nèi)建對象:日期(Date)。該對象存儲日期和時間,并提供了日期/時間的管理方法。
我們可以使用它來存儲創(chuàng)建/修改時間,測量時間,或者僅用來打印當(dāng)前時間。
調(diào)用 new Date()
來創(chuàng)建一個新的 Date
對象。在調(diào)用時可以帶有一些參數(shù),如下所示:
?new Date()
?
不帶參數(shù) —— 創(chuàng)建一個表示當(dāng)前日期和時間的 Date
對象:
let now = new Date();
alert( now ); // 顯示當(dāng)前的日期/時間
?new Date(milliseconds)
?
創(chuàng)建一個 Date
對象,其時間等于 1970 年 1 月 1 日 UTC+0 之后經(jīng)過的毫秒數(shù)(1/1000 秒)。
// 0 表示 01.01.1970 UTC+0
let Jan01_1970 = new Date(0);
alert( Jan01_1970 );
// 現(xiàn)在增加 24 小時,得到 02.01.1970 UTC+0
let Jan02_1970 = new Date(24 * 3600 * 1000);
alert( Jan02_1970 );
傳入的整數(shù)參數(shù)代表的是自 1970-01-01 00:00:00 以來經(jīng)過的毫秒數(shù),該整數(shù)被稱為 時間戳。
這是一種日期的輕量級數(shù)字表示形式。我們通常使用 new Date(timestamp)
通過時間戳來創(chuàng)建日期,并可以使用 date.getTime()
將現(xiàn)有的 Date
對象轉(zhuǎn)化為時間戳(下文會講到)。
在 01.01.1970 之前的日期帶有負(fù)的時間戳,例如:
// 31 Dec 1969
let Dec31_1969 = new Date(-24 * 3600 * 1000);
alert( Dec31_1969 );
?new Date(datestring)
?
如果只有一個參數(shù),并且是字符串,那么它會被自動解析。該算法與 Date.parse
所使用的算法相同,將在下文中進行介紹。
let date = new Date("2017-01-26");
alert(date);
// 未指定具體時間,所以假定時間為格林尼治標(biāo)準(zhǔn)時間(GMT)的午夜零點
// 并根據(jù)運行代碼時的用戶的時區(qū)進行調(diào)整
// 因此,結(jié)果可能是
// Thu Jan 26 2017 11:00:00 GMT+1100 (Australian Eastern Daylight Time)
// 或
// Wed Jan 25 2017 16:00:00 GMT-0800 (Pacific Standard Time)
?new Date(year, month, date, hours, minutes, seconds, ms)
?
使用當(dāng)前時區(qū)中的給定組件創(chuàng)建日期。只有前兩個參數(shù)是必須的。
year
? 應(yīng)該是四位數(shù)。為了兼容性,也接受 2 位數(shù),并將其視為 ?19xx
?,例如 ?98
? 與 ?1998
? 相同,但強烈建議始終使用 4 位數(shù)。month
? 計數(shù)從 ?0
?(一月)開始,到 ?11
?(十二月)結(jié)束。date
? 是當(dāng)月的具體某一天,如果缺失,則為默認(rèn)值 ?1
?。hours/minutes/seconds/ms
? 缺失,則均為默認(rèn)值 ?0
?。例如:
new Date(2011, 0, 1, 0, 0, 0, 0); // 1 Jan 2011, 00:00:00
new Date(2011, 0, 1); // 同樣,時分秒等均為默認(rèn)值 0
時間度量最大精確到 1 毫秒(1/1000 秒):
let date = new Date(2011, 0, 1, 2, 3, 4, 567);
alert( date ); // 1.01.2011, 02:03:04.567
從 Date
對象中訪問年、月等信息有多種方式:
獲取年份(4 位數(shù))
獲取月份,從 0 到 11。
獲取當(dāng)月的具體日期,從 1 到 31,這個方法名稱可能看起來有些令人疑惑。
getHours(),getMinutes(), getSeconds(),getMilliseconds()
獲取相應(yīng)的時間組件。
不是 ?
getYear()
?,而是 ?getFullYear()
?很多 JavaScript 引擎都實現(xiàn)了一個非標(biāo)準(zhǔn)化的方法
getYear()
。不推薦使用這個方法。它有時候可能會返回 2 位的年份信息。永遠(yuǎn)不要使用它。要獲取年份就使用getFullYear()
。
另外,我們還可以獲取一周中的第幾天:
獲取一周中的第幾天,從 0
(星期日)到 6
(星期六)。第一天始終是星期日,在某些國家可能不是這樣的習(xí)慣,但是這不能被改變。
以上的所有方法返回的組件都是基于當(dāng)?shù)貢r區(qū)的。
當(dāng)然,也有與當(dāng)?shù)貢r區(qū)的 UTC 對應(yīng)項,它們會返回基于 UTC+0 時區(qū)的日、月、年等:getUTCFullYear(),getUTCMonth(),getUTCDay()。只需要在 "get"
之后插入 "UTC"
即可。
如果你當(dāng)?shù)貢r區(qū)相對于 UTC 有偏移,那么下面代碼會顯示不同的小時數(shù):
// 當(dāng)前日期
let date = new Date();
// 當(dāng)?shù)貢r區(qū)的小時數(shù)
alert( date.getHours() );
// 在 UTC+0 時區(qū)的小時數(shù)(非夏令時的倫敦時間)
alert( date.getUTCHours() );
除了上述給定的方法,還有兩個沒有 UTC 變體的特殊方法:
返回日期的時間戳 —— 從 1970-1-1 00:00:00 UTC+0 開始到現(xiàn)在所經(jīng)過的毫秒數(shù)。
返回 UTC 與本地時區(qū)之間的時差,以分鐘為單位:
// 如果你在時區(qū) UTC-1,輸出 60
// 如果你在時區(qū) UTC+3,輸出 -180
alert( new Date().getTimezoneOffset() );
下列方法可以設(shè)置日期/時間組件:
以上方法除了 setTime()
都有 UTC 變體,例如:setUTCHours()
。
我們可以看到,有些方法可以一次性設(shè)置多個組件,比如 ?setHours
?。未提及的組件不會被修改。
舉個例子:
let today = new Date();
today.setHours(0);
alert(today); // 日期依然是今天,但是小時數(shù)被改為了 0
today.setHours(0, 0, 0, 0);
alert(today); // 日期依然是今天,時間為 00:00:00。
自動校準(zhǔn) 是 Date
對象的一個非常方便的特性。我們可以設(shè)置超范圍的數(shù)值,它會自動校準(zhǔn)。
舉個例子:
let date = new Date(2013, 0, 32); // 32 Jan 2013 ?!?
alert(date); // ……是 1st Feb 2013!
超出范圍的日期組件將會被自動分配。
假設(shè)我們要在日期 “28 Feb 2016” 上加 2 天。結(jié)果可能是 “2 Mar” 或 “1 Mar”,因為存在閏年。但是我們不需要考慮這些,只需要直接加 2 天,剩下的 Date
對象會幫我們處理:
let date = new Date(2016, 1, 28);
date.setDate(date.getDate() + 2);
alert( date ); // 1 Mar 2016
這個特性經(jīng)常被用來獲取給定時間段后的日期。例如,我們想獲取“現(xiàn)在 70 秒后”的日期:
let date = new Date();
date.setSeconds(date.getSeconds() + 70);
alert( date ); // 顯示正確的日期信息
我們還可以設(shè)置 0 甚至可以設(shè)置負(fù)值。例如:
let date = new Date(2016, 0, 2); // 2016 年 1 月 2 日
date.setDate(1); // 設(shè)置為當(dāng)月的第一天
alert( date );
date.setDate(0); // 天數(shù)最小可以設(shè)置為 1,所以這里設(shè)置的是上一月的最后一天
alert( date ); // 31 Dec 2015
當(dāng) Date
對象被轉(zhuǎn)化為數(shù)字時,得到的是對應(yīng)的時間戳,與使用 date.getTime()
的結(jié)果相同:
let date = new Date();
alert(+date); // 以毫秒為單位的數(shù)值,與使用 date.getTime() 的結(jié)果相同
有一個重要的副作用:日期可以相減,相減的結(jié)果是以毫秒為單位時間差。
這個作用可以用于時間測量:
let start = new Date(); // 開始測量時間
// do the job
for (let i = 0; i < 100000; i++) {
let doSomething = i * i * i;
}
let end = new Date(); // 結(jié)束測量時間
alert( `The loop took ${end - start} ms` );
如果我們僅僅想要測量時間間隔,我們不需要 Date
對象。
有一個特殊的方法 Date.now()
,它會返回當(dāng)前的時間戳。
它相當(dāng)于 new Date().getTime()
,但它不會創(chuàng)建中間的 Date
對象。因此它更快,而且不會對垃圾回收造成額外的壓力。
這種方法很多時候因為方便,又或是因性能方面的考慮而被采用,例如使用 JavaScript 編寫游戲或其他的特殊應(yīng)用場景。
因此這樣做可能會更好:
let start = Date.now(); // 從 1 Jan 1970 至今的時間戳
// do the job
for (let i = 0; i < 100000; i++) {
let doSomething = i * i * i;
}
let end = Date.now(); // 完成
alert( `The loop took ${end - start} ms` ); // 相減的是時間戳,而不是日期
在對一個很耗 CPU 性能的函數(shù)進行可靠的基準(zhǔn)測試(Benchmarking)時,我們需要謹(jǐn)慎一點。
例如,我們想判斷以下兩個計算日期差值的函數(shù):哪個更快?
這種性能測量通常稱為“基準(zhǔn)測試(benchmark)”。
// 我們有 date1 和 date2,哪個函數(shù)會更快地返回兩者的時間差?
function diffSubtract(date1, date2) {
return date2 - date1;
}
// or
function diffGetTime(date1, date2) {
return date2.getTime() - date1.getTime();
}
這兩個函數(shù)做的事情完全相同,但是其中一個函數(shù)使用顯式的 date.getTime()
來獲取毫秒形式的日期,另一個則依賴于“日期 — 數(shù)字”的轉(zhuǎn)換。它們的結(jié)果是一樣的。
那么,哪個更快呢?
首先想到的方法可能是連續(xù)運行兩者很多次,并計算所消耗的時間之差。就這個例子而言,函數(shù)過于簡單,所以我們必須執(zhí)行至少 100000 次。
讓我們開始測量:
function diffSubtract(date1, date2) {
return date2 - date1;
}
function diffGetTime(date1, date2) {
return date2.getTime() - date1.getTime();
}
function bench(f) {
let date1 = new Date(0);
let date2 = new Date();
let start = Date.now();
for (let i = 0; i < 100000; i++) f(date1, date2);
return Date.now() - start;
}
alert( 'Time of diffSubtract: ' + bench(diffSubtract) + 'ms' );
alert( 'Time of diffGetTime: ' + bench(diffGetTime) + 'ms' );
看起來使用 getTime()
這種方式快得多,這是因為它沒有進行類型轉(zhuǎn)換,對引擎優(yōu)化來說更加簡單。
我們得到了結(jié)論,但是這并不是一個很好的度量的例子。
想象一下當(dāng)運行 bench(diffSubtract)
的同時,CPU 還在并行處理其他事務(wù),并且這也會占用資源。然而,運行 bench(diffGetTime)
的時候,并行處理的事務(wù)完成了。
對于現(xiàn)代多進程操作系統(tǒng)來說,這是一個非常常見的場景。
比起第二個函數(shù),第一個函數(shù)所能使用的 CPU 資源更少。這可能導(dǎo)致錯誤的結(jié)論。
為了得到更加可靠的度量,整個度量測試包應(yīng)該重新運行多次。
例如,像下面的代碼這樣:
function diffSubtract(date1, date2) {
return date2 - date1;
}
function diffGetTime(date1, date2) {
return date2.getTime() - date1.getTime();
}
function bench(f) {
let date1 = new Date(0);
let date2 = new Date();
let start = Date.now();
for (let i = 0; i < 100000; i++) f(date1, date2);
return Date.now() - start;
}
let time1 = 0;
let time2 = 0;
// 交替運行 bench(diffSubtract) 和 bench(diffGetTime) 各 10 次
for (let i = 0; i < 10; i++) {
time1 += bench(diffSubtract);
time2 += bench(diffGetTime);
}
alert( 'Total time for diffSubtract: ' + time1 );
alert( 'Total time for diffGetTime: ' + time2 );
現(xiàn)代的 JavaScript 引擎的先進優(yōu)化策略只對執(zhí)行很多次的 “hot code” 有效(對于執(zhí)行很少次數(shù)的代碼沒有必要優(yōu)化)。因此,在上面的例子中,第一次執(zhí)行的優(yōu)化程度不高。我們可能需要增加一個預(yù)熱步驟:
// 在主循環(huán)中增加預(yù)熱環(huán)節(jié)
bench(diffSubtract);
bench(diffGetTime);
// 開始度量
for (let i = 0; i < 10; i++) {
time1 += bench(diffSubtract);
time2 += bench(diffGetTime);
}
進行微型基準(zhǔn)測試時要小心
現(xiàn)代的 JavaScript 引擎執(zhí)行了很多優(yōu)化。與正常編寫的代碼相比,它們可能會改變“人為編寫的專用于測試的代碼”的執(zhí)行流程,特別是在我們對很小的代碼片段進行基準(zhǔn)測試時,例如某個運算符或內(nèi)建函數(shù)的工作方式。因此,為了深入理解性能問題,請學(xué)習(xí) JavaScript 引擎的工作原理。在那之后,你或許再也不需要進行微型基準(zhǔn)測試了。
http://mrale.ph 提供了很多 V8 引擎相關(guān)的文章。
Date.parse(str) 方法可以從一個字符串中讀取日期。
字符串的格式應(yīng)該為:YYYY-MM-DDTHH:mm:ss.sssZ
,其中:
YYYY-MM-DD
? —— 日期:年-月-日。"T"
? 是一個分隔符。HH:mm:ss.sss
? —— 時間:小時,分鐘,秒,毫秒。'Z'
? 為 ?+-hh:mm
? 格式的時區(qū)。單個字符 ?Z
? 代表 UTC+0 時區(qū)。簡短形式也是可以的,比如 YYYY-MM-DD
或 YYYY-MM
,甚至可以是 YYYY
。
Date.parse(str)
調(diào)用會解析給定格式的字符串,并返回時間戳(自 1970-01-01 00:00:00 起所經(jīng)過的毫秒數(shù))。如果給定字符串的格式不正確,則返回 NaN
。
舉個例子:
let ms = Date.parse('2012-01-26T13:51:50.417-07:00');
alert(ms); // 1327611110417 (時間戳)
我們可以通過時間戳來立即創(chuàng)建一個 new Date
對象:
let date = new Date( Date.parse('2012-01-26T13:51:50.417-07:00') );
alert(date);
Date
? 對象總是同時創(chuàng)建兩者。getDay()
? 同樣從 0 開始計算(0 代表星期日)。Date
? 會進行自動校準(zhǔn)。這一點對于日/月/小時的加減很有用。Date
? 被轉(zhuǎn)換為數(shù)字時,?Date
? 對象會被轉(zhuǎn)換為時間戳。Date.now()
? 可以更快地獲取當(dāng)前時間的時間戳。和其他系統(tǒng)不同,JavaScript 中時間戳以毫秒為單位,而不是秒。
有時我們需要更加精準(zhǔn)的時間度量。JavaScript 自身并沒有測量微秒的方法(百萬分之一秒),但大多數(shù)運行環(huán)境會提供。例如:瀏覽器有 performance.now() 方法來給出從頁面加載開始的以毫秒為單位的微秒數(shù)(精確到毫秒的小數(shù)點后三位):
alert(`Loading started ${performance.now()}ms ago`);
// 類似于 "Loading started 34731.26000000001ms ago"
// .26 表示的是微秒(260 微秒)
// 小數(shù)點后超過 3 位的數(shù)字是精度錯誤,只有前三位數(shù)字是正確的
Node.js 可以通過 microtime
模塊或使用其他方法。從技術(shù)上講,幾乎所有的設(shè)備和環(huán)境都允許獲取更高精度的時間數(shù)值,只不過不是使用 Date
對象。
創(chuàng)建一個 ?Date
? 對象,日期是:Feb 20, 2012, 3:12am。時區(qū)是當(dāng)?shù)貢r區(qū)。
使用 ?alert
? 顯示結(jié)果。
new Date
構(gòu)造函數(shù)默認(rèn)使用本地時區(qū)。所以唯一需要牢記的就是月份從 0 開始計數(shù)。
所以二月對應(yīng)的數(shù)值是 1。
這是一個以數(shù)字作為日期參數(shù)的示例:
// new Date(year, month, date, hour, minute, second, millisecond)
let d1 = new Date(2012, 1, 20, 3, 12);
alert( d1 );
我們還可以從字符串創(chuàng)建日期,像這樣:
// new Date(datestring)
let d2 = new Date("2012-02-20T03:12");
alert( d2 );
重要程度: 5
編寫一個函數(shù) ?getWeekDay(date)
? 以短格式來顯示一個日期的星期數(shù):‘MO’,‘TU’,‘WE’,‘TH’,‘FR’,‘SA’,‘SU’。
例如:
let date = new Date(2012, 0, 3); // 3 Jan 2012
alert( getWeekDay(date) ); // 應(yīng)該輸出 "TU"
date.getDay()
方法返回從星期日開始的星期數(shù)。
我們創(chuàng)建一個關(guān)于星期的數(shù)組,這樣我們就可以通過編號獲取正確的日期名稱:
function getWeekDay(date) {
let days = ['SU', 'MO', 'TU', 'WE', 'TH', 'FR', 'SA'];
return days[date.getDay()];
}
let date = new Date(2014, 0, 3); // 3 Jan 2014
alert( getWeekDay(date) ); // FR
重要程度: 5
歐洲國家的星期計算是從星期一(數(shù)字 1)開始的,然后是星期二(數(shù)字 2),直到星期日(數(shù)字 7)。編寫一個函數(shù) getLocalDay(date)
,并返回日期的歐洲式星期數(shù)。
let date = new Date(2012, 0, 3); // 3 Jan 2012
alert( getLocalDay(date) ); // 星期二,應(yīng)該顯示 2
function getLocalDay(date) {
let day = date.getDay();
if (day == 0) { // weekday 0 (sunday) is 7 in european
day = 7;
}
return day;
}
重要程度: 4
寫一個函數(shù) getDateAgo(date, days)
,返回特定日期 date
往前 days
天是哪個月的哪一天。
例如,假設(shè)今天是 20 號,那么 getDateAgo(new Date(), 1)
的結(jié)果應(yīng)該是 19 號,getDateAgo(new Date(), 2)
的結(jié)果應(yīng)該是 18 號。
跨月、年也應(yīng)該是正確輸出:
let date = new Date(2015, 0, 2);
alert( getDateAgo(date, 1) ); // 1, (1 Jan 2015)
alert( getDateAgo(date, 2) ); // 31, (31 Dec 2014)
alert( getDateAgo(date, 365) ); // 2, (2 Jan 2014)
P.S. 函數(shù)不應(yīng)該修改給定的 date
值。
思路很簡單:從 date
中減去給定的天數(shù):
function getDateAgo(date, days) {
date.setDate(date.getDate() - days);
return date.getDate();
}
……但是函數(shù)不能修改 date
。這一點很重要,因為我們提供日期的外部代碼不希望它被修改。
要實現(xiàn)這一點,我們可以復(fù)制這個日期,就像這樣:
function getDateAgo(date, days) {
let dateCopy = new Date(date);
dateCopy.setDate(date.getDate() - days);
return dateCopy.getDate();
}
let date = new Date(2015, 0, 2);
alert( getDateAgo(date, 1) ); // 1, (1 Jan 2015)
alert( getDateAgo(date, 2) ); // 31, (31 Dec 2014)
alert( getDateAgo(date, 365) ); // 2, (2 Jan 2014)
重要程度: 5
寫一個函數(shù) getLastDayOfMonth(year, month)
返回 month 月的最后一天。有時候是 30,有時是 31,甚至在二月的時候會是 28/29。
參數(shù):
year
? —— 四位數(shù)的年份,比如 2012。month
? —— 月份,從 0 到 11。舉個例子,?getLastDayOfMonth(2012, 1) = 29
?(閏年,二月)
讓我們使用下個月創(chuàng)建日期,但將零作為天數(shù)(day)傳遞:
function getLastDayOfMonth(year, month) {
let date = new Date(year, month + 1, 0);
return date.getDate();
}
alert( getLastDayOfMonth(2012, 0) ); // 31
alert( getLastDayOfMonth(2012, 1) ); // 29
alert( getLastDayOfMonth(2013, 1) ); // 28
通常,日期從 1 開始,但從技術(shù)上講,我們可以傳遞任何數(shù)字,日期會自動進行調(diào)整。因此,當(dāng)我們傳遞 0 時,它的意思是“一個月的第一天的前一天”,換句話說:“上個月的最后一天”。
重要程度: 5
寫一個函數(shù) getSecondsToday()
,返回今天已經(jīng)過去了多少秒?
例如:如果現(xiàn)在是 10:00 am
,并且沒有夏令時轉(zhuǎn)換,那么:
getSecondsToday() == 36000 // (3600 * 10)
該函數(shù)應(yīng)該在任意一天都能正確運行。那意味著,它不應(yīng)具有“今天”的硬編碼值。
為獲取秒數(shù),我們可以使用今天的日期和 00:00:00 這個時間創(chuàng)建一個日期,然后使用當(dāng)前時間減去該時間。
不同之處在于,從今天之初開始算起的時間是以毫秒計算的,我們應(yīng)該將其除以 1000,進而得到秒數(shù):
function getSecondsToday() {
let now = new Date();
// 使用當(dāng)前的 day/month/year 創(chuàng)建一個對象
let today = new Date(now.getFullYear(), now.getMonth(), now.getDate());
let diff = now - today; // ms difference
return Math.round(diff / 1000); // make seconds
}
alert( getSecondsToday() );
另一種解決方法是獲取 hours/minutes/seconds,然后把它們轉(zhuǎn)換為秒數(shù):
function getSecondsToday() {
let d = new Date();
return d.getHours() * 3600 + d.getMinutes() * 60 + d.getSeconds();
};
alert( getSecondsToday() );
重要程度: 5
寫一個函數(shù) getSecondsToTomorrow()
,返回距離明天的秒數(shù)。
例如,現(xiàn)在是 23:00
,那么:
getSecondsToTomorrow() == 3600
P.S. 該函數(shù)應(yīng)該在任意一天都能正確運行。那意味著,它不應(yīng)具有“今天”的硬編碼值。
為獲取距離明天的毫秒數(shù),我們可以用“明天 00:00:00”這個日期減去當(dāng)前的日期。
首先我們生成“明天”,然后對其進行減法操作:
function getSecondsToTomorrow() {
let now = new Date();
// tomorrow date
let tomorrow = new Date(now.getFullYear(), now.getMonth(), now.getDate()+1);
let diff = tomorrow - now; // difference in ms
return Math.round(diff / 1000); // convert to seconds
}
另一種解法:
function getSecondsToTomorrow() {
let now = new Date();
let hour = now.getHours();
let minutes = now.getMinutes();
let seconds = now.getSeconds();
let totalSecondsToday = (hour * 60 + minutes) * 60 + seconds;
let totalSecondsInADay = 86400;
return totalSecondsInADay - totalSecondsToday;
}
請注意,很多國家有夏令時(DST),因此他們的一天可能有 23 小時或者 25 小時。我們對這些天數(shù)要區(qū)別對待。
重要程度: 4
寫一個函數(shù) formatDate(date)
,能夠?qū)?nbsp;date
進行如下格式化:
date
? 距離現(xiàn)在不到 1 秒,輸出 ?"right now"
?。date
? 距離現(xiàn)在不到 1 分鐘,輸出 ?"n sec. ago"
?。"m min. ago"
?。"DD.MM.YY HH:mm"
? 格式輸出完整日期。即:?"day.month.year hours:minutes"
?,全部以兩位數(shù)格式表示,例如:?31.12.16 10:00
?。舉個例子:
alert( formatDate(new Date(new Date - 1)) ); // "right now"
alert( formatDate(new Date(new Date - 30 * 1000)) ); // "30 sec. ago"
alert( formatDate(new Date(new Date - 5 * 60 * 1000)) ); // "5 min. ago"
// 昨天的日期,例如 31.12.16 20:00
alert( formatDate(new Date(new Date - 86400 * 1000)) );
為了獲取 date
距離當(dāng)前時間的間隔 —— 我們將兩個日期相減。
function formatDate(date) {
let diff = new Date() - date; // 以毫秒表示的差值
if (diff < 1000) { // 少于 1 秒
return 'right now';
}
let sec = Math.floor(diff / 1000); // 將 diff 轉(zhuǎn)換為秒
if (sec < 60) {
return sec + ' sec. ago';
}
let min = Math.floor(diff / 60000); // 將 diff 轉(zhuǎn)換為分鐘
if (min < 60) {
return min + ' min. ago';
}
// 格式化 date
// 將前置 0 加到一位數(shù) day/month/hours/minutes 前
let d = date;
d = [
'0' + d.getDate(),
'0' + (d.getMonth() + 1),
'' + d.getFullYear(),
'0' + d.getHours(),
'0' + d.getMinutes()
].map(component => component.slice(-2)); // 得到每個組件的后兩位
// 將時間信息和日期組合在一起
return d.slice(0, 3).join('.') + ' ' + d.slice(3).join(':');
}
alert( formatDate(new Date(new Date - 1)) ); // "right now"
alert( formatDate(new Date(new Date - 30 * 1000)) ); // "30 sec. ago"
alert( formatDate(new Date(new Date - 5 * 60 * 1000)) ); // "5 min. ago"
// 昨天的日期如:31.12.2016 20:00
alert( formatDate(new Date(new Date - 86400 * 1000)) );
另一種解法:
function formatDate(date) {
let dayOfMonth = date.getDate();
let month = date.getMonth() + 1;
let year = date.getFullYear();
let hour = date.getHours();
let minutes = date.getMinutes();
let diffMs = new Date() - date;
let diffSec = Math.round(diffMs / 1000);
let diffMin = diffSec / 60;
let diffHour = diffMin / 60;
// 格式化
year = year.toString().slice(-2);
month = month < 10 ? '0' + month : month;
dayOfMonth = dayOfMonth < 10 ? '0' + dayOfMonth : dayOfMonth;
hour = hour < 10 ? '0' + hour : hour;
minutes = minutes < 10 ? '0' + minutes : minutes;
if (diffSec < 1) {
return 'right now';
} else if (diffMin < 1) {
return `${diffSec} sec. ago`
} else if (diffHour < 1) {
return `${diffMin} min. ago`
} else {
return `${dayOfMonth}.${month}.${year} ${hour}:${minutes}`
}
}
更多建議: