如果秒数为00,java.time.LocalDateTime转换问题

11

我的网页应用程序正在使用 Apache CXF 和 JAVA8,如果用户发送 xs:datetime 输入(秒 00),则会在响应中面临以下错误

<urn1:dateTimeVal>2016-04-29T20:00:00</urn1:dateTimeVal>

错误:

org.apache.cxf.interceptor.Fault: 编组错误:cvc-datatype-valid.1.2.1:“2016-04-29T20:00”不是“dateTime”的有效值。

经过调试和分析,如果用户将dateTimeVal设置为2016-04-29T20:00:00,则 CXF 对输入进行的验证通过,并将 XML 值反编组java.time.LocalDateTime中,其值为2016-05-05T20:00,并在返回响应时发生编组错误,因为秒数部分(00)丢失了。

欢迎提供任何帮助或提示。

P.S. :您可以尝试以下片段:

   java.time.LocalDateTime dt= java.time.LocalDateTime.of(2016, Month.MAY, 5, 20, 00, 00);
   System.out.println(dt);

注意:以上代码示例仅用于理解如何打印日期时间值。但在Web应用程序中,预期的实际返回类型是java.time.LocalDateTime

期望输出:2016-05-05T20:00:00

实际输出:2016-05-05T20:00

编辑:该字段的绑定(JAXB)内容为:

 @XmlElement(required = true, type = String.class)
    @XmlJavaTypeAdapter(LocalDateTimeAdapter.class)
    @XmlSchemaType(name = "dateTime")
    @Generated(value = "com.sun.tools.xjc.Driver", date = "2016-05-03T05:28:57+05:30", comments = "JAXB RI v2.2.11")
    @NotNull
    protected LocalDateTime dateTimeVal;

并且 LocalDateTimeAdapter 文件是

 import java.time.LocalDateTime;
    import java.time.format.DateTimeFormatter;
    import java.time.format.DateTimeParseException;
    import java.time.temporal.TemporalAccessor;
    import javax.xml.bind.annotation.adapters.XmlAdapter;

    public class LocalDateTimeAdapter
      extends XmlAdapter<String, LocalDateTime>
    {
      public static LocalDateTime parse(String value)
      {
        DateTimeFormatter dateTimeAndZoneformatter = DateTimeFormatter.ISO_OFFSET_DATE_TIME;
        DateTimeFormatter dateTimeformatter = DateTimeFormatter.ISO_LOCAL_DATE_TIME;
        TemporalAccessor ta = null;
        try
        {
          ta = dateTimeformatter.parse(value);
        }
        catch (DateTimeParseException ex)
        {
          ta = dateTimeAndZoneformatter.parse(value);
        }
        return LocalDateTime.from(ta);
      }

      public static String print(LocalDateTime value)
      {
        return value.toString();
      }

      public LocalDateTime unmarshal(String value)
      {
        return parse(value);
      }

      public String marshal(LocalDateTime value)
      {
        return print(value);
      }
    }

你是否在某个时候使用 toString() 将 LocalDateTime 转换为 String? - assylias
不,所有内部转换都仅在CXF和Java之间完成。 - Arun Kumar
你是否有一个jaxb绑定文件、在你的pojo中使用的jaxb注释或任何未展示给我们的编组适配器? - Hank D
在问题中添加了编组适配器(LocalDateTimeAdapter)和JAXB绑定详细信息。 - Arun Kumar
2个回答

7
问题似乎出现在LocalDateTimeAdapter.print()中。LocalDateTime.toString()在秒值为0时省略了秒数。
如果您将其更改为:
public static String print(LocalDateTime value)
{
    return value.format(DateTimeFormatter.ISO_LOCAL_DATE_TIME);
}

在编组时,它还将提供秒数。

为了看一个快速的例子,请注意以下代码片段的结果:

System.out.println(LocalDateTime.of(2016,1,1,0,0,0,0).toString());
System.out.println(LocalDateTime.of(2016,1,1,0,0,0,0).format(DateTimeFormatter.ISO_LOCAL_DATE_TIME));

它提供的输出结果是:
2016-01-01T00:00
2016-01-01T00:00:00

LocalDateTime.toString() 的文档中,它解释了这个行为:
输出将是以下 ISO-8601 格式之一: - uuuu-MM-dd'T'HH:mm - uuuu-MM-dd'T'HH:mm:ss - uuuu-MM-dd'T'HH:mm:ss.SSS - uuuu-MM-dd'T'HH:mm:ss.SSSSSS - uuuu-MM-dd'T'HH:mm:ss.SSSSSSSSS 所使用的格式将是最短的,输出完整值的时间,其中省略的部分被认为是零。

我已经在问题中添加了绑定内容的详细信息。请参考 EDIT:部分获取详情。 - Arun Kumar

4

您可能想使用

System.out.println (DateTimeFormatter.ISO_LOCAL_DATE_TIME.format (dt));

它会给出:
2016-05-05T20:00:00

响应应该以 java.time.LocalDateTime 类型返回,而不是使用 DateTimeFormatter.ISO_LOCAL_DATE_TIME.format (dt) 返回的 String - Arun Kumar
+1:看起来问题在于 LocalDateTimeAdapter.print 方法。return value.toString() 应该改为 return DateTimeFormatter.ISO_LOCAL_DATE_TIME.format(value);我会尝试看看是否有效! - Arun Kumar
对于JAXB,您需要在XJB绑定文件中定义一个适配器类。例如:<globalBindings generateValueClass="true"><javaType name="org.joda.time.LocalDateTime" xmlType="xs:dateTime" parseMethod="com.helger.peppol.DateAdapter.getLocalDateTimeFromXSD" printMethod="com.helger.peppol.DateAdapter.getAsStringXSD" /></globalBindings>(使用Joda时间而不是Java8 DT)。请参阅https://github.com/phax/peppol-commons/tree/master/peppol-commons以获取整个项目设置。 - Philip Helger

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接