我正在尝试解析来自MongoDB的日期(2015-06-25T00:00:00.000Z)。
try {
DateFormat format = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'", Locale.ENGLISH);
Date date = format.parse("2015-06-25T00:00:00.000Z");
return new Date().after(date);
} catch (ParseException e) {
e.printStackTrace();
}
}
我哪里错了?
答案 0 :(得分:8)
您的模式只接受第二个数字,但您的字符串也包含小数秒
yyyy-MM-dd'T'HH:mm:ss 'Z'
2015-06-25 T 00:00:00.000 Z
您需要使用
"yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"
答案 1 :(得分:2)
Z
您的格式设置模式在Z
周围有单引号。这意味着将“Z”解释为仅仅是文本,期待它然后忽略它。非常糟糕,因为Z
有意义:祖鲁的缩写,意思是UTC time zone。
通过忽略Z,解析将隐式应用JVM的当前默认时区。您的输入意味着UTC中一天的第一时刻(午夜时段),但在下面的代码中,您可以看到该值在我的默认区域America/Los_Angeles
中误解为午夜 - 错误为7小时(我的区域当前offset from UTC)。
try {
java.text.DateFormat format = new SimpleDateFormat ( "yyyy-MM-dd'T'HH:mm:ss'Z'" , Locale.ENGLISH );
java.util.Date date = format.parse ( "2015-06-25T00:00:00Z" );
System.out.println ( "date: " + date );
} catch ( ParseException e ) {
e.printStackTrace ();
}
在此输出中,PDT
表示太平洋时间的夏令时(DST)版本(更准确地命名为America/Los_Angeles
)。请注意,时间是00:00:00,但错误 - 应该是前一天提前7小时,因为我的区域落后于 UTC。
日期:2015年6月25日星期五00:00:00
使用Java 8及更高版本中内置的java.time框架可以更轻松地完成这项工作。对于Java 6& 7,使用后端口ThreeTen-Backport。对于Android,改编后端口ThreeTenABP。
在解析/生成日期时间值的文本表示时,默认情况下java.time类使用ISO 8601格式。您的输入恰好符合ISO 8601.因此无需指定格式化模式。
Instant
是UTC时间轴上的一个时刻。
String input = "2015-06-25T00:00:00Z";
Instant instant = Instant.parse ( input );
如果需要,请申请proper time zone name。
ZoneId zoneId = ZoneId.of ( "America/Los_Angeles" );
ZonedDateTime zdt = ZonedDateTime.ofInstant ( instant , zoneId );
转储到控制台。
System.out.println ( "input: " + input + " | instant: " + instant + " | zdt: " + zdt );
输入:2015-06-25T00:00:00Z |时刻:2015-06-25T00:00:00Z | zdt:2015-06-24T17:00-07:00 [America / Los_Angeles]
请注意,在此输出中,现在可以将相同的输入正确调整到America/Los_Angeles
时区,方法是将七小时后移回上一个日期。
避免使用java.util.Date
。旧的日期时间类真的很糟糕。但是,如果需要,您可以在java.time类型和旧类型之间进行转换。在这种情况下,使用count-from - epoch毫秒。请注意,您可能会丢失一些数据,从java.util.Date中的纳秒分辨率到毫秒(不是在这种情况下,但可能在其他情况下)。
java.util.Date utilDate = new java.util.Date( instant.toEpochMilli() );