成人欧美一区二区三区的电影,日韩一级一欧美一级国产,国产成人国拍亚洲精品,无码人妻精品一区二区三区毛片,伊人久久无码大香线蕉综合

LOGO OA教程 ERP教程 模切知識交流 PMS教程 CRM教程 開發(fā)文檔 其他文檔  
 
網(wǎng)站管理員

一個關(guān)于時區(qū)的線上問題(PDT異常和內(nèi)存溢出)

freeflydom
2025年10月10日 11:3 本文熱度 564

一、背景

我們有一個較老的全球化項目,前端框架使用的是 Vue 2 + Element UI (v1.4.13)。

在加拿大等北美地區(qū)測試時,發(fā)現(xiàn)一個非常詭異的問題: 當(dāng)選擇日期為 2025-10-06 時,實際顯示卻成了 2025-10-05。

另外,在監(jiān)聽 onChange 事件時,還觸發(fā)了內(nèi)存溢出(死循環(huán)),導(dǎo)致瀏覽器卡死。 本文將結(jié)合實際調(diào)試過程,解釋問題根源,并提供完整解決方案。

二、問題一:日期顯示提前一天

1. Chrome 模擬時區(qū)復(fù)現(xiàn)

在 Chrome 控制臺中按下 ESC,打開下方工具欄:

點擊左下角三點圖標(biāo),選擇 Sensors

在 Location 一欄中,選擇 “Mountain View”(美國山景城),即北美西海岸時區(qū):

接著在控制臺執(zhí)行以下代碼:

new Date('2025-09-26')
// Thu Sep 25 2025 17:00:00 GMT-0700 (Pacific Daylight Time)
new Date('2025-09-26T00:00:00')
Fri Sep 26 2025 00:00:00 GMT-0700 (Pacific Daylight Time)

可以看到,兩種寫法結(jié)果不同:第一個比預(yù)期早了一天。

2. 原因分析

這是由 JavaScript Date 構(gòu)造函數(shù)的解析規(guī)則 和 時區(qū)換算機制 共同導(dǎo)致的。

new Date('2025-09-26')

  • 當(dāng)只傳入 "YYYY-MM-DD" 時,JavaScript 會默認(rèn)按 UTC 零點解析: 即 2025-09-26T00:00:00.000Z
  • 若系統(tǒng)時區(qū)為北美 PDT(UTC-7),則要減去 7 小時:
2025-09-26 00:00:00 UTC = 2025-09-25 17:00:00 PDT
  • 因此結(jié)果顯示為「9 月 25 日傍晚」,也就是你看到的「昨天」。

new Date('2025-09-26T00:00:00')

  • 當(dāng)字符串中包含 T 和時間部分時,JavaScript 會按 本地時區(qū) 解析(而不是當(dāng)作 UTC)。
  • 因此該寫法得到正確的本地日期:2025-09-26 00:00:00 PDT。

3. 解決方法

方法一:傳入完整時間字符串(推薦)

// 推薦,ISO標(biāo)準(zhǔn)
new Date('2025-09-26T00:00:00') // Fri Sep 26 2025 00:00:00 GMT-0700 (Pacific Daylight Time)
// Chrome 執(zhí)行正常,IE11 執(zhí)行變成 'Invalid Date'
new Date('2025-09-26 00:00:00') // Fri Sep 26 2025 00:00:00 GMT-0700 (Pacific Daylight Time)

方法二:使用 moment / moment-timezone

1)使用 moment 的 toDate() 方法

import moment from "moment";
moment("2025-09-26").toDate(); // Fri Sep 26 2025 00:00:00 GMT-0700 (Pacific Daylight Time)

2)指定時區(qū)的寫法

import moment from "moment-timezone";
moment.tz("2025-09-26", "YYYY-MM-DD", "America/Los_Angeles").toDate(); // Fri Sep 26 2025 00:00:00 GMT-0700 (Pacific Daylight Time)

3)格式化輸出

moment("2025-09-26").format("YYYY-MM-DDTHH:mm:ss") // 2025-09-26T00:00:00

方法三:數(shù)字構(gòu)造方式

// 注意:月份從 0 開始,8 = 九月
new Date(2025, 8, 26) // Fri Sep 26 2025 00:00:00 GMT-0700 (Pacific Daylight Time)

? Element UI 2.x 之后改用數(shù)字構(gòu)造,因此天然避免了該問題。

三、問題二:onChange 死循環(huán)與內(nèi)存溢出

1. 復(fù)現(xiàn)代碼

安裝舊版本:

pnpm i element-ui@1.4.13

main.js 引入 ElementUI

// ...
import ElementUI from "element-ui";
import "element-ui/lib/theme-default/index.css";
Vue.use(ElementUI);

編寫 App.vue

