最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

JavaScript時間處理Date/moment/dayjs/Temporal方法全解

 更新時間:2026年03月25日 08:57:58   作者:無心水  
前端開發(fā)中,時間處理一直是個讓人頭疼的難題,本文系統(tǒng)梳理了JavaScript時間處理的演進歷程,從原生Date對象的缺陷到第三方庫的解決方案,文中的示例代碼講解詳細,希望對大家有所幫助

前端開發(fā)中,時間處理一直是個讓人頭疼的難題。new Date('2026-03-24') 在不同瀏覽器里結果不同;月份從0開始,11月居然寫成 10;想顯示“2小時前”還要自己寫算法……本文帶你系統(tǒng)梳理 JavaScript 時間處理的演進史,從原生 Date 的深坑,到 moment.js 的輝煌與落幕,再到輕量級 day.js 和函數式 date-fns 的崛起,最后展望未來的標準 Temporal API。讀完本文,你將徹底告別時間處理的噩夢,寫出健壯的前端時間代碼。

一、引言:JS時間處理的“噩夢”

1.1 Date對象的設計缺陷

JavaScript 的 Date 對象從誕生之初就充滿了槽點:

  • 易變性Date 對象是可變的,任何修改都會影響原對象,容易引發(fā)副作用
  • 月份從0開始new Date(2026, 2, 24) 表示的是 3月24日,而不是2月,這是最反直覺的設計之一
  • 時區(qū)模糊new Date() 返回的是本地時間,但 new Date('2026-03-24') 在不同瀏覽器可能被解析為UTC或本地時間,導致跨瀏覽器結果不一致
  • 解析行為不統(tǒng)一Date.parse() 對非標準字符串的解析依賴于實現(xiàn),例如 "2026-03-24 14:30:00" 在 Chrome 和 Safari 中可能返回不同的結果
  • 缺少人性化方法:沒有內置“相對時間”(如“2小時前”)的輸出,需要自己計算

1.2 真實案例:前端時間顯示錯誤

某 SaaS 系統(tǒng)的后臺管理頁面,后端返回訂單時間:"2026-03-24T06:30:00Z"(UTC)。前端直接 new Date(orderTime) 后調用 toLocaleString(),結果美國用戶看到的是 3/23/2026, 11:30:00 PM(因為 toLocaleString 默認使用用戶本地時區(qū),而 new Date 解析 ISO 字符串時會正確識別 UTC,但展示時轉成了本地)。產品經理投訴:訂單明明是今天創(chuàng)建的,為什么顯示為昨天?原來是因為時區(qū)轉換后,UTC 6:30 對應美國西部時間的前一天 22:30。

根源:前端沒有明確控制時區(qū)展示邏輯,依賴了瀏覽器的默認行為。

