什么是解析为查询-PARAMS传递给REST API不同日期的标准呢?(What is the St

2019-10-29 04:33发布

我工作的支持日期作为查询参数一个REST API。 既然是查询参数将是字符串。 现在,日期可以在QueryParams以下格式发送:

yyyy-mm-dd[(T| )HH:MM:SS[.fff]][(+|-)NNNN] 

这意味着以下是有效日期:

2017-05-05 00:00:00.000+0000
2017-05-05 00:00:00.000
2017-05-05T00:00:00
2017-05-05+0000
2017-05-05

现在来分析所有这些不同的日期时间我使用Java8 datetime API。 该代码是,如下所示:

DateTimeFormatter formatter = new DateTimeFormatterBuilder().parseCaseInsensitive()
    .append(DateTimeFormatter.ofPattern("yyyy-MM-dd[[ ][['T'][ ]HH:mm:ss[.SSS]][Z]"))
    .toFormatter(); 
LocalDateTime localDateTime = null;
LocalDate localDate = null;
ZoneId zoneId = ZoneId.of(ZoneOffset.UTC.getId());
Date date = null;

try {
    localDateTime = LocalDateTime.parse(datetime, formatter);
    date = Date.from(localDateTime.atZone(zoneId).toInstant());
} catch (Exception exception) {
    System.out.println("Inside Excpetion");
    localDate = LocalDate.parse(datetime, formatter);
    date = Date.from(localDate.atStartOfDay(zoneId).toInstant());
}

由于可以从代码中作用似乎我使用DateTimeFormatter和附加的模式。 现在我第一次试图解析日期LocalDateTimetry-block ,如果它抛出了样病例异常2017-05-05 ,因为没有时间已过,我使用的是LocalDatecatch block

上述方法是给我,我在寻找解决办法,但我的问题是,这是对付发送日期为字符串,是我的做法是符合这些标准的标准呢?

此外,如果可能的话有什么其他的方式我可以分析不同类型的日期(见上有效日期),除了像使用一个数组列表,并把所有可能的格式,然后把其他一些简单的解决方案,使用循环试图解析日期?

Answer 1:

    DateTimeFormatter formatter = new DateTimeFormatterBuilder()
            .append(DateTimeFormatter.ISO_LOCAL_DATE)
            // time is optional
            .optionalStart()
            .parseCaseInsensitive()
            .appendPattern("[ ]['T']")
            .append(DateTimeFormatter.ISO_LOCAL_TIME)
            .optionalEnd()
            // offset is optional
            .appendPattern("[xx]")
            .parseDefaulting(ChronoField.HOUR_OF_DAY, 0)
            .parseDefaulting(ChronoField.OFFSET_SECONDS, 0)
            .toFormatter();
    for (String queryParam : new String[] {
            "2017-05-05 00:00:00.000+0000",
            "2017-05-05 00:00:00.000",
            "2017-05-05T00:00:00",
            "2017-05-05+0000",
            "2017-05-05",
            "2017-05-05T11:20:30.643+0000",
            "2017-05-05 16:25:09.897+0000",
            "2017-05-05 22:13:55.996",
            "2017-05-05t02:24:01"
    }) {
        Instant inst = OffsetDateTime.parse(queryParam, formatter).toInstant();
        System.out.println(inst);
    }

从这段代码的输出是:

2017-05-05T00:00:00Z
2017-05-05T00:00:00Z
2017-05-05T00:00:00Z
2017-05-05T00:00:00Z
2017-05-05T00:00:00Z
2017-05-05T11:20:30.643Z
2017-05-05T16:25:09.897Z
2017-05-05T22:13:55.996Z
2017-05-05T02:24:01Z

我使用的技巧包括:

  • 可选部分可以被包括在任一optionalStart / optionalEnd或在[]中的图案。 我同时使用,每个地方我觉得更容易阅读,你可能更喜欢不同。
  • 目前已经有日期和时间预定义的格式化,所以我重用这些。 特别是我拿的,事实的优点DateTimeFormatter.ISO_LOCAL_TIME已经处理了可选秒,秒的小数。
  • 解析成OffsetDateTime工作,我们需要对可能的查询参数缺少的部分提供缺省值。 parseDefaulting做到这一点。

在你的代码被转换为一个Date 。 该java.util.Date类是早已过时,并拥有多项设计上的问题,所以如果你能避免它。 Instant会做得很好。 如果你确实需要一个Date为传统的API,你不能改变或不想刚才改变,转换以同样的方式,你在做的问题。

编辑:现在违约HOUR_OF_DAY ,不MILLI_OF_DAY 。 后者导致当只有米利斯失踪冲突,但似乎格式是高兴的一天的只是默认小时的时间丢失时。



Answer 2:

我通常使用的DateUtils.parseDate属于公共琅 。

这种方法看起来是这样的:

public static Date parseDate(String str,
                         String... parsePatterns)
                  throws ParseException

下面是说明:

解析代表通过尝试各种不同的解析器的日期的字符串。

解析将依次尝试每个解析模式。 解析只认为是成功的,如果它解析整个输入字符串。 如果没有解析模式匹配,一个ParseException被抛出。

解析器将向着解析日期宽松。



文章来源: What is the Standard way to Parse different Dates passed as Query-Params to the REST API?