如何用Moment.js根据地区动态显示本地化格式的日期时间?
问题
我根据访客选择的locale和timezone显示其日期时间,目前功能正常,但代码输出的格式始终固定。我希望根据所选地区的格式,动态显示包含日、月、年和时间的本地化日期时间,请问是否可行?
以下是我编写的自定义Hook:
import {useState, useEffect} from "react"; import moment from "moment"; import IntlStorage from "../helpers/IntlStorage"; export const useLocaleTime = () => { const [formattedTime, setFormattedTime] = useState<string | null>(null); const locale = IntlStorage.getLocale(); // 示例值:en-US const timezone = IntlStorage.getTimezone(); // 示例值:US/Alaska useEffect(() => { const updateTime = () => { moment.locale(locale); moment.tz.setDefault(timezone); const currentTime = moment().format("D MMMM YYYY LTS"); setFormattedTime(currentTime); }; const interval = setInterval(updateTime, 1000); return () => clearInterval(interval); }, [locale, timezone]); return formattedTime; };
我还做了另一种尝试,但输出格式仍未改变:
useEffect(() => { const updateTime = () => { const options: any = { day: "numeric", month: "long", year: "numeric", hour: "numeric", minute: "numeric", second: "numeric", timeZone: timezone, }; const currentDate = new Date(); const formattedTime = currentDate.toLocaleString(locale, options); setFormattedTime(formattedTime); };
解决方案
当然可行,问题出在你要么指定了固定格式规则,要么没有正确利用本地化API的自动适配能力。下面给你两种修复方案:
方案一:使用原生Intl.DateTimeFormat(推荐)
你之前的原生API尝试已经接近正确,调整选项让格式完全跟随地区习惯,补全完整Hook代码如下:
import { useState, useEffect } from "react"; import IntlStorage from "../helpers/IntlStorage"; export const useLocaleTime = () => { const [formattedTime, setFormattedTime] = useState<string | null>(null); const locale = IntlStorage.getLocale(); const timezone = IntlStorage.getTimezone(); useEffect(() => { const updateTime = () => { // 不强制指定格式细节,让API根据locale自动适配组合格式 const options: Intl.DateTimeFormatOptions = { timeZone: timezone, dateStyle: "long", timeStyle: "medium" }; const formatter = new Intl.DateTimeFormat(locale, options); const formattedTime = formatter.format(new Date()); setFormattedTime(formattedTime); }; const interval = setInterval(updateTime, 1000); updateTime(); // 初始化立即执行一次 return () => clearInterval(interval); }, [locale, timezone]); return formattedTime; };
- 说明:
dateStyle和timeStyle参数会根据locale自动生成符合当地习惯的格式,比如en-US会输出October 5, 2024 3:45:23 PM,zh-CN会输出2024年10月5日 15:45:23。
方案二:修复moment.js的用法
你之前的moment代码用了固定格式字符串"D MMMM YYYY LTS",这会覆盖本地化自动格式,改成使用moment的本地化格式令牌即可:
import { useState, useEffect } from "react"; import moment from "moment"; import "moment-timezone"; import IntlStorage from "../helpers/IntlStorage"; export const useLocaleTime = () => { const [formattedTime, setFormattedTime] = useState<string | null>(null); const locale = IntlStorage.getLocale(); const timezone = IntlStorage.getTimezone(); useEffect(() => { const updateTime = () => { moment.locale(locale); const currentTime = moment.tz(timezone).format("LLL"); setFormattedTime(currentTime); }; const interval = setInterval(updateTime, 1000); updateTime(); return () => clearInterval(interval); }, [locale, timezone]); return formattedTime; };
- 说明:moment的
LLL令牌是本地化的长格式日期时间,会根据设置的locale自动调整格式,比如en-US输出October 5, 2024 3:45 PM,fr-FR输出5 octobre 2024 15:45。
内容的提问来源于stack exchange,提问作者Johan
相关产品推荐
相关产品推荐

