Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/305.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 解析作为查询参数传递给RESTAPI的不同日期的标准方法是什么?_Java_Rest_Java 8_Java Time - Fatal编程技术网

Java 解析作为查询参数传递给RESTAPI的不同日期的标准方法是什么?

Java 解析作为查询参数传递给RESTAPI的不同日期的标准方法是什么?,java,rest,java-8,java-time,Java,Rest,Java 8,Java Time,我正在开发一个RESTAPI,它支持将日期作为查询参数。因为它是查询参数,所以它将是字符串。现在,可以在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 现在,为了解析所有这些不同的日期

我正在开发一个RESTAPI,它支持将日期作为查询参数。因为它是查询参数,所以它将是字符串。现在,可以在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
现在,为了解析所有这些不同的日期时间,我使用了
java8datetime
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
和附加模式的代码中可以看出。现在,我首先尝试在
try块中将date解析为
LocalDateTime
,如果它在
2017-05-05
这样的情况下抛出异常,因为没有时间经过,我将在
catch块中使用
LocalDate

上述方法为我提供了我正在寻找的解决方案,但我的问题是,这是处理以字符串形式发送的日期的标准方法吗?我的方法是否符合这些标准

另外,如果可能的话,除了一些简单的解决方案,比如使用数组列表,放置所有可能的格式,然后使用for循环尝试解析日期之外,我还可以用什么方法解析不同类型的日期(上面显示的有效日期)

此方法如下所示:

public static Date parseDate(String str,
                         String... parsePatterns)
                  throws ParseException
以下是描述:

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

解析将依次尝试每个解析模式。只有在解析整个输入字符串时,才会认为解析成功。如果没有匹配的解析模式,将引发ParseException

解析器将对解析的日期宽大处理

我通常使用的是属于我的

此方法如下所示:

public static Date parseDate(String str,
                         String... parsePatterns)
                  throws ParseException
以下是描述:

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

解析将依次尝试每个解析模式。只有在解析整个输入字符串时,才会认为解析成功。如果没有匹配的解析模式,将引发ParseException

解析器将对解析的日期宽大处理

此代码段的输出为:

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
    ,我们需要为查询参数中可能缺少的部分提供默认值<代码>解析默认值
执行此操作 在代码中,您正在转换为日期。
java.util.Date
类早已过时,并且存在许多设计问题,因此如果可以,请避免使用它<代码>即时
就可以了。如果您确实需要一个旧式API的
日期
,而您现在无法更改或不想更改,请以与问题中相同的方式进行转换

编辑:现在默认为
HOUR\u OF \u DAY
,而不是
MILLI\u OF \u DAY
。后者在只有毫秒丢失的情况下引发了冲突,但格式化程序似乎只对丢失时间的默认小时感到满意

@Configuration
public class DateTimeConfig extends WebMvcConfigurationSupport {
    /**
     * https://docs.spring.io/spring-framework/docs/current/reference/html/core.html#format-configuring-formatting-globaldatetimeformat
     * @return
     */

    @Bean
    @Override
    public FormattingConversionService mvcConversionService() {
        DefaultFormattingConversionService conversionService = new DefaultFormattingConversionService(false);
        conversionService.addFormatterForFieldAnnotation(new NumberFormatAnnotationFormatterFactory());
// Register JSR-310 date conversion with a specific global format
        DateTimeFormatterRegistrar dateTimeRegistrar = new DateTimeFormatterRegistrar();
        dateTimeRegistrar.setDateTimeFormatter(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
        dateTimeRegistrar.setDateTimeFormatter(DateTimeFormatter.ofPattern("yyyy-MM-dd"));
       dateTimeRegistrar.setDateTimeFormatter(DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss'Z'"));
       dateTimeRegistrar.registerFormatters(conversionService);

  // Register date conversion with a specific global format
        DateFormatterRegistrar dateRegistrar = new DateFormatterRegistrar();
        dateRegistrar.setFormatter(new DateFormatter("yyyy-MM-dd"));
        dateRegistrar.setFormatter(new DateFormatter("yyyy-MM-dd HH:mm:ss"));
        dateRegistrar.setFormatter(new DateFormatter("yyyy-MM-dd'T'HH:mm:ss'Z'"));
        dateRegistrar.registerFormatters(conversionService);
        return conversionService;
    }
}
此代码段的输出为:

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
    ,我们需要为查询参数中可能缺少的部分提供默认值<代码>解析默认值执行此操作
在代码中,您正在转换为日期。
java.util.Date
类早已过时,并且存在许多设计问题,因此如果可以,请避免使用它<代码>即时就可以了。如果您确实需要一个旧式API的
日期
,而您现在无法更改或不想更改,请以与问题中相同的方式进行转换


编辑:现在默认为
HOUR\u OF \u DAY
,而不是
MILLI\u OF \u DAY
。后者在只有毫秒丢失的情况下导致了冲突,但格式化程序似乎只对丢失时间的默认小时感到满意。

IMHO,因为您必须指定不同的
parsePatterns
,我更喜欢问题中提到的方法,因为我可以指定一个通用解析器,并且可以使用相同的解析器来解析不同的datetime format.IMHO,因为您必须指定不同的
parsePatterns
,我更喜欢问题中提到的方法,因为我可以指定一个通用解析器,并且可以使用相同的解析器来解析不同的日期时间格式。事实上,在一个字段中需要5种不同的格式,这本身并不是标准的。您可能会为每种格式附加一个不同的格式化程序。@但是,这意味着如果将来我们支持10种不同的日期时间格式,那么我们需要10个日期时间解析器。但使用上述方法,可能会有另一个datetime解析器覆盖剩余的datetime。这就是标准存在的原因。您为系统定义了一个接口,如果有人想使用,他们需要调整格式。我不认为接受所有这些不同的格式有什么好处,相反,你必须处理所有可能的情况,使代码成为mes
@Configuration
public class DateTimeConfig extends WebMvcConfigurationSupport {
    /**
     * https://docs.spring.io/spring-framework/docs/current/reference/html/core.html#format-configuring-formatting-globaldatetimeformat
     * @return
     */

    @Bean
    @Override
    public FormattingConversionService mvcConversionService() {
        DefaultFormattingConversionService conversionService = new DefaultFormattingConversionService(false);
        conversionService.addFormatterForFieldAnnotation(new NumberFormatAnnotationFormatterFactory());
// Register JSR-310 date conversion with a specific global format
        DateTimeFormatterRegistrar dateTimeRegistrar = new DateTimeFormatterRegistrar();
        dateTimeRegistrar.setDateTimeFormatter(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
        dateTimeRegistrar.setDateTimeFormatter(DateTimeFormatter.ofPattern("yyyy-MM-dd"));
       dateTimeRegistrar.setDateTimeFormatter(DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss'Z'"));
       dateTimeRegistrar.registerFormatters(conversionService);

  // Register date conversion with a specific global format
        DateFormatterRegistrar dateRegistrar = new DateFormatterRegistrar();
        dateRegistrar.setFormatter(new DateFormatter("yyyy-MM-dd"));
        dateRegistrar.setFormatter(new DateFormatter("yyyy-MM-dd HH:mm:ss"));
        dateRegistrar.setFormatter(new DateFormatter("yyyy-MM-dd'T'HH:mm:ss'Z'"));
        dateRegistrar.registerFormatters(conversionService);
        return conversionService;
    }
}