SimpleDateFormat与DateFormat时区不一致问题求助
嘿,我来帮你理清这个问题~你看到的CEST和MESZ其实是同一个时区的不同语言缩写,背后的原因和两个API的行为差异有关:
1. 直接打印Date对象的行为
你的getDateFromStringSimpleDateFormat方法返回的是Date对象,当你用System.out.println输出它时,会调用Date.toString()方法——这个方法是硬编码使用英文的时区名称,完全忽略你设置的Locale.GERMANY。所以它会显示CEST(Central European Summer Time,中欧夏令时的英文缩写)。
2. DateFormat格式化的行为
而getStringNow里的DateFormat是用德国Locale初始化的,它会遵循本地化规则,使用德语的时区缩写MESZ(Mitteleuropäische Sommerzeit,中欧夏令时的德语表达),这才是符合你设置Locale的预期输出。
解决方法:不要直接打印Date,用格式化工具输出
如果你想让解析后的日期也显示德语时区缩写,别直接打印Date对象,而是用DateFormat或SimpleDateFormat再格式化一次。修改你的main方法试试:
public static void main(String[] args) { System.out.println(getStringNow()); Date parsedDate = getDateFromStringSimpleDateFormat("01.05.2018 00:00:00"); // 用德国Locale的DateFormat格式化解析后的日期 DateFormat germanFormatter = DateFormat.getDateTimeInstance(dateStyleLoc, timeStyleLoc, localeLoc); System.out.println("SimpleDateFormat解析后格式化结果: " + germanFormatter.format(parsedDate)); }
这样输出的时区就会和getStringNow的结果一致,显示MESZ啦。
额外推荐:使用Java 8+的java.time API
旧的DateFormat和SimpleDateFormat不仅线程不安全,还存在不少设计缺陷。Java 8引入的java.time包(比如ZonedDateTime、DateTimeFormatter)更可靠,也更容易处理本地化和时区问题。举个替代的例子:
import java.time.LocalDateTime; import java.time.ZoneId; import java.time.ZonedDateTime; import java.time.format.DateTimeFormatter; import java.util.Locale; public class StringAndDateFormat { private static final Locale localeLoc = Locale.GERMANY; private static final ZoneId GERMAN_ZONE = ZoneId.of("Europe/Berlin"); private static final DateTimeFormatter OUTPUT_FORMATTER = DateTimeFormatter.ofPattern("dd.MM.yy HH:mm:ss z", localeLoc); private static final DateTimeFormatter INPUT_FORMATTER = DateTimeFormatter.ofPattern("dd.MM.yyyy HH:mm:ss", localeLoc); public static void main(String[] args) { // 格式化当前时间 ZonedDateTime now = ZonedDateTime.now(GERMAN_ZONE); System.out.println("当前时间(java.time): " + now.format(OUTPUT_FORMATTER)); // 解析日期并格式化 String inputDate = "01.05.2018 00:00:00"; LocalDateTime localDateTime = LocalDateTime.parse(inputDate, INPUT_FORMATTER); ZonedDateTime parsedZonedDate = localDateTime.atZone(GERMAN_ZONE); System.out.println("解析后格式化结果(java.time): " + parsedZonedDate.format(OUTPUT_FORMATTER)); } }
这个代码的输出会直接显示MESZ,而且线程安全,API设计也更清晰。
内容的提问来源于stack exchange,提问作者Fabian Hörstrup

