MessageFormat 依赖显式传入的 Locale 实例进行日期格式化,不自动感知系统区域设置;需配合 {0,date,style} 中的合法风格(short/medium/long/full)或自定义 pattern,并注意其不支持时区与高级日历,推荐结合 ResourceBundle 实现文案与日期本地化统一。

MessageFormat 能自动按当前 Locale 格式化日期,但关键在于它不直接感知系统区域设置,而是依赖传入的 Locale 实例或默认 JVM 区域。要让日期变量在不同区域下正确显示,必须显式指定 Locale,并配合正确的格式类型与风格。
明确传入 Locale 是前提
MessageFormat 默认使用 JVM 启动时的默认 Locale(如 Locale.getDefault()),这通常由操作系统决定,不可靠。生产中应始终显式传入目标 Locale:
- 用
new MessageFormat(pattern, locale)构造实例 - 或调用静态方法
MessageFormat.format(pattern, locale, args)(需 JDK 21+) - 常见写法:
new MessageFormat("事件日期:{0,date,medium}", Locale.CHINA)→ “事件日期:2026-5-8” - 换用
Locale.US→ “事件日期:May 8, 2026”
日期格式类型和风格要匹配需求
占位符中 {0,date,style} 的 style 决定输出粒度和本地习惯,不是任意字符串:
-
short:紧凑型,如US→5/8/26,CHINA→26/5/8(注意顺序差异) -
medium:平衡可读性与长度,如US→May 8, 2026,CHINA→2026年5月8日 -
long:带完整月份名,如US→May 8, 2026(同 medium),DE→8. Mai 2026 -
full:含星期,如US→Friday, May 8, 2026,JA→2026年5月8日金曜日 - 也可用自定义 pattern,如
{0,date,yyyy年MM月dd日},但会绕过 Locale 的本地化逻辑,仅做字符串替换
避免混淆:MessageFormat 不替代 DateTimeFormatter
MessageFormat 的日期格式化能力基于底层 DateFormat.getInstance(..., locale),属于较老的 API,有以下限制:
- 不支持时区动态切换(
timeZone属性在 MessageFormat 中无效) - 无法精细控制小时制(如 12/24 小时、AM/PM 位置)、农历、波斯历等高级日历
- 若需时区感知或现代日历支持,应改用
java.time.format.DateTimeFormatter配合LocalDateTime.format()或ZonedDateTime.format() - MessageFormat 更适合“文本模板 + 基础日期插入”场景,比如邮件正文、提示语中的日期引用
实际建议:结合 ResourceBundle 使用
真正做国际化时,日期格式化常嵌套在多语言文案中。推荐做法是:
- 把带占位符的文案(如
event.date={0,date,medium} 发生了事件)放在messages_zh.properties和messages_en.properties中 - 加载对应
ResourceBundle后,用其获取的字符串作为 MessageFormat 的 pattern - 再传入
Date对象和当前用户 Locale,确保文案语言与日期格式一致 - 这样既分离了文案,又保持了日期本地化逻辑的可控性










