我正在尝试将ISO 8601格式的String转换为java.util.Date
。
如果与区域设置(比较示例)一起使用,我发现模式yyyy-MM-dd'T'HH:mm:ssZ
符合ISO8601。
但是,使用java.text.SimpleDateFormat
不能转换格式正确的String 2010-01-01T12:00:00+01:00
。 我必须先将其转换为2010-01-01T12:00:00+0100
,而不能使用冒号。
所以,目前的解决方案是
SimpleDateFormat ISO8601DATEFORMAT = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ", Locale.GERMANY);
String date = "2010-01-01T12:00:00+01:00".replaceAll("\\+0([0-9]){1}\\:00", "+0$100");
System.out.println(ISO8601DATEFORMAT.parse(date));
显然不是那么好。 我是否缺少某些东西或有更好的解决方案?
回答
感谢JuanZe的评论,我找到了Joda-Time魔术, 这里也对此进行了描述 。
因此,解决方案是
DateTimeFormatter parser2 = ISODateTimeFormat.dateTimeNoMillis();
String jtdate = "2010-01-01T12:00:00+01:00";
System.out.println(parser2.parseDateTime(jtdate));
或更简单地说,通过构造函数使用默认解析器:
DateTime dt = new DateTime( "2010-01-01T12:00:00+01:00" ) ;
对我来说,这很好。
#1楼
好的,这个问题已经回答了,但是我还是放弃了。 它可能会帮助某人。
我一直在寻找Android (API 7)的解决方案 。
- 乔达(Joda)毫无疑问-它庞大且初始化缓慢。 对于该特定目的,这似乎也是一个重大的过大杀伤力。
- 涉及
javax.xml
答案不适用于Android API 7。
最终实现了这个简单的类。 它仅涵盖最常见的ISO 8601字符串形式 ,但是在某些情况下(当您完全确定输入将采用这种格式时)就足够了。
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
/**
* Helper class for handling a most common subset of ISO 8601 strings
* (in the following format: "2008-03-01T13:00:00+01:00"). It supports
* parsing the "Z" timezone, but many other less-used features are
* missing.
*/
public final class ISO8601 {
/** Transform Calendar to ISO 8601 string. */
public static String fromCalendar(final Calendar calendar) {
Date date = calendar.getTime();
String formatted = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ")
.format(date);
return formatted.substring(0, 22) + ":" + formatted.substring(22);
}
/** Get current date and time formatted as ISO 8601 string. */
public static String now() {
return fromCalendar(GregorianCalendar.getInstance());
}
/** Transform ISO 8601 string to Calendar. */
public static Calendar toCalendar(final String iso8601string)
throws ParseException {
Calendar calendar = GregorianCalendar.getInstance();
String s = iso8601string.replace("Z", "+00:00");
try {
s = s.substring(0, 22) + s.substring(23); // to get rid of the ":"
} catch (IndexOutOfBoundsException e) {
throw new ParseException("Invalid length", 0);
}
Date date = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ").parse(s);
calendar.setTime(date);
return calendar;
}
}
性能说明:每次实例化新的SimpleDateFormat都是为了避免Android 2.1中的错误 。 如果您像我一样惊讶,请参阅这个谜语 。 对于其他Java引擎,您可以将实例缓存在私有静态字段中(使用ThreadLocal,以确保线程安全)。
#2楼
我认为我们应该使用
DateFormat format = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'")
为日期2010-01-01T12:00:00Z
#3楼
Apache Jackrabbit使用ISO 8601格式来保留日期,并且有一个帮助器类来解析它们:
org.apache.jackrabbit.util.ISO8601
#4楼
基本功能礼貌:@wrygiel。
此函数可以将ISO8601格式转换为可以处理偏移值的Java Date。 根据ISO 8601的定义,偏移可以以不同的格式提及。
±[hh]:[mm]
±[hh][mm]
±[hh]
Eg: "18:30Z", "22:30+04", "1130-0700", and "15:00-03:30" all mean the same time. - 06:30PM UTC
此类具有要转换的静态方法
- ISO8601字符串转换为Date(Local TimeZone)对象
- ISO8601字符串的日期
- 夏令时自动计算
示例ISO8601字符串
/* "2013-06-25T14:00:00Z";
"2013-06-25T140000Z";
"2013-06-25T14:00:00+04";
"2013-06-25T14:00:00+0400";
"2013-06-25T140000+0400";
"2013-06-25T14:00:00-04";
"2013-06-25T14:00:00-0400";
"2013-06-25T140000-0400";*/
public class ISO8601DateFormatter {
private static final DateFormat DATE_FORMAT_1 = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ");
private static final DateFormat DATE_FORMAT_2 = new SimpleDateFormat("yyyy-MM-dd'T'HHmmssZ");
private static final String UTC_PLUS = "+";
private static final String UTC_MINUS = "-";
public static Date toDate(String iso8601string) throws ParseException {
iso8601string = iso8601string.trim();
if(iso8601string.toUpperCase().indexOf("Z")>0){
iso8601string = iso8601string.toUpperCase().replace("Z", "+0000");
}else if(((iso8601string.indexOf(UTC_PLUS))>0)){
iso8601string = replaceColon(iso8601string, iso8601string.indexOf(UTC_PLUS));
iso8601string = appendZeros(iso8601string, iso8601string.indexOf(UTC_PLUS), UTC_PLUS);
}else if(((iso8601string.indexOf(UTC_MINUS))>0)){
iso8601string = replaceColon(iso8601string, iso8601string.indexOf(UTC_MINUS));
iso8601string = appendZeros(iso8601string, iso8601string.indexOf(UTC_MINUS), UTC_MINUS);
}
Date date = null;
if(iso8601string.contains(":"))
date = DATE_FORMAT_1.parse(iso8601string);
else{
date = DATE_FORMAT_2.parse(iso8601string);
}
return date;
}
public static String toISO8601String(Date date){
return DATE_FORMAT_1.format(date);
}
private static String replaceColon(String sourceStr, int offsetIndex){
if(sourceStr.substring(offsetIndex).contains(":"))
return sourceStr.substring(0, offsetIndex) + sourceStr.substring(offsetIndex).replace(":", "");
return sourceStr;
}
private static String appendZeros(String sourceStr, int offsetIndex, String offsetChar){
if((sourceStr.length()-1)-sourceStr.indexOf(offsetChar,offsetIndex)<=2)
return sourceStr + "00";
return sourceStr;
}
}
#5楼
Jackson-databind库还具有做到这一点的ISO8601DateFormat类 (在ISO8601Utils中的实际实现。
ISO8601DateFormat df = new ISO8601DateFormat();
Date d = df.parse("2010-07-28T22:25:51Z");