Java DateFormat parse()不尊重时区

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

9月24日星期六20:10:51 CEST 2011

为什么当我解析格式()得到的日期时,它不尊重时区?

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

不要忘记Date没有时区 – 它代表一个时刻,以Unix时代(1970年1月1日午夜)为单位的毫秒数来衡量。

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

顺便说一句 ,如果您在Java中进行大量的日期/时间工作,我建议使用Joda Time而不是Date / Calendar ; 它是一个更好的API。

DateFormat.parse()不是一个查询(返回值并且不会改变系统状态的东西)。 这是一个具有更新内部Calendar对象的副作用的命令。 在调用parse()您必须通过访问DateFormatCalendar或调用DateFormat.getTimeZone()来访问时区。 除非您想丢弃原始时区并使用本地时间,否则请不要使用parse()返回的Date值。 而是在解析后使用日历对象。 格式方法也是如此。 如果要格式化日期,请在调用format()之前将带有时区信息的日历传递到DateFormat对象。 以下是如何将一种格式转换为另一种格式,保留原始时区:

  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类)。

DateFormat是日期/时间格式化子类的抽象类,它以与语言无关的方式格式化和分析日期或时间。 日期/时间格式化子类(如SimpleDateFormat)允许格式化(即日期 – >文本),解析(文本 – >日期)和规范化。 日期表示为Date对象或自1970年1月1日00:00:00 GMT以来的毫秒数

根据规范 ,它返回EPOCH时间