🎉 "从 ISO 到 GMT+8:Vue 前端时间格式的奇妙之旅!" 🎉
作者:小丁 | 日期:2025-03-04
嘿,各位前端探险家 👩💻👨💻!今天我要带你们走进一个时间格式的"变形记":从前端的 ISO 格式("2025-03-04T07:28:17.058Z"
)到后端期待的 GMT+8 "yyyy-MM-dd HH:mm:ss"
("2025-03-04 15:28:17"
),我如何在 Vue 项目中搞定这个"时间旅行"的小挑战?别急,拿好你的爆米花 🍿,跟我一起揭开这段代码冒险的幕后故事吧!
🎬 故事开场:时间格式的"误会"
有一天,我在调试一个 Vue 项目,子组件 <ave-form>
负责收集用户寄样信息。代码里有个关键函数:
javascript
private handleExpressCompanyChange(value: string) {
if (value) {
this.form.sampleSendTime = new Date().toISOString();
}
}
逻辑很简单:用户一选快递公司,sampleSendTime
就自动填上当前时间,格式是 ISO 8601 的 "2025-03-04T07:28:17.058Z"
。我得意地提交表单,期待后端完美接收。结果呢?后端报错:
json
Cannot deserialize value of type `java.util.Date`
from String "2025-03-04T07:28:17.058Z":
expected format "yyyy-MM-dd HH:mm:ss"
后端冷冰冰地告诉我,它想要的是 @JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
,也就是 "2025-03-04 15:28:17"
。这下尴尬了,前端和后端就像在"跨时区吵架":一个讲国际标准,一个要东八区时间!😂
🕵️♂️ 破案第一步:时间格式的"身份危机"
让我们先看看问题出在哪里:
- 前端输出 :
new Date().toISOString()
生成"2025-03-04T07:28:17.058Z"
。T
分隔日期和时间。.058
是毫秒。Z
表示 UTC 时间(零时区)。
- 后端期待 :
"2025-03-04 15:28:17"
。- 无
T
,无毫秒。 - 空格分隔。
- GMT+8 时区(比 UTC 早 8 小时)。
- 无
这就好比前端递给后端一张"国际护照" ✈️,后端却说:"我只认本地身份证!" 🪪 显然,我们得把时间"改头换面"。
🛠️ 动手改造:从 ISO 到 GMT+8
我决定在前端动手,把时间格式调整到后端喜欢的模样。目标:
- 去掉
T
和毫秒,改用空格。 - 调整为 GMT+8 时区。
- 输出
"yyyy-MM-dd HH:mm:ss"
。
初步尝试:手动格式化
我写了个小函数,把 Date
对象"打扮"成 GMT+8 的样子:
javascript
private formatDateToGMT8(date: Date): string {
const offset = 8 * 60; // GMT+8 是 8 小时,转换为分钟
const localDate = new Date(date.getTime() + offset * 60 * 1000); // 调整为 GMT+8
const pad = (num: number) => num.toString().padStart(2, '0');
return `${localDate.getUTCFullYear()}-${pad(localDate.getUTCMonth() + 1)}-${pad(localDate.getUTCDate())} ` +
`${pad(localDate.getUTCHours())}:${pad(localDate.getUTCMinutes())}:${pad(localDate.getUTCSeconds())}`;
}
private handleExpressCompanyChange(value: string) {
if (value) {
this.form.sampleSendTime = this.formatDateToGMT8(new Date());
}
}
getTime()
+ 偏移:把时间戳加 8 小时,模拟 GMT+8。pad
:补齐两位数,比如7
变成07
。- 结果 :如果现在是 UTC 的
"2025-03-04T07:28:17"
,加上 8 小时后,输出"2025-03-04 15:28:17"
。
提交后,后端终于不吵了,数据库里存下了完美的 "2025-03-04 15:28:17"
!🎉
🎨 SVG 图解:时间的"变装秀"
为了让大家看得更清楚,我用 SVG 画了个"时间变形记":
前端 ISO 时间 "2025-03-04T07:28:17.058Z" 后端 GMT+8 时间 "2025-03-04 15:28:17" +8小时 & 格式化 (去掉 T 和毫秒) +8小时 & 格式化 (去掉 T 和毫秒) +8小时 & 格式化 (去掉 T 和毫秒)
🧠 为什么删掉初始值?
顺便说一句,我还干了件"断舍离"的事:删掉了 form
的初始赋值:
javascript
// 之前
private form: any = {
sampleTrackingNumber: '',
sampleExpressCompany: '',
sampleSendTime: new Date().toISOString()
};
// 现在
private form: any = {};
为啥?因为子组件有个 @Watch('value')
,每次父组件传 value
(比如空对象 {}
)时,form
都会被覆盖,初始值压根没机会"上场"!删了它,代码更干净,反正 sampleSendTime
在选择快递公司时会重新赋值。🏃♂️
🌟 收获与反思
这次时间格式的调整让我学到了几招:
- 前端后端要"谈恋爱":时间格式得统一,别让一方"国际派",一方"本地派",不然迟早"分手"!😅
- 时区是个坑 :
toISOString()
是 UTC 时间,得手动调整到目标时区(比如 GMT+8)。 - 精简代码有回报:没用的初始值果断删,既省内存又少烦恼。
最终,我的表单数据顺利提交,后端开心地存下了 "2025-03-04 15:28:17"
,项目又迈进了一小步!🏆
🛠️ 代码锦囊:留给你的"时间魔法"
想复刻这个魔法?直接抄走这段代码吧:
javascript
private formatDateToGMT8(date: Date): string {
const offset = 8 * 60; // GMT+8 偏移(分钟)
const localDate = new Date(date.getTime() + offset * 60 * 1000);
const pad = (num: number) => num.toString().padStart(2, '0');
return `${localDate.getUTCFullYear()}-${pad(localDate.getUTCMonth() + 1)}-${pad(localDate.getUTCDate())} ` +
`${pad(localDate.getUTCHours())}:${pad(localDate.getUTCMinutes())}:${pad(localDate.getUTCSeconds())}`;
}
private handleExpressCompanyChange(value: string) {
if (value) {
this.form.sampleSendTime = this.formatDateToGMT8(new Date());
}
}
💬 小彩蛋:你的时间故事
你有没有遇到过类似的"时间格式纠葛"?是前端后端"吵架",还是时区让你头晕?评论区聊聊吧!我带着代码和咖啡 ☕,随时帮你解惑!✌️
