【问题标题】:Convert date between java and .net - 2 days off在 java 和 .net 之间转换日期 - 休息 2 天
【发布时间】:2013-04-11 13:22:41
【问题描述】:

我需要将 .NET DateTime 转换为等效的 Java Calendar 表示。

.NET DateTime 使用 Ticks0001 年 1 月 1 日(.NET 纪元)作为底层表示。

Java GregorianCalendar 使用自1970 年 1 月 1 日(Java(或 Unix)纪元)以来的毫秒数。正如预期的那样,对于 Java 纪元之前的日期,该值为负数。

Java 时代以来,我在这里以毫秒为单位转换 DateTime 表示:

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

现在复制粘贴此 Java sn-p 中的毫秒值:

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

我想我的问题是:我应该如何从 DateTime 中获取一个有效的毫秒值,以便我可以正确地构造一个 Java 日历?

...带有隐含的子问题“这里到底发生了什么?”

编辑:我在从儒略历到公历的缺失日期范围内使用 DateTimeValues(1582 年 10 月 4 日“紧随”1582 年 10 月 15 日)。

对于 1582 年 10 月 15 日之后的日期,转换似乎工作正常。

...但是在缺少的范围内,DateTime 开始(或者更确切地说,开始)表现得滑稽:

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

返回 11 天的 TimeSpan,因此 DateTime 运算符不考虑该漏洞。是什么赋予了?我以为底层实现是基于System.Globalization.GregorianCalendar

【问题讨论】:

  • 如果你使用Joda Time会怎样?你能? Joda time 改进了标准 Java 日期,并可能以干净的方式解决您的问题。它还提供到 java.util.Date 和 java.util.Calendar 的转换,因此如果您确实需要使用标准 Java 日期,您可以使用 Joda 时间转换来解决您的问题。
  • 这有点像用大炮杀死苍蝇。我 可以 做的是更改 Java 位以调用 calendar.Set(year, month, day, ...) 而不是 calendar.SetTimeInMillis() 并从 .NET DateTime 获取这些字段中的每一个对象的属性。但我也想了解发生了什么。
  • 顺便说一句,问题似乎出在 .NET 方面 - 伟大的 JS 已将他的库移植到 .NET:code.google.com/p/noda-time(几天前发布了 v 1.1!)跨度>
  • This is a bit like killing flies with a cannon:是和不是。使用 joda 代替 java.util 正在成为一种标准。从这个意义上说,使用 joda 无论如何都会很好。但我完全同意你句子的第二部分:I also want to understand what's going on
  • 我的印象是,Java 8 有关日期处理的标准化过程正朝着包括 JSR 310 - threeten.sourceforge.net,而不是 JodaTime 的方向发展。

标签: java .net datetime calendar gregorian-calendar


【解决方案1】:

令人惊讶的是,没有人真正回答过为什么在 1582 年 10 月 4 日和 1582 年 10 月 15 日之间的公历中存在一个“洞”的问题。有趣的答案是在公历被采用的历史中1582年改革儒略历。有关详细信息,请参阅Wikipedia's article on Gregorian Calendar。历史中的最后一段:格里高利改革段落指出

  • 格雷戈里(教皇格雷戈里十三世)减少了 10 天,以使日历恢复与季节同步。因此,当新历法投入使用时,自尼西亚会议以来13个世纪以来积累的错误被删去十天来纠正。 1582 年 10 月 4 日星期四是儒略历日,随后是 1582 年 10 月 15 日星期五公历的第一天(工作日周期不受影响)。*

实际上,公历中不存在从 1582 年 10 月 5 日到 1582 年 10 月 14 日的日期。我怀疑 .Net Framework 使用通用公式,在处理 1582 年 10 月 15 日之前的日期时没有考虑到差异,而 Java 库确实考虑了这一点。

【讨论】:

  • +1 感谢您花时间添加解释。我知道这个洞,并暗示它是常识。但是,我的问题不是“为什么有这个洞?”,而是“为什么不是 .NET DateTime 中的那个洞?” - 猜猜这就是为什么直到现在才涵盖历史方面的原因。
  • 哦,顺便说一句,这东西令人着迷
【解决方案2】:

来自Java documentation

[...] 使用GregorianCalendar 获得的日期仅在历史上是准确的 从公元 4 年 3 月 1 日起,现代儒略历规则 采纳

考虑到您的DateTime 减法,这只是Ticks 的差异,这里绝对没有特定日历的概念。实现基本是return new TimeSpan(x.Ticks - y.Ticks)

您可能更擅长简单地输出然后解析 ISO-8061 日期/时间,例如 0001-02-03T00:00:00Z,它没有歧义,而不是依赖于内部表示。

【讨论】:

    【解决方案3】:

    回答“为什么”:

    来自(反编译 - 感谢 dotPeek!).NET 4 源代码(cmets 是我的):

    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);
    }
    

    是的,对于 DateTime 运算符,绝对没有特殊的“公历”处理。

    关于“如何修复”:

    我最终使用了一些类似的东西:(伪 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);
    

    【讨论】:

      猜你喜欢
      • 2019-11-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多