I'm getting inconsistent results when converting Date
s to LocalDate
s, around the year 200. Using the following code to do the conversion:
private LocalDate toLocalDate(Date localDate)
{
return LocalDateTime.ofInstant(localDate.toInstant(), ZoneId.systemDefault()).toLocalDate();
}
My ZoneId.systemDefault()
is Africa/Harare
, which matches the CAT
used in the test. The test case I run is
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("EEE MMM dd HH:mm:ss zzz yyyy", Locale.US);
String dateString = "Tue Jan 01 00:00:00 CAT 200";
String dateString2 = "Tue Jan 01 00:00:00 CAT 201";
String dateString3 = "Wed Dec 31 00:00:00 CAT 200";
System.out.println(toLocalDate(simpleDateFormat.parse(dateString)));
System.out.println(toLocalDate(simpleDateFormat.parse(dateString2)));
System.out.println(toLocalDate(simpleDateFormat.parse(dateString3)));
My expected output for this would be
0200-01-01
0201-01-01
0200-12-31
Or, if not that, at least consistently incorrect values. The actual results are
0199-12-31
0201-01-01
0200-12-31
So it seems that the first one is being rolled back slightly, possibly the two hours corresponding to the CAT
timezone? But why does this only happen on the one case? Doing the same experiment with the year 2000 does not produce the same error.
Stephen has provided an explanation in the comment. Basically, java.util.Date
uses a calendar system which cuts over between the Julian calendar system and the Gregorian calendar system in 1582, skipping 10 days. So dates in 1582 or before will exhibit discrepancies - but the size of the discrepancy will vary over time - by 3 days every 400 years, on average. It so happens that between 200 and 400AD, you don't see this because that corresponds to when the discrepancy is 0.
Here's a short but complete program to demonstrate the problem:
import java.time.*;
import java.util.*;
public class Test {
public static void main(String[] args) throws Exception {
// Value obtained with Noda Time: should be 0199-12-31T22:00:00Z.
long millis = -55855792800000L;
Instant instant = Instant.ofEpochMilli(millis);
Date date = new Date(millis);
System.out.println(instant);
System.out.println(date);
}
}
Output on my machine:
0199-12-31T22:00:00Z
Tue Jan 01 22:00:00 GMT 200
This is all complicated by the problems in your initial code of assuming CAT and Africa/Harare are the same (at that point in time, Africa/Harare is regarded as having an offset of +02:10) and the incorrect day names in your strings - but it's the bug in Java which is causing the issue here.
I suggest you perform all your parsing using the java.time.format
classes - then I'd hope you won't get this inconsistency.
See more on this question at Stackoverflow