Java 7 通过字符(而不是小写或大写)在类中引入了SimpleDateFormat
对 ISO 8601 格式的支持。在 Java 6 中支持这种格式需要预处理,所以最好的方法就是问题。X
Z
这种新格式是Z
(大写 Z)的超集,还有 2 个附加变体:
- “分钟”字段是可选的(即,2 位而不是 4 位时区是有效的)
- 冒号字符 (':') 可用于将 2 位数“小时”字段与 2 位数“分钟”字段分开)。
因此,从Java 7 的文档中SimpleDateFormat
可以看出,以下 3 种格式现在是有效的(而不仅仅是Z
Java 6 中涵盖的第二种格式),当然,它们是等效的:
- -08
- -0800
- -08:00
正如前面关于支持这种“扩展”时区格式的特殊情况(始终使用“:”作为分隔符)的问题中所讨论的,将 Java 7 功能反向移植到 Java 6 的最佳方法是子类化SimpleDateformat
该类并覆盖其parse()
方法, IE:
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
并且您想要解析符合模式的日期yyyy-MM-dd'T'HH:mm:ssX
,那么您应该使用实例化为的对象
new ExtendedSimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ");
在上述较早的问题中,建议使用正则表达式:(?=[0-9]{2}$)
来删除“:”,并且在类似的问题中,建议使用正则表达式(?<=[+-]\d{2})$
在需要时将“分钟”字段附加为00
。
显然,成功运行 2 个替换可用于实现全部功能。因此,iso
覆盖parse()
方法中的局部变量将设置为
iso = date.replaceFirst(":(?=[0-9]{2}$)","");
或者
iso = iso.replaceFirst("(?<=[+-]\\d{2})$", "00");
在两者之间进行if
检查,以确保pos
稍后也正确设置了该值,并且也用于length()
较早的比较。
问题是:我们是否可以使用单个正则表达式来实现相同的效果,包括不需要检查长度和pos
稍后正确设置几行所需的信息?
该实现适用于读取大量可以采用任何格式(甚至完全非日期)的字符串字段的代码,仅选择符合格式并返回已解析的 JavaDate
对象的代码。
因此,准确性和速度都至关重要(即,如果使用 2 次传球速度更快,则这种方法更可取)。