代码之家  ›  专栏  ›  技术社区  ›  Ezombort

.NET日期时间,转换为OADate和从OADate转换时的分辨率不同?

  •  7
  • Ezombort  · 技术社区  · 14 年前

    我在把约会时间转换成约会时间。我本来希望在转换回OADate时得到完全相同的DateTime,但现在它只有毫秒分辨率,因此有所不同。

    var a = DateTime.UtcNow;
    double oadate = a.ToOADate();
    var b = DateTime.FromOADate(oadate);
    int compare = DateTime.Compare(a, b); 
    
    //Compare is not 0; the date times are not the same
    

    来自a:634202170964319073的滴答声

    来自b的滴答声:63420217096431000

    OADate双倍:40437.290467951389

    3 回复  |  直到 14 年前
        1
  •  3
  •   vc 74    14 年前

    ToOADate调用的静态方法明确地将滴答数除以10000,然后将结果存储在long中,从而删除任何亚毫秒的信息

    有人知道在哪里可以找到OADate格式的规范吗?

        private static double TicksToOADate(long value)
        {
            if (value == 0L)
            {
                return 0.0;
            }
            if (value < 0xc92a69c000L)
            {
                value += 0x85103c0cb83c000L;
            }
            if (value < 0x6efdddaec64000L)
            {
                throw new OverflowException(Environment.GetResourceString("Arg_OleAutDateInvalid"));
            }
            long num = (value - 0x85103c0cb83c000L) / 0x2710L;
            if (num < 0L)
            {
                long num2 = num % 0x5265c00L;
                if (num2 != 0L)
                {
                    num -= (0x5265c00L + num2) * 2L;
                }
            }
            return (((double)num) / 86400000.0);
        }
    
        2
  •  13
  •   Achilles1515    4 年前

    我认为这是一个很好的问题。(我刚发现。)

    除非你操作的日期非常接近1900年 DateTime 会有一个 较高的 日期时间 日期时间

    这里有一个解决方法:

    static readonly DateTime oaEpoch = new DateTime(1899, 12, 30);
    
    public static DateTime FromOADatePrecise(double d)
    {
      if (!(d >= 0))
        throw new ArgumentOutOfRangeException(); // NaN or negative d not supported
    
      return oaEpoch + TimeSpan.FromTicks(Convert.ToInt64(d * TimeSpan.TicksPerDay));
    }
    
    public static double ToOADatePrecise(this DateTime dt)
    {
      if (dt < oaEpoch)
        throw new ArgumentOutOfRangeException();
    
      return Convert.ToDouble((dt - oaEpoch).Ticks) / TimeSpan.TicksPerDay;
    }
    

    现在,让我们(从你的问题)来考虑 日期时间

    var ourDT = new DateTime(634202170964319073);
    // .ToSting("O") gives 2010-09-16T06:58:16.4319073
    

    任何 日期时间

    在我们考虑的日期和时间附近,OA日期的精度为:

    Math.Pow(2.0, -37.0) 天,或大约 0.6286

    我们的结论是 在这个地区 日期时间

    让我们皈依吧 ourDT double

    double ourOADate = ourDT.ToOADatePrecise();
    // .ToString("G") gives 40437.2904679619
    // .ToString("R") gives 40437.290467961888
    

    现在,如果你皈依 ourOADate 回到a 日期时间 使用静态 FromOADatePrecise 上面的方法,你得到

    2010-09-16T06:58:16.4319072 "O" 格式)

    与原始值相比,我们发现在这种情况下精度损失为0.1 s。我们预计精度损失在±0.4 s之内,因为该间隔的长度为0.8 s,与前面提到的0.6286 s相当。

    如果我们走另一条路,从 双重的 第一 使用 FromOADatePrecise公司 ,和 ToOADatePrecise 双重的 ,而且因为 FromOADate ToOADate 在同样的顺序下,获得一个好的往返是极不可能的(除非 双重的

        3
  •  1
  •   Carvellis    14 年前