如何将带时区的ISO日期转换为指定格式并保留原时区?
解决带时区ISO日期转指定格式时保留原时区的问题
你的代码问题在于Date对象本质只是时间戳,不携带时区信息,所以用SimpleDateFormat格式化时会默认使用服务器时区,导致原时区丢失。以下是两种解决方案:
推荐方案:使用Java 8+ 新日期时间API(优先选择)
Java 8引入的java.time包是线程安全的,设计更合理,能直接保留时区信息:
import java.time.ZonedDateTime; import java.time.format.DateTimeFormatter; import java.util.Locale; public class DateConverter { public static void main(String[] args) { String dateStr = "2020-11-22T10:02:13.501-04:00"; // 解析带时区的ISO格式字符串,得到带时区的日期对象 DateTimeFormatter parser = DateTimeFormatter.ISO_OFFSET_DATE_TIME; ZonedDateTime zonedDateTime = ZonedDateTime.parse(dateStr, parser); // 定义目标格式,Locale.US确保月份和时区缩写为英文,hh对应12小时制 DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd/MMM/yyyy hh:mm aa zzz", Locale.US); String formattedDate = zonedDateTime.format(formatter); System.out.println(formattedDate); // 输出:22/Nov/2020 10:02 AM EST } }
说明:
ZonedDateTime会完整保留解析得到的时区信息(-04:00对应America/New_York时区,自动识别为EST)- 用
Locale.US避免因系统默认语言导致月份/时区缩写显示为中文 - 格式中的
hh是12小时制,对应aa的AM/PM,原代码用的HH是24小时制,需替换才能正确显示上午/下午标记
兼容方案:使用旧版SimpleDateFormat(仅当无法升级Java版本时使用)
如果必须使用旧API,需要给格式化用的SimpleDateFormat设置与原日期对应的时区ID(注意不能直接用GMT-04:00,否则时区缩写会显示为GMT-04:00而非EST):
import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Date; import java.util.Locale; import java.util.TimeZone; public class OldDateConverter { public static void main(String[] args) throws ParseException { String dateStr = "2020-11-22T10:02:13.501-04:00"; SimpleDateFormat parser = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSXXX", Locale.US); Date dateVal = parser.parse(dateStr); SimpleDateFormat formatter = new SimpleDateFormat("dd/MMM/yyyy hh:mm aa zzz", Locale.US); // 设置对应时区ID,America/New_York会自动处理EST/EDT切换 formatter.setTimeZone(TimeZone.getTimeZone("America/New_York")); String formattedDate = formatter.format(dateVal); System.out.println(formattedDate); // 输出:22/Nov/2020 10:02 AM EST } }
说明:
- 必须指定具体的时区ID(如
America/New_York),才能让SimpleDateFormat显示正确的时区缩写(EST) - 同样需要设置
Locale.US保证英文格式
内容的提问来源于stack exchange,提问作者SC1
相关产品推荐
相关产品推荐

