2011-09-23 78 views
14
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(); 
} 

下面是结果:Java的日期格式解析()不尊重时区

2011-09-24十四点10分51秒-0400

周六09月24日20:10 :51 CEST 2011

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

回答

23

您正在打印致电Date.toString()的结果,其中总是使用默认时区。基本上,除调试外,您不应该使用Date.toString()

不要忘记一个Date时区 - 它代表着一个时刻,因为自Unix纪元(午夜1970年1月1日UTC)毫秒。

如果您再次使用格式化程序格式化日期,那么应该与以前相同。另外,如果您在Java中执行任何大量的日期/时间工作,我会推荐使用Joda Time而不是Date/Calendar;这是一个太多更好的API。

+1

这是正确的...尝试打印'System.out。println(df.format(df.parse(df.format(cal.getTime()))));'它和预期一样:-) –

+0

好了,显然问题来自toString()?感谢您的建议。 –

+0

@MaximeLaval:特别是从'Date.toString',是的 - 你需要知道'Date'只是一个瞬间,而不是在任何特定的时区或日历。 –

2

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

spec,它返回EPOCH时间

7

DateFormat.parse()不是一个查询(东西,返回一个值,不改变系统的状态)。这是一个具有更新内部对象的副作用的命令。拨打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类)。