Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

java.time.LocalDateTime conversion issue if seconds are 00

My web application is using Apache CXF and JAVA8, and facing below error in response if user send xs:datetime input(seconds 00) as

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

ERROR :

org.apache.cxf.interceptor.Fault: Marshalling Error: cvc-datatype-valid.1.2.1: '2016-04-29T20:00' is not a valid value for 'dateTime'.

I debug and analysed that if user send dateTimeVal as 2016-04-29T20:00:00 then CXF validations for input are passed and XML value is UnMarshaled to java.time.LocalDateTime as 2016-05-05T20:00 , and at the time of returning the response, the Marshaling error occurs due to loss of seconds part(00).

Any help/hint are appreciated.

P.S : You can try with below snippet :

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

Note : Above code sample is just for understanding to print datetime value. But actual return type expected in web application is java.time.LocalDateTime

OUTPUT EXPECTED : 2016-05-05T20:00:00

OUTPUT ACTUAL : 2016-05-05T20:00

EDIT : The binding (JAXB) content for the field is :

 @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;

AND LocalDateTimeAdapter File is

 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);
      }
    }
like image 553
Arun Kumar Avatar asked May 04 '16 10:05

Arun Kumar


People also ask

How do I get time difference in LocalDateTime?

getDays() + " days " + time[0] + " hours " + time[1] + " minutes " + time[2] + " seconds.");

Is LocalDateTime a UTC?

The LocalDateTime class represents the date-time,often viewed as year-month-day-hour-minute-second and has got no representation of time-zone or offset from UTC/Greenwich.

How do I get LocalDateTime in a specific format?

1. LocalDate. LocalDate is an immutable class that represents Date with default format of yyyy-MM-dd. We can use now() method to get the current date.


2 Answers

The problem appears to be in LocalDateTimeAdapter.print(). LocalDateTime.toString() omits the seconds when the seconds value is 0.

If you change it to

public static String print(LocalDateTime value)
{
    return value.format(DateTimeFormatter.ISO_LOCAL_DATE_TIME);
}

it will provide the seconds as well when marshaling.

To see a quick example, note the results of the following snippet:

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));

The output it gives is

2016-01-01T00:00
2016-01-01T00:00:00

In the documentation for LocalDateTime.toString() it explains this behavior:

The output will be one of the following ISO-8601 formats:
- 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
The format used will be the shortest that outputs the full value of the time where the omitted parts are implied to be zero.

like image 136
Hank D Avatar answered Oct 30 '22 07:10

Hank D


You may want to use

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

It gives:

2016-05-05T20:00:00
like image 34
Philip Helger Avatar answered Oct 30 '22 07:10

Philip Helger