1.3 前端時間處理的痛點

  • 跨瀏覽器兼容性:不同瀏覽器對 Date 構造函數的字符串解析差異
  • 用戶時區(qū)感知:需要根據用戶所在時區(qū)展示時間(如中國用戶看北京時間,美國用戶看美東時間)
  • 國際化顯示:不同語言/地區(qū)的日期格式差異(如 03/24/2026 vs 24/03/2026
  • 性能與體積:移動端或首屏渲染要求庫體積盡可能小

本文將從原生 Date 入手,逐步升級到現(xiàn)代化方案,幫助你根據場景選擇最合適的時間處理方式。

二、原生Date對象:認清坑,用對場景

2.1 Date對象的底層邏輯

Date 對象在 JavaScript 中基于 Unix 時間戳(毫秒),存儲的是自 1970年1月1日 00:00:00 UTC 以來的毫秒數。時區(qū)信息完全由運行環(huán)境(操作系統(tǒng)/瀏覽器)提供,Date 對象本身不保存時區(qū)。

2.2 基礎操作

(1) 時間創(chuàng)建

// 當前時間(本地)
const now = new Date();
console.log(now); // Thu Mar 24 2026 14:30:00 GMT+0800 (中國標準時間)

// 從時間戳創(chuàng)建(毫秒)
const fromTimestamp = new Date(1742807400000);
console.log(fromTimestamp); // 2026-03-24T06:30:00.000Z (UTC)

// 從ISO字符串創(chuàng)建(推薦)
const iso = new Date('2026-03-24T06:30:00Z');
console.log(iso.toISOString()); // 2026-03-24T06:30:00.000Z

// 從年月日創(chuàng)建(注意月份從0開始)
const dt = new Date(2026, 2, 24, 14, 30, 0); // 2026-03-24 14:30:00 本地時間
console.log(dt); // Thu Mar 24 2026 14:30:00 GMT+0800 (中國標準時間)

(2) UTC方法 vs 本地方法

Date 對象提供了兩套獲取時間組件的方法:本地方法(基于系統(tǒng)時區(qū))和 UTC 方法(基于 UTC+0)。

const date = new Date('2026-03-24T14:30:00+08:00'); // 北京時間 14:30

console.log(date.getHours());       // 14 (本地小時,取決于系統(tǒng)時區(qū))
console.log(date.getUTCHours());    // 6  (UTC小時)
console.log(date.getMonth());       // 2  (3月,因為從0開始)
console.log(date.getUTCMonth());    // 2

(3) 格式化

Date 原生提供幾種格式化方法:

const d = new Date();

d.toString();           // "Thu Mar 24 2026 14:30:00 GMT+0800 (中國標準時間)"
d.toISOString();        // "2026-03-24T06:30:00.000Z"
d.toUTCString();        // "Tue, 24 Mar 2026 06:30:00 GMT"
d.toLocaleString();     // "2026/3/24 14:30:00" (取決于瀏覽器語言)
d.toLocaleDateString(); // "2026/3/24"

2.3 避坑指南(四個經典坑)

坑1:new Date('2026-03-24')是UTC還是本地?

答案:不同瀏覽器行為不一致!根據 ES5 規(guī)范,僅包含日期的 ISO 8601 字符串應解析為 UTC,但部分舊瀏覽器或非標準實現(xiàn)會當作本地時間。

// 在 Chrome 中:解析為 UTC
new Date('2026-03-24').toISOString(); // "2026-03-24T00:00:00.000Z"

// 在某些舊版 Safari 中:可能解析為本地時間
// 因此,強烈建議使用帶時間的完整 ISO 字符串,如 '2026-03-24T00:00:00Z'

解決方案:始終使用完整格式 '2026-03-24T00:00:00Z' 表示 UTC 日期,或使用 new Date(Date.UTC(2026, 2, 24)) 構造 UTC 時間。

坑2:月份從0開始

const month = new Date().getMonth(); // 3月 => 2

解決方案:封裝輔助函數,或者使用第三方庫。

function getRealMonth(date) {
    return date.getMonth() + 1;
}

坑3:Date對象是可變的

const date1 = new Date();
const date2 = date1;
date2.setDate(10); // date1 也被修改了!

解決方案:需要拷貝時,使用 new Date(date1) 創(chuàng)建新對象。

坑4:解析非標準時間字符串的兼容性問題

const d = new Date('2026-03-24 14:30:00'); // 非 ISO 格式,可能返回 Invalid Date

解決方案:永遠不要用 Date 解析非標準格式。要么用正則拆解,要么用第三方庫。

2.4 原生Date的適用場景

  • 簡單的本地時間展示(不涉及時區(qū)轉換)
  • 獲取當前時間戳(Date.now()
  • 輕量級場景,且你已清楚上述坑并做了規(guī)避

對于復雜的時區(qū)、格式化和相對時間,建議使用第三方庫。

圖1:Date對象常見坑點圖示——用思維導圖展示月份從0、可變性、解析不一致、UTC/本地混淆四個坑點及其解決方案。

三、第三方庫:從moment.js到day.js

3.1 moment.js:經典但笨重

moment.js 曾經是前端時間處理的王者,功能強大,但體積較大(約 200KB+),且不支持 Tree Shaking。目前官方已進入維護模式,不再添加新功能,推薦使用更現(xiàn)代的替代品。

核心功能示例

// 安裝:npm install moment
import moment from 'moment';

// 創(chuàng)建
const now = moment();                     // 當前時間
const utc = moment.utc();                 // UTC時間
const fromStr = moment('2026-03-24T14:30:00+08:00'); // 自動識別

// 時區(qū)轉換(需要 moment-timezone 擴展)
import momentTz from 'moment-timezone';
const beijing = moment.tz('Asia/Shanghai');
const newYork = beijing.clone().tz('America/New_York');

// 格式化
now.format('YYYY-MM-DD HH:mm:ss'); // 2026-03-24 14:30:00

// 相對時間
now.fromNow(); // "2 hours ago"

// 運算
now.add(1, 'day').subtract(2, 'hours');

局限性

  • 體積大,影響首屏加載
  • 可變性(add/subtract 會修改原對象),容易出bug
  • 官方已停止功能開發(fā),僅維護安全漏洞

3.2 day.js:輕量替代(2KB)

day.js 的 API 與 moment.js 幾乎一致,但體積僅 2KB,支持插件擴展,是目前最受歡迎的輕量級時間庫。

安裝與使用

npm install dayjs
import dayjs from 'dayjs';
import utc from 'dayjs/plugin/utc';
import timezone from 'dayjs/plugin/timezone';
import relativeTime from 'dayjs/plugin/relativeTime';
import 'dayjs/locale/zh-cn';

// 擴展插件
dayjs.extend(utc);
dayjs.extend(timezone);
dayjs.extend(relativeTime);
dayjs.locale('zh-cn'); // 設置中文

// 基礎操作
const now = dayjs();                     // 當前時間(本地)
const utcNow = dayjs.utc();              // UTC時間
const parsed = dayjs('2026-03-24T14:30:00+08:00');

// 時區(qū)轉換
const beijing = dayjs.tz('2026-03-24 14:30:00', 'Asia/Shanghai');
const newYork = beijing.tz('America/New_York');
console.log(newYork.format()); // 2026-03-24T02:30:00-04:00

// 格式化
console.log(now.format('YYYY-MM-DD HH:mm:ss')); // 2026-03-24 14:30:00

// 相對時間
console.log(now.fromNow()); // "2小時前"

// 運算(不可變,返回新對象)
const tomorrow = now.add(1, 'day');

day.js + 時區(qū)插件實現(xiàn) UTC ↔ 北京時間互轉

// UTC 轉北京時間
const utcTime = dayjs.utc('2026-03-24T06:30:00Z');
const beijingTime = utcTime.tz('Asia/Shanghai');
console.log(beijingTime.format()); // 2026-03-24T14:30:00+08:00

// 北京時間轉 UTC
const beijing = dayjs.tz('2026-03-24 14:30:00', 'Asia/Shanghai');
const utc = beijing.utc();
console.log(utc.format()); // 2026-03-24T06:30:00Z

3.3 date-fns:函數式時間處理

date-fns 采用純函數、按需導入的方式,每個功能都是獨立函數,體積小,適合現(xiàn)代打包工具。

安裝與使用

npm install date-fns
import { format, addDays, differenceInHours, formatDistance } from 'date-fns';
import { zhCN } from 'date-fns/locale';

const now = new Date();

// 格式化
console.log(format(now, 'yyyy-MM-dd HH:mm:ss')); // 2026-03-24 14:30:00

// 運算(返回新對象)
const tomorrow = addDays(now, 1);

// 時間差
const diff = differenceInHours(tomorrow, now); // 24

// 相對時間
console.log(formatDistance(now, addDays(now, 2), { locale: zhCN })); // "2天"

date-fns 的優(yōu)勢

  • 完全按需,打包后體積小
  • 不可變性,純函數,易于測試
  • 支持時區(qū)(通過 date-fns-tz 擴展包)

3.4 庫選型建議

體積特點適用場景
moment.js~200KB功能全面,API 穩(wěn)定老舊項目維護,不推薦新項目
day.js~2KB輕量,API 兼容 moment,插件化大多數新項目,需時區(qū)/相對時間
date-fns按需函數式,不可變,無副作用追求打包體積、使用現(xiàn)代開發(fā)模式
原生 Date0無依賴極簡場景,且已充分了解坑點

圖2:庫選型對比圖——表格形式展示 moment、dayjs、date-fns、原生在體積、API風格、功能完整性、推薦指數上的對比。

四、未來標準:Temporal API

4.1 Temporal API 的設計目標

Temporal 是 TC39 正在推進的提案,旨在徹底解決 Date 對象的所有缺陷。它提供了不可變、語義清晰、支持時區(qū)、支持高精度時間的新 API。

核心特性

  • 不可變性:所有操作返回新對象
  • 明確的類型:區(qū)分帶時區(qū)的時間、無時區(qū)日期、無時區(qū)時間、時間段等
  • 支持時區(qū):內置 IANA 時區(qū)數據庫
  • 支持高精度:納秒級精度
  • 直觀的 API:年份從1開始,月份從1開始,無需再記憶坑點

4.2 核心類解析

說明示例
Temporal.Instant絕對的納秒級時間點(類似 Unix 時間戳)用于機器存儲
Temporal.ZonedDateTime帶時區(qū)的日期時間(推薦業(yè)務使用)2026-03-24T14:30:00+08:00[Asia/Shanghai]
Temporal.PlainDate不帶時區(qū)的日期(生日、紀念日)2026-03-24
Temporal.PlainTime不帶日期的時間14:30:00
Temporal.PlainDateTime不帶時區(qū)的日期+時間2026-03-24T14:30:00
Temporal.Duration時間段(支持年/月/日/時/分/秒/毫秒/微秒/納秒){ hours: 2, minutes: 30 }

4.3 實戰(zhàn)案例

(1) 創(chuàng)建 UTC 時間和本地時間

// 當前 UTC 時間(Instant)
const now = Temporal.Now.instant();
console.log(now.toString()); // 2026-03-24T06:30:00.123456789Z

// 當前系統(tǒng)時區(qū)的 ZonedDateTime
const nowInLocal = Temporal.Now.zonedDateTimeISO();
console.log(nowInLocal.toString()); // 2026-03-24T14:30:00.123456789+08:00[Asia/Shanghai]

// 從 ISO 字符串創(chuàng)建 ZonedDateTime
const beijing = Temporal.ZonedDateTime.from('2026-03-24T14:30:00+08:00[Asia/Shanghai]');
console.log(beijing.toString()); // 2026-03-24T14:30:00+08:00[Asia/Shanghai]

(2) 時區(qū)轉換

const beijing = Temporal.ZonedDateTime.from('2026-03-24T14:30:00+08:00[Asia/Shanghai]');
const newYork = beijing.withTimeZone('America/New_York');
console.log(newYork.toString()); // 2026-03-24T02:30:00-04:00[America/New_York]

(3) 時間運算

const now = Temporal.Now.zonedDateTimeISO();

// 加 2 天 3 小時
const later = now.add({ days: 2, hours: 3 });

// 時間差
const diff = now.until(later);
console.log(diff.total({ unit: 'hours' })); // 51

(4) 無時區(qū)日期處理

const date = Temporal.PlainDate.from('2026-03-24');
const nextMonth = date.add({ months: 1 });
console.log(nextMonth.toString()); // 2026-04-24

4.4 如何提前使用 Temporal

目前 Temporal 提案處于 Stage 3,尚未被所有瀏覽器原生支持。但可以通過 polyfill 提前體驗:

npm install @js-temporal/polyfill
import { Temporal } from '@js-temporal/polyfill';

const now = Temporal.Now.zonedDateTimeISO();
console.log(now.toString());

生產環(huán)境建議:待 Temporal 正式成為標準后,再逐步遷移。目前仍推薦 day.js 或 date-fns。

圖3:Temporal 核心類關系圖——展示 Instant、ZonedDateTime、PlainDate 等類的關系及各自用途。

五、前端實戰(zhàn):用戶時區(qū)與國際化

5.1 獲取用戶時區(qū)

瀏覽器提供了 Intl.DateTimeFormat().resolvedOptions().timeZone 來獲取用戶的時區(qū) ID:

const userTimeZone = Intl.DateTimeFormat().resolvedOptions().timeZone;
console.log(userTimeZone); // "Asia/Shanghai" 或 "America/New_York"

這個時區(qū) ID 是 IANA 標準格式(如 Asia/Shanghai),可直接用于 day.js 或 Temporal。

5.2 后端返回 UTC,前端轉換本地

假設后端 API 返回 ISO 8601 UTC 字符串:

{
  "create_time_utc": "2026-03-24T06:30:00Z"
}

前端使用 day.js 轉換:

import dayjs from 'dayjs';
import utc from 'dayjs/plugin/utc';
import timezone from 'dayjs/plugin/timezone';

dayjs.extend(utc);
dayjs.extend(timezone);

const utcTime = dayjs.utc('2026-03-24T06:30:00Z');
const localTime = utcTime.tz(userTimeZone);
console.log(localTime.format('YYYY-MM-DD HH:mm:ss')); // 根據用戶時區(qū)顯示

5.3 國際化顯示(多語言日期格式)

使用 Intl.DateTimeFormat 或 day.js 的 locale 插件:

// 原生 Intl
const date = new Date('2026-03-24T14:30:00Z');
const formatter = new Intl.DateTimeFormat('zh-CN', {
    dateStyle: 'full',
    timeStyle: 'medium',
    timeZone: 'Asia/Shanghai'
});
console.log(formatter.format(date)); // 2026年3月24日星期二 22:30:00

// day.js 國際化
import 'dayjs/locale/zh-cn';
import 'dayjs/locale/en';
dayjs.locale('zh-cn');
console.log(dayjs(date).format('LLLL')); // 2026年3月24日星期二 22:30

5.4 跨端時間處理(瀏覽器/Node.js/小程序)

  • 瀏覽器:使用上述庫,注意兼容性
  • Node.js:同樣可以使用 day.js 或 date-fns,但需要注意 Intl API 可能需要 Node.js 編譯時開啟 ICU 支持
  • 微信小程序:不支持 Intl 完整功能,建議使用 day.js 并打包時區(qū)數據

六、工程最佳實踐

6.1 前端存儲:優(yōu)先存 UTC 時間戳

在本地存儲(localStorage、IndexedDB)中,不要存儲格式化的字符串,而應存儲 UTC 時間戳(毫秒)。這樣在讀取時可以直接傳給 day.js 或 Temporal 進行格式化,避免時區(qū)混亂。

// 存儲
const timestamp = dayjs.utc().valueOf();
localStorage.setItem('lastVisit', timestamp);

// 讀取
const stored = parseInt(localStorage.getItem('lastVisit'));
const localTime = dayjs(stored).tz(userTimeZone);

6.2 接口傳輸:統(tǒng)一用 ISO 8601 格式

與后端交互時,統(tǒng)一使用 2026-03-24T06:30:00Z 這樣的 UTC 格式。不要使用本地格式字符串,也不要使用時間戳(除非特殊場景,如大量數據傳輸)。

6.3 避免依賴客戶端時區(qū)(敏感場景)

對于訂單創(chuàng)建時間、支付時間等敏感業(yè)務,建議由后端直接返回展示格式(如北京時間字符串),避免前端時區(qū)轉換帶來的爭議。前端只負責展示后端已確定的時間。

6.4 性能優(yōu)化:減少頻繁創(chuàng)建 Date/Temporal 對象

在列表渲染或高頻操作中,避免在循環(huán)中創(chuàng)建大量時間對象??梢灶A先計算好需要的時間字符串,或使用 Intl.DateTimeFormat 批量格式化。

// 優(yōu)化前
items.forEach(item => {
    item.displayTime = dayjs(item.time).format('YYYY-MM-DD');
});

// 優(yōu)化后:使用 formatter 批量格式化
const formatter = new Intl.DateTimeFormat('zh-CN', { dateStyle: 'short' });
items.forEach(item => {
    item.displayTime = formatter.format(new Date(item.time));
});

七、總結與預告

7.1 JS時間處理核心建議

場景推薦方案
簡單本地時間展示原生 Date(注意坑)
需要時區(qū)轉換、相對時間day.js + 插件
追求極致體積、函數式date-fns
新項目,期望未來升級day.js,待 Temporal 穩(wěn)定后遷移
探索未來標準使用 @js-temporal/polyfill 體驗

核心原則

  • 后端統(tǒng)一返回 UTC ISO 8601 字符串
  • 前端根據用戶時區(qū)轉換展示
  • 存儲用時間戳或 UTC 字符串
  • 敏感時間由后端決定展示格式

到此這篇關于JavaScript時間處理Date/moment/dayjs/Temporal方法全解的文章就介紹到這了,更多相關JavaScript時間處理內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

  • js中變量的連續(xù)賦值(實例講解)

    js中變量的連續(xù)賦值(實例講解)

    下面小編就為大家?guī)硪黄猨s中變量的連續(xù)賦值(實例講解)。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-07-07
  • 如何利用Typescript封裝本地存儲

    如何利用Typescript封裝本地存儲

    這篇文章主要給大家介紹了關于如何利用Typescript封裝本地存儲的相關資料,文中通過實例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下
    2022-01-01
  • JavaScript觀察者模式(經典)

    JavaScript觀察者模式(經典)

    Observer模式也叫觀察者模式,是由GoF提出的23種軟件設計模式的一種。Observer模式是行為模式之一,它的作用是當一個對象的狀態(tài)發(fā)生變化時,能夠自動通知其他關聯(lián)對象,自動刷新對象狀態(tài)
    2015-12-12
  • JS功能代碼集錦

    JS功能代碼集錦

    這篇文章主要介紹了JS功能代碼集錦 的相關資料,需要的朋友可以參考下
    2016-05-05
  • 跟我學習javascript的Date對象

    跟我學習javascript的Date對象

    跟我學習javascript的Date對象,文章主要介紹了Date 日期和時間對象的操作,文章末尾為大家附加了兩個案例,幫助大家更好的學習javascript的Date對象,對這方面感興趣的小伙伴們可以參考一下
    2015-11-11
  • js數字計算 誤差問題的快速解決方法

    js數字計算 誤差問題的快速解決方法

    下面小編就為大家?guī)硪黄猨s數字計算 誤差問題的快速解決方法。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-02-02
  • js無痛刷新Token的實現(xiàn)

    js無痛刷新Token的實現(xiàn)

    本文主要介紹了js無痛刷新Token的實現(xiàn),文中根據實例編碼詳細介紹的十分詳盡,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-03-03
  • 整理Javascript數組學習筆記

    整理Javascript數組學習筆記

    整理Javascript數組學習筆記,之前一系列的文章是跟我學習Javascript,本文就是進一步學習javascript數組,希望大家繼續(xù)關注
    2015-11-11
  • 微信小程序用戶自定義模版用法實例分析

    微信小程序用戶自定義模版用法實例分析

    這篇文章主要介紹了微信小程序用戶自定義模版用法,結合實例形式較為詳細的分析了微信小程序自定義模板的定義、數據調用、布局設置等簡單使用技巧,需要的朋友可以參考下
    2017-11-11
  • JavaScript 繼承詳解(五)

    JavaScript 繼承詳解(五)

    在本章中,我們將分析John Resig關于JavaScript繼承的一個實現(xiàn) - Simple JavaScript Inheritance,需要的朋友可以參考下
    2016-10-10

最新評論

临清市| 额尔古纳市| 南通市| 麦盖提县| 车致| 越西县| 陆川县| 绿春县| 新干县| 马山县| 监利县| 海口市| 上杭县| 镇安县| 雷波县| 谢通门县| 出国| 浦城县| 青龙| 蚌埠市| 洮南市| 武穴市| 保定市| 建德市| 贵港市| 靖州| 长宁区| 余姚市| 曲麻莱县| 梁山县| 诏安县| 平山县| 嵩明县| 南昌县| 喀什市| 久治县| 新和县| 乌鲁木齐市| 北川| 桃园市| 二连浩特市|