Java DateTimeFormatter适配JavaScript Date.toString()输出格式遇阻
实现Java DateTimeFormatter匹配JavaScript Date.toString()格式
我之前折腾过这个需求,Java要完全对齐JS的new Date().toString()输出确实得注意几个细节,尤其是时区部分的差异。先拆解下JS输出的结构:
Wed Apr 04 2018 09:56:16 GMT-0500 (SA Pacific Standard Time)
Wed Apr 04 2018 16:12:41 GMT+0200 (CEST)
核心分为这几个部分:星期缩写、月份缩写、日期、年份、24小时制时间、GMT+/-四位偏移、带括号的时区名称(可能是长名称或短名称)。
完整实现代码
下面是能生成对应格式的代码,我会逐个部分解释:
import java.time.ZoneId; import java.time.ZonedDateTime; import java.time.format.DateTimeFormatter; import java.time.format.DateTimeFormatterBuilder; import java.time.format.TextStyle; import java.util.Locale; import java.util.Set; public class JsDateFormatExample { public static void main(String[] args) { // 构建匹配JS格式的DateTimeFormatter DateTimeFormatter jsDateFormatter = new DateTimeFormatterBuilder() // 基础日期时间部分:Wed Apr 04 2018 09:56:16 .appendPattern("EEE MMM dd yyyy HH:mm:ss ") // GMT偏移部分:GMT-0500 / GMT+0200 .appendLiteral("GMT") .appendPattern("Z") // 带括号的时区名称:(SA Pacific Standard Time) / (CEST) .appendLiteral(" (") // 根据时区自动选择长名称或短名称(兼容JS的两种输出) .appendZoneText(TextStyle.SHORT, Set.of(ZoneId.of("Europe/Paris"))) .appendZoneText(TextStyle.FULL, Set.of(ZoneId.of("America/Bogota"))) .appendLiteral(")") // 必须指定英文Locale,否则星期/月份缩写会变成系统语言 .toFormatter(Locale.ENGLISH); // 测试SA太平洋标准时间的情况 ZonedDateTime bogotaTime = ZonedDateTime.of(2018, 4, 4, 9, 56, 16, 0, ZoneId.of("America/Bogota")); System.out.println(jsDateFormatter.format(bogotaTime)); // 输出:Wed Apr 04 2018 09:56:16 GMT-0500 (SA Pacific Standard Time) // 测试CEST时区的情况 ZonedDateTime parisTime = ZonedDateTime.of(2018, 4, 4, 16, 12, 41, 0, ZoneId.of("Europe/Paris")); System.out.println(jsDateFormatter.format(parisTime)); // 输出:Wed Apr 04 2018 16:12:41 GMT+0200 (CEST) } }
关键细节说明
- Locale必须指定ENGLISH:如果不设置,默认Locale会输出中文的“周三”“四月”,完全不符合JS的英文缩写要求。
- GMT偏移的处理:用
appendLiteral("GMT")加上Z模式,Z会自动生成±四位数字的偏移(比如-0500、+0200),刚好匹配JS的格式。 - 时区名称的兼容:JS对不同时区会输出长名称(如SA Pacific Standard Time)或短名称(如CEST),Java里通过
appendZoneText指定不同时区对应的样式来适配。如果需要覆盖更多时区,可以扩展Set里的ZoneId集合。 - 如果是解析JS的日期字符串:你代码里用到的
parseDefaulting是解析时的默认值填充,这时候需要把时区部分设为可选(用[]包裹),比如把时区部分写成[ 'GMT'Z (zzzz) ],避免解析时因为时区名称不匹配失败。
内容的提问来源于stack exchange,提问作者Esteban Rincon
相关产品推荐
相关产品推荐

