我正在从parse.com获取我的对象的createdAt时间戳,为2014-08-01T01:17:56.751Z。我有一个类可以将其转换为相对时间。
public static String timeAgo(String time){
PrettyTime mPtime = new PrettyTime();
long timeAgo = timeStringtoMilis(time);
return mPtime.format( new Date( timeAgo ) );
}
public static long timeStringtoMilis(String time) {
long milis = 0;
try {
SimpleDateFormat sd = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
Date date = sd.parse(time);
milis = date.getTime();
} catch (Exception e) {
e.printStackTrace();
}
return milis;
}
问题是这错误地解析了日期。现在的结果说40年前,这是非常错误的。我做错了什么?
当前日期格式"yyyy-MM-dd HH:mm:ss"
不适用于给定的示例2014-08-01T01:17:56.751Z
。格式缺少字符T
和Z
以及毫秒。更改为:
new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");
修复它。
还要查看SimpleDateFormat
的JavaDoc中的示例,因为它还显示了示例的正确日期格式:http://docs.oracle.com/javase/7/docs/api/java/text/SimpleDateFormat.html.
扩展@Tom的答案:
问题
当硬编码"Z"时,您假设所有日期都保存为UTC,但事实并非如此。
问题是SimpleDateFormat无法将文字'Z'
识别为UTC"-0000"偏移量的别名(无论出于何种原因,因为它声称符合ISO-8601)。
所以你不能做
new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");
因为这错误地假设所有日期都将始终以UTC书写,但您不能执行
new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ");
或者,因为这将无法解析文字"Z"出现的日期。
解决方案1:使用javax.xml.bind.DatatypeConverter
这个数据类型转换器实际上符合ISO8601,可以像一样简单地使用
import javax.xml.bind.DatatypeConverter;
public Long isoToMillis(String dateString){
Calendar calendar = DatatypeConverter.parseDateTime(dateString);
return calendar.getTime().getTime();
}
如果您无论如何都使用JAXB,那将是可行的方法。
解决方案2:使用条件格式
final static String ZULUFORMAT = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'";
final static String OFFSETFORMAT = "yyyy-MM-dd'T'HH:mm:ss.SSSZ";
/* This is a utility method, so you want the calling method
* to be informed that something is wrong with the input format
*/
public static Long isoToMillis(String dateString) throws ParseException{
/* It is the default, so we should use it by default */
String formatString = ZULUFORMAT;
if(! dateString.endsWith("Z") ) {
formatString = OFFSETFORMAT;
}
SimpleDateFormat sd = new SimpleDateFormat(formatString);
return sd.parse(dateString).getTime();
}
如果您还没有使用JAXB,您可能希望将此方法放入一个实用程序类中。