将Java和.NET之间的日期 - 2天日期、Java、NET

2023-09-04 01:06:26 作者:自导自演。

我需要改变一个.NET 的DateTime 为等效的Java 日历重presentation。

I need to transform a .NET DateTime to an equivalent Java Calendar representation.

在.NET 的DateTime 使用,因为 1月1日0001 的(在.NET划时代)作为底层重新presentation。

The .NET DateTime uses Ticks since Jan 1st 0001 (the .NET epoch) as the underlying representation.

Java的的GregorianCalendar 使用毫秒以来的 1970年1月1日的(在Java(或Unix)的时代)。该值为负数的日期了Java时代之前,符合市场预期。

The Java GregorianCalendar uses milliseconds since Jan 1st 1970 (the Java (or Unix) epoch). The value is negative for dates before the Java epoch, as expected.

在这里,我改变了的DateTime 重presentation在米利斯以来的的Java 的时代:

Here I'm transforming the DateTime representation in millis since the Java epoch:

var dt = new DateTime(1,2,3);  //way, way back.
var javaEpoch = new DateTime(1970, 1, 1);

var javaMillis = (dt - javaEpoch).Ticks / TimeSpan.TicksPerMillisecond;

dt.ToString("MM/dd/yyyy").Dump();          // .Dump() is provided by LinqPad. 
javaMillis.Dump();                         // Use Console.WriteLine(...)
                                           // for a regular console app.

此输出:

02 / 03 / 0001   -62132745600000

02/03/0001 -62132745600000

现在复制粘贴此Java毫秒值片段:

Now copy-paste the milliseconds value in this Java snippet:

java.util.Calendar cal = new java.util.GregorianCalendar();
cal.setTimeInMillis(-62132745600000L);
java.text.SimpleDateFormat df = new java.text.SimpleDateFormat();
df.applyPattern("MM/dd/yyyy");
System.out.println(df.format(cal.getTime()));

此输出:

02 / 05 / 0001

02/05/0001

我想我的问题是:我怎么从一个日期时间,从中我可以正确地构建一个Java日历获取有效的毫秒值

I guess my question is: How am I supposed to get a valid milliseconds value from a DateTime, from which I can correctly construct a Java Calendar?

......与隐含的子问题:这里究竟怎么回事?

...with the implied sub-question "what is really going on in here?"

编辑:我(按1582年10月15日1582年10月4日是跟随)使用了与周围缺少的日期范围DateTimeValues​​从朱利安公历

I played with DateTimeValues around the missing date range from Julian to Gregorian calendar (Oct 4 1582 is "followed" by Oct 15 1582).

有关日期,比1582年10月15日更近,转换似乎很好地工作。

For dates more recent than Oct 15 1582, the conversion seems to work fine.

...但是周围缺少的范围,日期时间开始(或者更确切地说,的不的开始)充当搞笑:

...But around the missing range, DateTime starts (or rather, doesn't start) to act funny:

var timespan = new DateTime(1582, 10, 15) - new DateTime(1582, 10, 4);

返回时间跨度为11天,所以孔不考虑由日期时间运算符。怎么办?我以为底层的实现是基于 System.Globalization.GregorianCalendar

returns a TimeSpan of 11 days, so the hole is not taken into consideration by the DateTime operators. What gives? I thought the underlying implementation is based on System.Globalization.GregorianCalendar.

推荐答案

在回答为什么:

从(反编译 - 感谢dotPeek!).NET 4源$ C ​​$ C(评论是我的):

From the (decompiled - thanks dotPeek!) .NET 4 source code (comments are mine):

public static DateTime operator -(DateTime d, TimeSpan t)
{
  //range checks
  long internalTicks = d.InternalTicks;
  long num = t._ticks;
  if (internalTicks < num || internalTicks - 3155378975999999999L > num)
    throw new ArgumentOutOfRangeException("t", 
            Environment.GetResourceString("ArgumentOutOfRange_DateArithmetic"));

    else

    //plain arithmetic using the Ticks property of the two dates.
    return new DateTime((ulong) (internalTicks - num) | d.InternalKind);
}

所以是的,绝对没有任何特殊的公历的治疗日期时间运营。

So yeah, absolutely no special 'gregorian' treatment for DateTime operators.

关于如何解决:

最后我用的东西沿着这些路线:(伪JAVA)

I ended up using something along these lines: (pseudo-Java)

Calendar cal = new GregorianCalendar();
cal.set(dt.Year, dt.Month - 1 /*it's 0-based*/, dt.Day, dt.Hour, dt.Minute, dt.Second);
cal.set(Calendar.MILLISECOND, dt.Millisecond);