Java-序列化/反序列化日期时出错

时间:2019-02-28 12:54:05

标签: java date date-format

我很难弄清楚这个日期格式是什么:delete from table2 where ColumnA in (select ColumnA from table1) 。我尝试了不同的日期格式来获得此结果,但没有任何效果。最接近的模式是:2019-02-28T12:17:46.279+0000,但是使用此模式,输出是这样的:yyyy-MM-dd'T'HH:mm:ss.SSSZ2019-02-28T12:17:46.279-0000是秒之后而不是-

我收到此异常:

+

我的Caused by: java.lang.IllegalArgumentException: 2019-02-28T12:17:46.279+0000 at org.apache.xerces.jaxp.datatype.XMLGregorianCalendarImpl$Parser.skip(XMLGregorianCalendarImpl.java:2932) at org.apache.xerces.jaxp.datatype.XMLGregorianCalendarImpl$Parser.parse(XMLGregorianCalendarImpl.java:2898) at org.apache.xerces.jaxp.datatype.XMLGregorianCalendarImpl.<init>(XMLGregorianCalendarImpl.java:478) at org.apache.xerces.jaxp.datatype.DatatypeFactoryImpl.newXMLGregorianCalendar(DatatypeFactoryImpl.java:230) at __redirected.__DatatypeFactory.newXMLGregorianCalendar(__DatatypeFactory.java:132) at javax.xml.bind.DatatypeConverterImpl.parseDate(DatatypeConverterImpl.java:519) at javax.xml.bind.DatatypeConverter.parseDate(DatatypeConverter.java:431) at eu.europa.ec.my.custom.package.model.mapper.XsdDateTimeConverter.unmarshal(XsdDateTimeConverter.java:23) 类看起来像这样:

XsdDateTimeConverter

我的postgres数据库中的解析日期看起来像这样:

public class XsdDateTimeConverter {

    public static Date unmarshal(String dateTime) {
        return DatatypeConverter.parseDate(dateTime).getTime();
    }

    public static String marshalDate(Date date) {
        final Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        return DatatypeConverter.printDate(calendar);
    }

    public static String marshalDateTime(Date dateTime) {
        final Calendar calendar = Calendar.getInstance();
        calendar.setTime(dateTime);
        return DatatypeConverter.printDateTime(calendar);
    }
}

在我的休息方法中,我像这样使用move_timestamp timestamp(6) with time zone 2019-02-28 12:17:46.279+00

ObjectMapper

我想我真正想要的是这个日期的正确模式。我可以进入此页面:http://www.sdfonlinetester.info/并输入我的模式(例如MyCustomResponseDto responseDto = customService.getCustomResponseDto(query); ObjectMapper mapper = new ObjectMapper(); mapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false); String strValue = mapper.writeValueAsString(responseDto); return Response.ok(strValue).build(); ),它会为您提供该模式的实际日期输出。我需要另一种方式。我想输入日期,它将为我提供正确的模式。

3 个答案:

答案 0 :(得分:2)

tl; dr

OffsetDateTime.parse( 
    "2019-02-28T12:17:46.279+0000" , 
    DateTimeFormatter.ofPattern( "uuuu-MM-dd'T'HH:mm:ss.SSSX" , Locale.ROOT )
)

java.time

您使用的是可怕的Calendar类,而该类在多年前被 java.time 类所取代。

ISO 8601

您的输入字符串为标准ISO 8601格式,旨在用于人类可读的日期时间值的机器可解析的文本表示形式。这是一件好事。

java.time 类在解析/生成字符串时默认使用ISO 8601格式。

OffsetDateTime

应该能够简单地用OffsetDateTime进行解析。

OffsetDateTime.parse( "2019-02-28T12:17:46.279+0000" )

...但是不幸的是,从偏移量(+00:00)中省略了可选的冒号字符是一个问题。 OffsetDateTime类有一个小错误,它在没有该字符的情况下拒绝解析。在herehere中讨论了该错误。

ISO 8601标准允许不存在冒号,但实际上您应该始终将其包括在内。 OffsetDateTime类并不孤单。我已经看到其他库在缺少冒号或填充零时中断。我建议您要求数据发布者使用完整的ISO 8601格式,包括冒号。

OffsetDateTime错误的解决方法是显式定义DateTimeFormatter

DateTimeFormatter f = DateTimeFormatter.ofPattern( "uuuu-MM-dd'T'HH:mm:ss.SSSX" , Locale.ROOT ) ;

然后解析。

String input = "2019-02-28T12:17:46.279+0000" ;
OffsetDateTime odt = OffsetDateTime.parse( input , f ) ;

要生成完全标准的ISO 8601格式的文本,只需调用toString

String output = odt.toString() ;

请参阅此code run live at IdeOne.com

  

输出:2019-02-28T12:17:46.279Z

最后的Z表示UTC,即+0000+00:00。发音为“ Zulu”。非常常用,比数字偏移量更易读。

如果您想要与输入相同的输出格式,请使用相同的DateTimeFormatter

String output = odt.format( f ) ;

答案 1 :(得分:0)

您可以尝试以下代码

SimpleDateFormat格式=新的SimpleDateFormat(“ yyyy-MM-dd'T'HH:mm:ss.SSSZ”,Locale.ENGLISH); 字符串lastmod = format.format(new Date());

答案 2 :(得分:0)

为自己省去了很多麻烦,并以毫秒为单位节省了时间。仅在UI中解析和呈现日期。很少有人为人类安排时间,这需要计算机知道小时,日,周,月,年...但是节省时间只是一个“漫长的”时间。