Java 6中对ISO 8601格式的通用支持

PNS*_*PNS 8 java regex date simpledateformat java-6

Java 7 SimpleDateFormat通过字符X(而不是大写或小写Z)在ISO 8601格式的类中引入了支持.在Java 6中支持这样的格式需要预处理,因此最好的方法是问题.

这种新格式是Z(大写Z)的超集,另外还有两种变体:

  1. "分钟"字段是可选的(即,2位而不是4位时区有效)
  2. 冒号字符(':')可用于将2位"小时"字段与2位"分钟"字段分开.

因此,正如人们可以从Java 7文档中SimpleDateFormat看到的那样,以下3种格式现在是有效的(而不仅仅是ZJava 6中涵盖的第二种格式),当然,等效:

  1. -08
  2. -0800
  3. -08:00

正如之前关于支持这种"扩展"时区格式的特殊情况的问题所讨论的那样,始终使用':'作为分隔符,将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次传递更快,这种方法是可取的).

ggr*_*des 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();
    }
}
Run Code Online (Sandbox Code Playgroud)


Ole*_*.V. 5

您可以在 Java 6 中使用 java.time,即现代 Java 日期和时间 API。在我看来,这是一个很好且面向未来的解决方案。它对 ISO 8601 有良好的支持。

\n\n
import 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}\n
Run Code Online (Sandbox Code Playgroud)\n\n

该程序的输出是:

\n\n
\n
2012-10-01T19:30+02:00\n2012-10-01T19:30+02:00\n2012-10-01T19:30+02:00\n2012-10-01T19:30Z\n
Run Code Online (Sandbox Code Playgroud)\n
\n\n

它要求您将 ThreeTen Backport 库添加到您的项目设置中。

\n\n
    \n
  • 在 Java 8 及更高版本以及较新的 Android 设备(从 API 级别 26 开始)中,现代 API 是内置的。
  • \n
  • 在 Java 6 和 7 中,获取 ThreeTen Backport,即新类的向后移植(ThreeTen for JSR 310;请参阅底部的链接)。
  • \n
  • 在(较旧的)Android 上使用 ThreeTen Backport 的 Android 版本。它\xe2\x80\x99s 称为ThreeTenABP。并确保从org.threeten.bp子包中导入日期和时间类。
  • \n
\n\n

从代码中可以看出,+02and+0200需要一个格式化程序来指定偏移量的格式,同时+02:00(也Z)符合默认格式,并且不需要指定 \xe2\x80\x99t 。

\n\n

我们可以使用相同的格式化程序解析所有偏移格式吗?

\n\n

读取混合数据时,您不想\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));\n
Run Code Online (Sandbox Code Playgroud)\n\n

输出与上面相同。中的方括号表示可能存在[XXX][XX][X]格式+02:00,+0200或。+02

\n\n

链接

\n\n\n