在JavaScript中,DateTime.ToOADate()的等效方法是什么?

4

我该如何在JavaScript中获取OADate(OLE自动化日期)? 我需要以双精度值的形式传递我的日期对象(给我的Web服务)。

在C#中:

var d = DateTime.Now.ToOADate();

在JavaScript中相当于什么?

7个回答

9
要将 JScript 日期转换为 OLE Automation 日期,调用 getVarDate 方法: http://msdn.microsoft.com/zh-cn/library/4d4x3w61(VS.85).aspx (如果你需要反过来做——也就是说,你有一个 JScript 对象,并且你分配了一个包含 VT_DATE 类型变量的属性——JScript 引擎应该会自动将其转换为相应的 JScript 日期。)
如果你的浏览器提供商没有编写 getVarDate 方法,那么你可以自己编写代码,但是为了处理所有情况都正确,你必须处理一些关于纪元前日期的棘手特殊情况。
我知道的最好方法是首先将其转换为自纪元以来整数和小数天数的原始数字,这里我指的是1899年12月30日午夜,而不是12月31日。一旦你完成了这个步骤,你就可以对纪元前的值进行特殊处理。
非常注意舍入!我建议在转换为 OA 格式之前将值四舍五入到最近的秒。因为 OA 格式是这样一种格式,-1.9999999 是在 1899 年 12 月 30 日午夜之前,而 -2.0 是在 1899 年 12 月 28 日午夜,如果你将前者舍入到后者,你就将一个小数秒舍入成了两天的误差。
有关 OA 格式的细节问题,请参阅我在 2003 年撰写的文章: http://blogs.msdn.com/b/ericlippert/archive/2003/09/16/53013.aspx 如果你想深入了解这种奇怪的日期格式的历史背景,请参阅 Joel 在 Microsoft 工作期间的文章: http://www.joelonsoftware.com/items/2006/06/16.html

5
如果您不能更改Web服务,则必须重新实现ToOADate()
MSDN说,

OLE自动化日期是实现为浮点数的数字,其整数部分是午夜前或午夜后的天数,即1899年12月30日,其小数部分表示当天的时间除以24。例如, 1899年12月31日午夜表示为1.0; 1900年1月1日上午6点表示为2.25; 1899年12月29日午夜表示为-1.0; 1899年12月29日上午6点表示为-1.25。

因此,您应该能够编写类似以下内容的代码:
var oaDate = (date - new Date(1899, 11, 31)) / (24 * 60 * 60 * 1000);

(未经测试)


@valipour 我认为它会因夏令时和类似的事情而偏差几个小时。在意大利这里,它偏差了1个小时。 - xanatos
1
找到了。var oaDate = (date - new Date(Date.UTC(1899, 11, 30))) / (24 * 60 * 60 * 1000) - xanatos
1
当然,这对于纪元前的日期根本不起作用!我曾经把这个问题作为面试热身问题;这种实现方式不会得到任何工作机会。 :-) - Eric Lippert
8
哇,Eric。所以某人可以在面试中脱口而出这种话,因为你遇到了这个问题并想出了如何纠正它的方法,但他们没有预料到在你的面试中你会开除他们...你很讨厌。 - The Lazy Coder
1
@SLaks 我想那是一个很好的观点。我希望有一点来回沟通。但我认为那个回答最多只能算是自负。我猜,当你编造东西时,人们没有理解就生气也是可以的吧。但是嘿,就连微软也第一次没做对。难道因为他们有一个 bug 就应该放弃整个 Excel 团队吗?评论提供了关于 bug 的有用信息。但它也显示了他的性格。令人印象深刻。 - The Lazy Coder
显示剩余4条评论

4
< p > markitondemand@Github 采用以下方式解决问题,其中考虑了夏令时(DST)。< /p> < p >https://github.com/markitondemand/moment-msdate/blob/master/moment-msdate.js< /p>
toOADate: function (date) {
    var timezoneOffset = date.getTimezoneOffset() / (60 * 24);
    var msDateObj = (date.getTime() / 86400000) + (25569 - timezoneOffset);
    return msDateObj;
 },
fromOADate: function (oadate) {
   var date = new Date(((oadate - 25569) * 86400000));
   var tz = date.getTimezoneOffset();
   return new Date(((oadate - 25569 + (tz / (60 * 24))) * 86400000));
},

1
一种适用于夏令时日期的解决方案:

var toOADate = (function () {
    /** @const */ var utc18991230 = Date.UTC(1899, 11, 31);
    /** @const */ var msPerDay = 24 * 60 * 60 * 1000;

    return function (date) {
        if (date instanceof Date) {
            date = Date.UTC(date.getUTCFullYear(), date.getUTCMonth(), date.getUTCDate());
        }
        return (date - utc18991230) / msPerDay;
    };

})();

0

修复时区偏移:

function toOADate(date) {
    var msPerDay = 24 * 60 * 60 * 1000;
    var baseDate = new Date("1899-12-30T00:00:00.000+0000");
    return (date.getTime() - baseDate.getTime() - 60*1000*getTimezoneOffset()) / msPerDay;
}

0

这些对于JS来说看起来不错,但如果你想在PHP中将其转换为Unix时间戳,请使用以下代码:

// $ms_date_floating_point is the MS date
// 42372.3432210648 converts to Sun Jan 3rd, 2016
$ms_date_seconds = $ms_date_floating_point * 60 * 60 * 24;
$unix_timestamp_seconds = strtotime("Nov 11, 1899 00:00:00") + $ms_date_seconds;

-1

你应该更改你的 Web 服务以接受 UNIX 时间戳。

然后,你可以在 JavaScript 中调用 new Date().getTime(),或者在 C# 中调用 (someDate - new DateTime(1970, 1, 1)).TotalMilliseconds


1
如果这是另一个人的 Web 服务,而我无法更改它怎么办? - Mo Valipour

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接