<script>
export default {
	data() {
		return {
			value: "",
		};
	},
	methods: {
		onChange(val) {
			if (!this.jjj) {
				this.jjj = 0;
			}
			this.jjj++;
			if (this.jjj > 100) {
				console.error("內(nèi)存溢出");
				this.jjj = 0;
				return;
			}
			this.value = val;
		},
	},
};
</script>
<template>
	<div>
		<el-date-picker
			v-model="value"
			@change="onChange"
			type="date"
			placeholder="選擇日期范圍"
			clearable
		>
		</el-date-picker>
	</div>
</template>

onChange 會被反復(fù)觸發(fā),造成內(nèi)存溢出,控制臺打印日志:內(nèi)存溢出。

2. 解決方案:封裝兼容組件

新建一個 ElDatePickerTimezone.vue,將所有日期組件替換為該封裝版本。

App.vue 使用方式:

<script>
import ElDatePickerTimezone from "./components/ElDatePickerTimezone.vue";
export default {
	components: { ElDatePickerTimezone },
	data() {
		return {
			value: "",
		};
	},
	methods: {
		onChange(val) {
			this.value = val;
		},
	},
};
</script>
<template>
	<div>
		<ElDatePickerTimezone
			v-model="value"
			@change="onChange"
			type="date"
			placeholder="選擇日期范圍"
			clearable
		>
		</ElDatePickerTimezone>
	</div>
</template>

ElDatePickerTimezone.vue 組件封裝如下:

<template>
	<el-date-picker v-bind="attrs" v-on="listeners" :value="proxyValue">
		<!-- 默認(rèn)插槽轉(zhuǎn)發(fā) -->
		<slot />
		<!-- 作用域插槽轉(zhuǎn)發(fā) -->
		<template v-for="(_, name) in $scopedSlots" v-slot:[name]="slotProps">
			<slot :name="name" v-bind="slotProps" />
		</template>
	</el-date-picker>
</template>
<script>
import moment from "moment";
const YMD_RE = /^\d{4}-\d{2}-\d{2}$/;
// 把傳進(jìn)來的字符串里所有 正則特殊字符(比如 . * + ? ^ $ { } ( ) | [ ] \)都加上反斜杠轉(zhuǎn)義。
// 舉例: '*' => '\*'
const esc = (s) => s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
export default {
	name: "ElDatePickerTimezone",
	inheritAttrs: false,
	props: {
		value: {
			type: [String, Number, Date, Array],
			default: null,
		},
	},
	computed: {
		listeners() {
			return this.$listeners;
		},
		attrs() {
			const { value, ...rest } = this.$attrs;
			return rest;
		},
		proxyValue() {
			return this.normalizeIn(this.value);
		},
		rangeSeparator() {
			return (
				this.$attrs["range-separator"] || this.$attrs.rangeSeparator || " - "
			);
		},
		rangeRegex() {
			return new RegExp(
				"^\\s*(\\d{4}-\\d{2}-\\d{2})\\s*" +
					esc(this.rangeSeparator) +
					"\\s*(\\d{4}-\\d{2}-\\d{2})\\s*$"
			);
		},
		// 如果 rangeRegex 沒匹配上,再嘗試用一個寬松規(guī)則
		hyphenFallbackRegex() {
			return /^\s*(\d{4}-\d{2}-\d{2})\s*-\s*(\d{4}-\d{2}-\d{2})\s*$/;
		},
	},
	methods: {
		normalizeIn(val) {
			const toDate = (x) => {
				if (x === "" || x === null || x === undefined) return null;
				if (x instanceof Date) return isNaN(x.getTime()) ? null : x;
				if (typeof x === "string") {
					const s = x.trim();
					// range: 優(yōu)先匹配實際分隔符
					let m = this.rangeRegex.exec(s);
					if (!m) m = this.hyphenFallbackRegex.exec(s);
					if (m) {
						const [, a, b] = m;
						const m1 = moment(a, "YYYY-MM-DD", true);
						const m2 = moment(b, "YYYY-MM-DD", true);
						return [
							m1.isValid() ? m1.toDate() : null,
							m2.isValid() ? m2.toDate() : null,
						];
					}
					// 單個 YYYY-MM-DD
					if (YMD_RE.test(s)) {
						const md = moment(s, "YYYY-MM-DD", true);
						return md.isValid() ? md.toDate() : null;
					}
				}
				const any = moment(x);
				return any.isValid() ? any.toDate() : null;
			};
			return Array.isArray(val) ? val.map(toDate) : toDate(val);
		},
	},
};
</script>

四、補充知識

4.1 介紹下 PDT 和 PST

1. PDT 和 PST 是什么?

它們都是美國西海岸(包括加州、華盛頓州等地)的時區(qū):

  • PDT = Pacific Daylight Time(太平洋夏令時間)
  • PST = Pacific Standard Time(太平洋標(biāo)準(zhǔn)時間)

2. 兩者的區(qū)別

