Java DateFormat parse() 不尊重时区

2022-09-03 17:38:48
Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("America/New_York"));
DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss Z");
df.setTimeZone(TimeZone.getTimeZone("America/New_York"));

try {
    System.out.println(df.format(cal.getTime()));
    System.out.println(df.parse(df.format(cal.getTime())));
} catch (ParseException e) {
    e.printStackTrace();
}

结果如下:

2011-09-24 14:10:51 -0400

星期六 九月 24 20:10:51 CEST 2011

为什么当我解析从format()获得的日期时,它不尊重时区?


答案 1

您正在打印调用 Date.toString() 的结果,它始终使用默认时区。基本上,除了调试之外,您不应该用于其他任何东西。Date.toString()

不要忘记 a 没有时区 - 它代表一个时间时刻,自 Unix 时代(1970 年 1 月 1 日 UTC 午夜)以来以毫秒为单位进行测量。Date

如果您再次使用格式化程序格式化日期,应该会得出与以前相同的答案。

顺便说一句,如果你在Java中做任何大量的日期/时间工作,我建议使用Joda Time而不是/;这是一个更好的API。DateCalendar


答案 2

DateFormat.parse()不是查询(返回值且不会更改系统状态的内容)。它是一个具有更新内部对象的副作用的命令。呼叫后,您必须通过访问 或呼叫 来访问时区。除非要丢弃原始时区并使用本地时间,否则不要使用 返回的值。请改用解析后的日历对象。格式方法也是如此。如果要设置日期格式,请在调用 之前将包含时区信息的日历传递到对象中。以下是将一种格式转换为另一种格式并保留原始时区的方法:Calendarparse()DateFormatCalendarDateFormat.getTimeZone()Dateparse()DateFormatformat()

    DateFormat originalDateFormat = new SimpleDateFormat("EEE MMM dd HH:mm:ss Z yyyy");
    DateFormat targetDateFormat = new SimpleDateFormat("EEE., MMM. dd, yyyy");

    originalDateFormat.parse(origDateString);
    targetDateFormat.setCalendar(originalDateFormat.getCalendar());
    return targetDateFormat.format(targetDateFormat.getCalendar().getTime());

它很混乱,但必要,因为它不返回保留时区的值,也不接受定义时区(类)的值。parse()format()Date