。NET DateTime,与OADate相互转换时的分辨率不同?

问题描述 投票:7回答:3

我正在将DateTime转换为OADate。我期望将OADa​​te转换回时获得完全相同的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

提示来自:634202170964319073

来自b的提示:634202170964310000

The OADate double:40437.290467951389

这是什么原因? DateTime的分辨率显然足够好。

c# .net datetime resolution ole-automation
3个回答
3
投票

ToOADate调用的静态方法将滴答声清楚地除以10000,然后将结果存储在很长的时间中,从而删除了任何不到毫秒的信息

有人知道在哪里可以找到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);
    }

11
投票

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

除非您使用的日期与1900年非常接近,否则DateTime的精度将比OA日期的精度更高。但是出于某些晦涩的原因,DateTime的作者将love的结构截断为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)); // <-- HERE, remove this comment } public static double ToOADatePrecise(this DateTime dt) { if (dt < oaEpoch) throw new ArgumentOutOfRangeException(); return Convert.ToDouble((dt - oaEpoch).Ticks) / TimeSpan.TicksPerDay; }

现在,让我们考虑(从您的问题出发):DateTime

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

任何DateTime的精度为0.1 µs。

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

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

我们得出的结论是[[在该区域

DateTime比OA日期精确六倍。

让我们使用上面的扩展方法将ourDT转换为doubledouble ourOADate = ourDT.ToOADatePrecise(); // .ToString("G") gives 40437.2904679619 // .ToString("R") gives 40437.290467961888

现在,如果使用上述静态ourOADate方法将DateTime转换回FromOADatePrecise,则会得到

[2010-09-16T06:58:16.4319072(以"O"格式编写]

与原始图像相比,我们看到在这种情况下精度损失为0.1 µs。我们希望精度损失在±0.4 µs之内,因为此间隔的长度为0.8 µs,与前面提到的0.6286 µs相仿。

如果采用另一种方法,则以double开头,它表示OA日期不太接近1900年,而

first

使用FromOADatePrecise,而

then

ToOADatePrecise,那么我们回到double,并且由于中间DateTime的精度优于OA日期,因此在这种情况下,我们希望实现完美的往返。另一方面,如果您以相同的顺序使用BCL方法FromOADateToOADate,则很难实现良好的往返(除非我们以double开头的格式非常特殊) 。
可能与double的精度有关,而不与DateTime有关。

1
投票
© www.soinside.com 2019 - 2024. All rights reserved.