Java DateFormat parse()不';我不尊重时区
结果如下: 2011-09-2414:10:51-0400 2011年9月24日星期六20:10:51 CESTJava DateFormat parse()不';我不尊重时区,java,parsing,date,format,Java,Parsing,Date,Format,结果如下: 2011-09-2414:10:51-0400 2011年9月24日星期六20:10:51 CEST 为什么当我解析从format()获得的日期时,它不尊重时区?您正在打印调用结果,调用结果总是使用默认时区。基本上,除了调试之外,您不应该使用Date.toString() 不要忘记,日期没有时区-它表示时间上的一个瞬间,从Unix纪元(1970年1月1日UTC午夜)开始以毫秒为单位测量 如果您再次使用格式化程序格式化日期,应该会得到与以前相同的答案 顺便说一句,如果您正在用Java进
为什么当我解析从format()获得的日期时,它不尊重时区?您正在打印调用结果,调用结果总是使用默认时区。基本上,除了调试之外,您不应该使用
Date.toString()
不要忘记,日期
没有时区-它表示时间上的一个瞬间,从Unix纪元(1970年1月1日UTC午夜)开始以毫秒为单位测量
如果您再次使用格式化程序格式化日期,应该会得到与以前相同的答案
顺便说一句,如果您正在用Java进行大量的日期/时间工作,我建议使用而不是Date
/Calendar
;这是一个更好的API
DateFormat是日期/时间格式化子类的抽象类
哪种格式和解析日期或时间的语言独立
态度。日期/时间格式子类,例如SimpleDataFormat,
允许格式化(即日期->文本)、解析(文本->日期),
和正常化日期表示为日期对象或
自1970年1月1日00:00:00 GMT以来的毫秒数
从中,它返回EPOCH timeDateFormat.parse()
不是查询(返回值且不更改系统状态的内容)。这是一个命令,其副作用是更新内部日历
对象。调用parse()
后,您必须通过访问DateFormat
的Calendar
或调用DateFormat.getTimeZone()
来访问时区。除非您想丢弃原始时区并使用本地时间,否则不要使用parse()
返回的Date
值。而是在解析后使用日历对象。格式化方法也是如此。如果要格式化日期,请在调用format()
之前,将带有时区信息的日历传递到DateFormat
对象中。以下是如何将一种格式转换为另一种格式,以保留原始时区:
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();
}
这很混乱,但很有必要,因为
parse()
不返回保留时区的值,format()
不接受定义时区的值(日期类)。一个java.util.Date
对象不像;相反,它表示自称为“历元”的标准基准时间(即1970年1月1日00:00:00 GMT)起的毫秒数。因为它不保存任何格式和时区信息,所以它应用格式,EEE MMM dd HH:mm:ss z yyyy
和JVM的时区来返回从该毫秒值派生的Date\toString
值。如果需要以不同的格式和时区打印日期时间,则需要使用带有所需格式和适用时区的SimpleDateFormat
,例如:
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());
请注意,java.util
Date-Time API及其格式化API,SimpleDataFormat
已经过时且容易出错。建议完全停止使用,并切换到*
使用java.time
的解决方案,现代API:
输出:
import java.time.OffsetDateTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Locale;
public class Main {
public static void main(String[] args) {
ZonedDateTime zdt = ZonedDateTime.now(ZoneId.of("America/New_York"));
System.out.println(zdt);
// With timezone offset
OffsetDateTime odt = zdt.toOffsetDateTime();
System.out.println(odt);
// In a custom format
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("uuuu-MM-dd HH:mm:ss Z", Locale.ENGLISH);
String formatted = dtf.format(odt);
System.out.println(formatted);
}
}
在这里,您可以使用yyyy
而不是uuu
但是
了解更多关于java.time
、来自的*
*无论出于何种原因,如果您必须坚持使用Java6或Java7,您可以使用哪个backport将大部分Java.time功能移植到Java6&7。如果您正在为Android项目工作,并且您的Android API级别仍然不符合Java-8,请检查并确认。
没错……试着打印
System.out.println(df.format(df.parse(df.format(cal.getTime())))代码>并且它按预期工作:-)好的,那么问题显然来自toString()?谢谢您的建议。@MaximeLaval:FromDate.toString
特别是,是的-您需要注意的是,Date
只是一个瞬间,而不是在任何特定的时区或日历中。除了显示/调试之外,千万不要依赖.toString
方法。还要注意SimpleDataFormatter是区域设置敏感的。@ChristopherRoussy:当然,除非记录了该行为以满足您的需要。
import java.time.OffsetDateTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Locale;
public class Main {
public static void main(String[] args) {
ZonedDateTime zdt = ZonedDateTime.now(ZoneId.of("America/New_York"));
System.out.println(zdt);
// With timezone offset
OffsetDateTime odt = zdt.toOffsetDateTime();
System.out.println(odt);
// In a custom format
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("uuuu-MM-dd HH:mm:ss Z", Locale.ENGLISH);
String formatted = dtf.format(odt);
System.out.println(formatted);
}
}
2021-06-04T14:25:08.266940-04:00[America/New_York]
2021-06-04T14:25:08.266940-04:00
2021-06-04 14:25:08 -0400