简体   繁体   中英

java.util.Date is parsing wrong dates with dates before 1912

I don't understand the reason why Jackson library is parsing wrong dates before 1912. I suppose the problem is the java.util.Date conversion , because the problem persists with Gson.

This is my code:

ObjectMapper mapper = new ObjectMapper();
String tmp = "{\"date\":\"1911-01-01T00:00:00+00:00\"}";
        
Response resp = mapper.readValue(tmp, Response.class);
System.out.println("Date->"+resp.date);

date is a field of type java.util.Date

As you can see, the input is: 1911-01-01T00:00:00+00:00

And the output is: Sun Jan 01 00:09:21 CET 1911 (I don't understand why that time is set)

But If I set this input: 1912-01-01T00:00:00+00:00

The ouput is correct: Mon Jan 01 00:00:00 CET 1912

Only happens with dates before 1912.

Jdk v1.8.0_101

Thanks.

java.time

Never use the legacy class Date . Do not waste your time trying to understand the awful mess that is Date and Calendar .

Use only the modern java.time classes. Later versions of Jackson support java.time .

OffsetDateTime odt = OffsetDateTime.parse( "1911-01-01T00:00:00+00:00" ) ;

When asked to produce text representing its value, that OffsetDateTime generates:

odt.toString(): 1911-01-01T00:00Z

The Z on the end means an offset of zero hours-minutes-seconds from UTC, and is pronounced “Zulu”.


For an explanation as to what happened with your code using the legacy classes, see the excellent Answer by Ole VV But notice that using the properly-designed classes in java.time avoids the underlying issue: Applying a time zone where none was called for.

A time zone is a history of the past, present, and future changes to the offset used by the people of a particular region. Your input carries an offset (of zero), with no indication of time zone. So no need to involve a time zone in processing your input.

The good answer with the good solution has been posted by Basil Bourque. Here's the answer explaining the reason for what you observed.

Europe/Paris time zone was at offset +00:09:21 from when a standard time was defined until March 11, 1911. I believe that some French possessions in Northern Africa (Algeria, Tunisia) followed suit. So if your default time zone falls within one of those places, then VGR is correct in the comment that your output is correct.

Nit-picking: Only the time zone abbreviation is debatable. According to the link below it should be PMT (supposedly for Paris Mean Time), not CET (supposedly for Central European Time). I don't think the now outdated Date class ever had ambitions of giving correct historical time zone abbreviations though. It probably just gives CET because these days Paris uses Central European Time.

Once upon a time every capital and also many other metropols had their time defined by their mean solar time rather than a whole number of hours from some standard time reference (the role that GMT later acquired and still later UTC). So an offset of +00:09:21 was nothing special back then.

    ZonedDateTime dateTimeInFrance = OffsetDateTime.parse("1911-01-01T00:00:00+00:00")
            .atZoneSameInstant(ZoneId.of("Europe/Paris"));
    System.out.println(dateTimeInFrance);

Output:

1911-01-01T00:09:21+00:09:21[Europe/Paris]

Near-duplicate: Convert a timestamp before year 1900 in java .

Further link: Time Changes in Paris Over the Years

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM