I try to provide a tool to convert datetime from Java to C#. But there is a serious problem.
In Java, I read '0001-01-01' from the SQL Server database via java.sql.Date, and get the millisecond -62135798400000
.
I also consider the timezone offset.
private static long getMilliSecondWithoutTimeZone(long origin) {
return origin + (ZonedDateTime.now().getOffset().getLong(OFFSET_SECONDS) * 1000);
}
And the final millisecond is -62135769600000
.
In C#, I use this millisecond to new Datetime
var ticks = new DateTime(1970, 1, 1).Ticks + (-62135769600000 * 10000);
var date = new DateTime(ticks);
When the code runs, it will throw the exception:
System.ArgumentOutOfRangeException: 'Ticks must be between DateTime.MinValue.Ticks and DateTime.MaxValue.Ticks. (Parameter 'ticks')'
However, the conversion is correct after '1600-01-01' according to my test.
Before '1600-01-01', there always is a few days of error.
It makes me very confused.
I find the remarks in https://docs.microsoft.com/en-us/dotnet/api/system.globalization.juliancalendar?view=net-5.0#remarks
The Gregorian calendar was developed as a replacement for the Julian calendar (which is represented by the JulianCalendar class) and was first introduced in a small number of cultures on October 15, 1582. When working with historic dates that precede a culture's adoption of the Gregorian calendar, you should use the original calendar if it is available in the .NET Framework. For example, Denmark changed from the Julian calendar to the Gregorian calendar on February 19 (in the Julian calendar) or March 1 (in the Gregorian calendar) of 1700. In this case, for dates before the adoption of the Gregorian calendar, you should use the Julian calendar. However, note that no culture offers intrinsic support for the JulianCalendar class. You must use the JulianCalendar class as a standalone calendar. For more information, see Working with calendars.
The actual reason is:
- C# uses the Gregorian calendar all the time.
- Java uses the Gregorian calendar after October 15, 1582, and uses the Julian calendar before.
The solution:
import java.sql.Date;
import java.time.chrono.IsoChronology;
import java.time.*;
public class Test {
public static Long getMilliSeconds(Date date) {
if (null == date) {
return null;
}
IsoChronology ISO = IsoChronology.INSTANCE;
LocalDate ld = date.toLocalDate();
return ISO.localDateTime(LocalDateTime.of(ld.getYear(), ld.getMonth(), ld.getDayOfMonth(), 0, 0, 0)).toInstant(ZoneOffset.UTC).toEpochMilli();
}
}
question from:
https://stackoverflow.com/questions/65930964/cannot-convert-date-0001-01-01-from-java-to-c-sharp-correctly