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

问题描述 投票:0回答:3

我很难弄清楚这个日期格式是什么:2019-02-28T12:17:46.279+0000。我尝试了不同的日期格式来获得这个结果,但没有任何效果。最近的模式是:yyyy-MM-dd'T'HH:mm:ss.SSSZ但是这个模式的输出是这样的:2019-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课程看起来像这样:

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

我的postgres db中的解析日期如下所示:

move_timestamp timestamp(6) with time zone

2019-02-28 12:17:46.279+00

在我的休息方法中,我像这样使用ObjectMapper

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

我想我真正想要的是这个日期的正确模式是什么。我可以进入这个页面:http://www.sdfonlinetester.info/并输入我的模式(例如yyyy-MM-dd'T'HH:mm:ss.SSSZ),它会为您提供该模式的实际日期输出。我需要相反的方式。我想输入我的约会,它会给我正确的模式。

java date date-format
3个回答
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

你正在使用几年前被java.time类取代的糟糕的Calendar类。

ISO 8601

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

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

OffsetDateTime

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

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

...但不幸的是,从偏移量(+00:00)中省略了可选的COLON字符是一个问题。 OffsetDateTime类有一个小错误,它拒绝解析没有该字符。这个bug被讨论了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 ) ;

0
投票

您可以尝试以下代码

SimpleDateFormat format = new SimpleDateFormat(“yyyy-MM-dd'T'HH:mm:ss.SSSZ”,Locale.ENGLISH); String lastmod = format.format(new Date());


0
投票

为自己省去一大堆麻烦,并以毫秒为单位节省时间。仅在UI中解析和呈现日期。极少数人类安排需要计算机知道小时,天,周,月,年......但是及时保存只是一个“长期”。

© www.soinside.com 2019 - 2024. All rights reserved.