title: Cannot Convert Date '0001-01-01' from Java to C# correctly
body: <p>I try to provide a tool to convert datetime from Java to C#. But there is a serious problem.</p>
  <p>In Java, I read '0001-01-01' from the SQL Server database via java.sql.Date, and get the millisecond <code>-62135798400000</code>.</p>
  <p>I also consider the timezone offset.</p>
  <pre class="lang-java prettyprint-override"><code>private static long getMilliSecondWithoutTimeZone(long origin) {
      return origin + (ZonedDateTime.now().getOffset().getLong(OFFSET_SECONDS) * 1000);
  }
  </code></pre>
  <p>And the final millisecond is <code>-62135769600000</code>.</p>
  <p>In C#, I use this millisecond to new Datetime</p>
  <pre><code>var ticks = new DateTime(1970, 1, 1).Ticks + (-62135769600000 * 10000);
  var date = new DateTime(ticks);
  </code></pre>
  <p>When the code runs, it will throw the exception:</p>
  <pre class="lang-cs prettyprint-override"><code>System.ArgumentOutOfRangeException: 'Ticks must be between DateTime.MinValue.Ticks and DateTime.MaxValue.Ticks. (Parameter 'ticks')'
  </code></pre>
  <p>However, <strong>the conversion is correct after '1600-01-01' according to my test.</strong><br />
  Before '1600-01-01', there always is a few days of error.</p>
  <p>It makes me very confused.</p>
  <hr />
  <p>I find the remarks in <a href="https://docs.microsoft.com/en-us/dotnet/api/system.globalization.juliancalendar?view=net-5.0#remarks" rel="nofollow noreferrer">https://docs.microsoft.com/en-us/dotnet/api/system.globalization.juliancalendar?view=net-5.0#remarks</a></p>
  <blockquote>
  <p>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.</p>
  </blockquote>
  <p>The actual reason is:</p>
  <ul>
  <li>C# uses the Gregorian calendar all the time.</li>
  <li>Java uses the Gregorian calendar after October 15, 1582, and uses the Julian calendar before.</li>
  </ul>
  <p>The solution:</p>
  <pre class="lang-java prettyprint-override"><code>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();
      }
  }
  </code></pre>