react-intl FormattedDate切换en-GB locale出现无效日期问题
解决react-intl FormattedDate接收en-GB格式化字符串时出现“无效日期”的问题
问题场景
原本通过以下代码将日期格式化为en-US字符串,传入FormattedDate组件能正常显示MM/DD/YYYY格式:
let formattedDate = new Date(updated_at).toLocaleDateString('en-US', { timeZone: 'UTC' })
<FormattedDate value={formattedDate} />
改为en-GB格式以实现DD/MM/YYYY显示时:
let formattedDate = new Date(updated_at).toLocaleDateString('en-GB', { timeZone: 'UTC' })
表格中部分日期显示“无效日期”,控制台报错:
Error: [@formatjs/intl Error FORMAT_ERROR] Error formatting date. Invalid time value RangeError: Invalid time value at formatDate (dateTime.js:50:1)
原始日期为ISO格式(如2022-09-22T06:52:32.870184Z),单独用en-GB格式化代码能得到正确结果,但在组件中失效。
问题原因
FormattedDate的value属性设计用于接收Date实例、Unix时间戳(数字)、或ISO 8601标准字符串,而非本地化后的日期字符串:
- en-US格式字符串(如
09/22/2022)会被浏览器默认按MM/DD/YYYY规则解析为有效Date; - en-GB格式字符串(如
22/09/2022)会被浏览器尝试按MM/DD/YYYY解析,此时月份22超出合法范围,导致解析失败,抛出“无效时间值”错误。
解决方案
方案1:直接传递原始Date对象(最推荐)
无需提前用toLocaleDateString格式化,将原始Date实例传给FormattedDate,由组件处理本地化:
const date = new Date(updated_at);
<FormattedDate value={date} locale="en-GB" timeZone="UTC" year="numeric" month="2-digit" day="2-digit" />
该方案符合react-intl设计规范,避免字符串解析的兼容性问题。
方案2:传递ISO格式字符串或时间戳
直接使用原始ISO格式的updated_at,或转换为时间戳后传入组件:
// 传递原始ISO字符串 <FormattedDate value={updated_at} locale="en-GB" timeZone="UTC" year="numeric" month="2-digit" day="2-digit" /> // 或传递时间戳 const timestamp = new Date(updated_at).getTime(); <FormattedDate value={timestamp} locale="en-GB" timeZone="UTC" year="numeric" month="2-digit" day="2-digit" />
方案3:(不推荐)手动解析en-GB格式字符串
若必须传递本地化后的字符串,需手动将DD/MM/YYYY格式转换为Date对象:
const formattedDate = new Date(updated_at).toLocaleDateString('en-GB', { timeZone: 'UTC' }); const parseEnGbDate = (dateStr) => { const [day, month, year] = dateStr.split('/'); // 月份为0-based,需减1 return new Date(Date.UTC(year, month - 1, day)); };
<FormattedDate value={parseEnGbDate(formattedDate)} locale="en-GB" timeZone="UTC" year="numeric" month="2-digit" day="2-digit" />
此方法冗余且易出错,仅作为特殊场景下的备选方案。
内容的提问来源于stack exchange,提问作者Recharge Gomez
相关产品推荐
相关产品推荐

