Java 7通过字符SimpleDateFormat
(而不是小写或大写X
)引入了{8}格式Z
类的支持。在Java 6中支持这样的格式需要预处理,因此最好的方法是问题。
这种新格式是Z
(大写Z)的超集,另外还有两种变体:
因此,正如人们可以从Java 7 documentation of SimpleDateFormat
观察到的,以下3种格式现在是有效的(而不仅仅是Java 6中Z
覆盖的第二种格式),当然,等同于:< / p>
如earlier question中所述,关于支持这种“扩展”时区格式的特殊情况,总是使用':'作为分隔符,将Java 7功能向后移植到Java 6中的最佳方法是子类SimpleDateformat
类并覆盖其parse()
方法,即:
public Date parse(String date, ParsePosition pos)
{
String iso = ... // Replace the X with a Z timezone string, using a regex
if (iso.length() == date.length())
{
return null; // Not an ISO 8601 date
}
Date parsed = super.parse(iso, pos);
if (parsed != null)
{
pos.setIndex(pos.getIndex()+1); // Adjust for ':'
}
return parsed;
}
请注意,必须使用相应的基于SimpleDateFormat
的模式初始化上面的子类Z
对象,即子类是ExtendedSimpleDateformat
并且您想要解析符合模式的日期{ {1}},那么你应该使用实例化为
yyyy-MM-dd'T'HH:mm:ssX
在前面提到的earlier question中,建议使用正则表达式new ExtendedSimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ");
来删除“:”而在similar question中,建议使用正则表达式:(?=[0-9]{2}$)
附加如果需要,“分钟”字段为(?<=[+-]\d{2})$
。
显然,成功运行2个替换可用于实现全部功能。因此,重写的00
方法中的iso
局部变量将设置为
parse()
或
iso = date.replaceFirst(":(?=[0-9]{2}$)","");
在iso = iso.replaceFirst("(?<=[+-]\\d{2})$", "00");
之间进行检查,以确保稍后也正确设置if
值,并且之前也进行pos
比较。
问题是:我们是否可以使用单个正则表达式来实现相同的效果,包括不必要地检查长度以及稍后正确设置length()
几行所需的信息?
该实现旨在用于读取可以采用任何格式(甚至完全非日期)的大量字符串字段的代码,仅选择符合该格式的字符串并返回已解析的Java pos
对象
因此,准确度和速度都至关重要(例如,如果使用2次传递更快,则此方法更为可取。)
答案 0 :(得分:6)
似乎你可以使用它:
import java.util.Calendar;
import javax.xml.bind.DatatypeConverter;
public class TestISO8601 {
public static void main(String[] args) {
parse("2012-10-01T19:30:00+02:00"); // UTC+2
parse("2012-10-01T19:30:00Z"); // UTC
parse("2012-10-01T19:30:00"); // Local
}
public static Date parse(final String str) {
Calendar c = DatatypeConverter.parseDateTime(str);
System.out.println(str + "\t" + (c.getTime().getTime()/1000));
return c.getTime();
}
}
答案 1 :(得分:2)
您可以在Java 6中使用现代的Java日期和时间API java.time。在我看来,这是一个不错的且可以面向未来的解决方案。它对ISO 8601有很好的支持。
import org.threeten.bp.OffsetDateTime;
import org.threeten.bp.format.DateTimeFormatter;
public class DemoIso8601Offsets {
public static void main(String[] args) {
System.out.println(OffsetDateTime.parse("2012-10-01T19:30:00+0200",
DateTimeFormatter.ofPattern("uuuu-MM-dd'T'HH:mm:ssXX")));
System.out.println(OffsetDateTime.parse("2012-10-01T19:30:00+02",
DateTimeFormatter.ofPattern("uuuu-MM-dd'T'HH:mm:ssX")));
System.out.println(OffsetDateTime.parse("2012-10-01T19:30:00+02:00"));
System.out.println(OffsetDateTime.parse("2012-10-01T19:30:00Z"));
}
}
此程序的输出为:
2012-10-01T19:30+02:00 2012-10-01T19:30+02:00 2012-10-01T19:30+02:00 2012-10-01T19:30Z
这要求您将ThreeTen Backport库添加到项目设置中。
org.threeten.bp
导入日期和时间类。从代码中可以看到,+02
和+0200
要求使用格式化程序来指定偏移量的格式,而+02:00
(也需要Z
)要符合使用默认格式,无需指定。
读取混合数据时,您不想专门处理每种偏移格式。最好在格式模式字符串中使用可选部分:
DateTimeFormatter allInOne
= DateTimeFormatter.ofPattern("uuuu-MM-dd'T'HH:mm:ss[XXX][XX][X]");
System.out.println(OffsetDateTime.parse("2012-10-01T19:30:00+0200", allInOne));
System.out.println(OffsetDateTime.parse("2012-10-01T19:30:00+02", allInOne));
System.out.println(OffsetDateTime.parse("2012-10-01T19:30:00+02:00", allInOne));
System.out.println(OffsetDateTime.parse("2012-10-01T19:30:00Z", allInOne));
输出与上面相同。 [XXX][XX][X]
中的方括号表示可能存在格式+02:00
,+0200
或+02
。
java.time
。java.time
。java.time
向Java 6和7(JSR-310的ThreeTen)的反向端口。