PNS*_*PNS 8 java regex date simpledateformat java-6
Java 7 SimpleDateFormat通过字符X(而不是大写或小写Z)在ISO 8601格式的类中引入了支持.在Java 6中支持这样的格式需要预处理,因此最好的方法是问题.
这种新格式是Z(大写Z)的超集,另外还有两种变体:
因此,正如人们可以从Java 7文档中SimpleDateFormat看到的那样,以下3种格式现在是有效的(而不仅仅是ZJava 6中涵盖的第二种格式),当然,等效:
正如之前关于支持这种"扩展"时区格式的特殊情况的问题所讨论的那样,始终使用':'作为分隔符,将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;
}
Run Code Online (Sandbox Code Playgroud)
请注意,SimpleDateFormat上面的子类对象必须使用相应的Z基于模式进行初始化,即如果子类是ExtendedSimpleDateformat并且您想要解析符合模式的日期yyyy-MM-dd'T'HH:mm:ssX,那么您应该使用实例化为
new ExtendedSimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ");
Run Code Online (Sandbox Code Playgroud)
在前面提到的问题中,:(?=[0-9]{2}$)正在建议使用正则表达式去除':',并且在类似的问题(?<=[+-]\d{2})$中00,如果需要,正在建议将正则表达式附加到"分钟"字段.
显然,成功运行2个替换可用于实现完整功能.因此,iso重写parse()方法中的局部变量将设置为
iso = date.replaceFirst(":(?=[0-9]{2}$)","");
Run Code Online (Sandbox Code Playgroud)
要么
iso = iso.replaceFirst("(?<=[+-]\\d{2})$", "00");
Run Code Online (Sandbox Code Playgroud)
与if检查之间,以确保该pos值也会设置正确以后,也为length()比较早.
问题是:我们可以使用单个正则表达式来实现相同的效果,包括不必要地检查长度以及pos以后正确设置几行所需的信息吗?
该实现旨在用于读取可以采用任何格式(甚至完全非日期)的大量字符串字段的代码,仅选择符合该格式的字符串并返回已解析的Java Date对象.
因此,准确性和速度都是至关重要的(即,如果使用2次传递更快,这种方法是可取的).
似乎你可以使用这个:
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();
}
}
Run Code Online (Sandbox Code Playgroud)
您可以在 Java 6 中使用 java.time,即现代 Java 日期和时间 API。在我看来,这是一个很好且面向未来的解决方案。它对 ISO 8601 有良好的支持。
\n\nimport org.threeten.bp.OffsetDateTime;\nimport org.threeten.bp.format.DateTimeFormatter;\n\npublic class DemoIso8601Offsets {\n public static void main(String[] args) {\n System.out.println(OffsetDateTime.parse("2012-10-01T19:30:00+0200", \n DateTimeFormatter.ofPattern("uuuu-MM-dd\'T\'HH:mm:ssXX")));\n System.out.println(OffsetDateTime.parse("2012-10-01T19:30:00+02", \n DateTimeFormatter.ofPattern("uuuu-MM-dd\'T\'HH:mm:ssX")));\n System.out.println(OffsetDateTime.parse("2012-10-01T19:30:00+02:00"));\n System.out.println(OffsetDateTime.parse("2012-10-01T19:30:00Z"));\n }\n}\nRun Code Online (Sandbox Code Playgroud)\n\n该程序的输出是:
\n\n\n\n\nRun Code Online (Sandbox Code Playgroud)\n2012-10-01T19:30+02:00\n2012-10-01T19:30+02:00\n2012-10-01T19:30+02:00\n2012-10-01T19:30Z\n
它要求您将 ThreeTen Backport 库添加到您的项目设置中。
\n\norg.threeten.bp子包中导入日期和时间类。从代码中可以看出,+02and+0200需要一个格式化程序来指定偏移量的格式,同时+02:00(也Z)符合默认格式,并且不需要指定 \xe2\x80\x99t 。
读取混合数据时,您不想\xe2\x80\x99 专门处理每种偏移格式。最好在格式模式字符串中使用可选部分:
\n\n DateTimeFormatter allInOne \n = DateTimeFormatter.ofPattern("uuuu-MM-dd\'T\'HH:mm:ss[XXX][XX][X]");\n System.out.println(OffsetDateTime.parse("2012-10-01T19:30:00+0200", allInOne));\n System.out.println(OffsetDateTime.parse("2012-10-01T19:30:00+02", allInOne));\n System.out.println(OffsetDateTime.parse("2012-10-01T19:30:00+02:00", allInOne));\n System.out.println(OffsetDateTime.parse("2012-10-01T19:30:00Z", allInOne));\nRun Code Online (Sandbox Code Playgroud)\n\n输出与上面相同。中的方括号表示可能存在[XXX][XX][X]格式+02:00,+0200或。+02
java.time.java.time。java.time到 Java 6 和 7(ThreeTen for JSR-310)。