名稱全稱與 UTC 的時差使用時間舉例城市
PSTPacific Standard TimeUTC ? 8 小時冬季使用(約 11 月初到次年 3 月中旬)洛杉磯、舊金山、山景城、西雅圖
PDTPacific Daylight TimeUTC ? 7 小時夏季使用(約 3 月中旬到 11 月初)同上

?? 簡單記法:

夏天用 PDT(慢 7 小時),

冬天用 PST(慢 8 小時)。

舉個例子:

假設(shè) UTC 時間是:2025-09-26 00:00:00

  • PDT(夏天)下:是 2025-09-25 17:00:00
  • PST(冬天)下:是 2025-09-25 16:00:00

3. 為什么要區(qū)分?

美國實行 夏令時制度 (Daylight Saving Time, DST), 目的是讓人們在夏天“更晚天黑”,充分利用日照。 所以每年春天會:

  • 把時間撥快一小時(進(jìn)入 PDT);
  • 到秋天再撥回一小時(回到 PST)。

4.2 介紹下 ISO

1. 什么是 ISO 標(biāo)準(zhǔn)(ISO 8601)

ISO 是國際標(biāo)準(zhǔn)化組織(International Organization for Standardization)的簡稱。 ISO 8601 是它為“日期與時間的表示法”制定的國際標(biāo)準(zhǔn)。

? 目的:讓全世界的計算機系統(tǒng)用同一種方式理解時間,避免歧義。

比如:

  • ???? 美國人習(xí)慣寫 09/26/2025(月/日/年)
  • ???? 中國人習(xí)慣寫 2025-09-26(年-月-日)
  • ???? 法國人可能寫 26/09/2025(日/月/年)

這些格式人能分辨,但程序會混淆。 所以 ISO 8601 統(tǒng)一規(guī)定寫成:

YYYY-MM-DDTHH:mm:ssZ

2. 字符串里的 T 是什么意思?

在 ISO 8601 中,T 是一個固定分隔符,意思是:

Time」的縮寫,用來分隔日期和時間部分。

舉個例子:

2025-09-26T00:00:00

可以理解為:

日期: 2025-09-26
時間: 00:00:00

中間的 T 就相當(dāng)于寫成 "2025-09-26 00:00:00" 的空格,只不過更標(biāo)準(zhǔn)化、機器可解析。

3. 常見 ISO 格式舉例

格式含義備注
2025-09-26僅日期(UTC 解析)容易產(chǎn)生時區(qū)偏移 ??
2025-09-26T00:00:00本地時間零點? 推薦用于 JS 本地時間
2025-09-26T00:00:00ZUTC 時間零點(Z = Zulu = UTC)? 推薦用于跨時區(qū)傳輸
2025-09-26T00:00:00+08:00北京時間(UTC+8)明確指定時區(qū)

五、總結(jié)

  • new Date('YYYY-MM-DD') 會被當(dāng)作 UTC 零點,導(dǎo)致北美等地區(qū)顯示提前一天。

  • 推薦始終使用:

    • new Date('YYYY-MM-DDT00:00:00')
    • 或通過 moment / moment-timezone 明確時區(qū)解析。
  • 對于舊版 Element UI(1.4.x),建議:

    • 封裝自定義 ElDatePickerTimezone;
    • 或升級至 2.x 以上版本,避免死循環(huán)與時區(qū) Bug。

?轉(zhuǎn)自https://juejin.cn/post/6844904134257147917


該文章在 2025/10/10 11:03:15 編輯過
關(guān)鍵字查詢
相關(guān)文章
正在查詢...
點晴ERP是一款針對中小制造業(yè)的專業(yè)生產(chǎn)管理軟件系統(tǒng),系統(tǒng)成熟度和易用性得到了國內(nèi)大量中小企業(yè)的青睞。
點晴PMS碼頭管理系統(tǒng)主要針對港口碼頭集裝箱與散貨日常運作、調(diào)度、堆場、車隊、財務(wù)費用、相關(guān)報表等業(yè)務(wù)管理,結(jié)合碼頭的業(yè)務(wù)特點,圍繞調(diào)度、堆場作業(yè)而開發(fā)的。集技術(shù)的先進(jìn)性、管理的有效性于一體,是物流碼頭及其他港口類企業(yè)的高效ERP管理信息系統(tǒng)。
點晴WMS倉儲管理系統(tǒng)提供了貨物產(chǎn)品管理,銷售管理,采購管理,倉儲管理,倉庫管理,保質(zhì)期管理,貨位管理,庫位管理,生產(chǎn)管理,WMS管理系統(tǒng),標(biāo)簽打印,條形碼,二維碼管理,批號管理軟件。
點晴免費OA是一款軟件和通用服務(wù)都免費,不限功能、不限時間、不限用戶的免費OA協(xié)同辦公管理系統(tǒng)。
Copyright 2010-2025 ClickSun All Rights Reserved