在Javascript中OADate到毫秒时间戳

时间:2013-03-21 14:07:45

标签: javascript datetime timestamp

我尝试做的恰恰相反:

What is equivalent of DateTime.ToOADate() in javascript?

从OADate创建一个毫秒日期(自1970年1月1日以来的毫秒数)(1899年12月30日以来的天数为双倍值)

我的猜测是我可以这样做:

this.unixTimeStampFromOADate = function( OADateFloat)
{
        var oaDateFor1970 = ?? ; //what's the value for 1/1/1970 in OADate format ?
        var delta = Math.floor(OADateFloat - oaDateFor1970);

        return delta*(1000*60*60*24); 
}

所以如果我是对的,我需要OADate格式的1/1/1970的值。 如果我错了,你能否提出另一种转换方法?

1 个答案:

答案 0 :(得分:5)

Javascript日期使用的时间值是自1970-01-01T00:00:00Z以来的毫秒数。 1899-12-30日期的时间值为-2209197600000。

要获得此后的日子,请在今天开始时获取午夜的毫秒数,从OA时期中减去它,在一天内除以ms并获得绝对值。请注意,时间值均为UTC,因此可以考虑夏令时,闰年等。

var epoch = new Date(1899, 11, 30); // 1899-12-30T00:00:00
var now = new Date();               // 2013-03-22T<current time>
now.setHours(0,0,0,0)               // 2013-03-22T00:00:00

var oaDate  = Math.abs((epoch - now) / 8.64e7); // 41355 for 2013-03-22

您可以针对某些日期here对其进行测试(请注意,这些日期采用令人困惑的美国m / d / yy格式)。

修改

抱歉,倒退了。以下是一些双向功能。

还花了一些时间来解决它所说的“OLE自动化日期是作为浮点数实现的,其积分分量是1899年12月30日午夜之前或之后的天数”实际上意味着在1899年或之后 - 12-30 00:00:00并且“小数部分代表当天的时间除以24”。换句话说,虽然1899-12-29 00:00:00是-1,但是'899-12-29 06:00:00的值是-1.25,而不是-0.75。

无论如何,这些功能现在似乎都有效,但请彻底测试:

var toOADate = (function () {
  var epoch = new Date(1899,11,30);
  var msPerDay = 8.64e7;

  return function(d) {
    var v = -1 * (epoch - d)/msPerDay;

    // Deal with dates prior to 1899-12-30 00:00:00
    var dec = v - Math.floor(v);

    if (v < 0 && dec) {
      v = Math.floor(v) - dec;
    }

    return v;
  }
}());


var fromOADate = (function() {
  var epoch = new Date(1899,11,30);
  var msPerDay = 8.64e7;

  return function(n) {
    // Deal with -ve values
    var dec = n - Math.floor(n);

    if (n < 0 && dec) {
      n = Math.floor(n) - dec;
    }

    return new Date(n*msPerDay + +epoch);
  }
}());

var now = new Date();
var oaNow = toOADate(now);
var now2 = fromOADate(oaNow);

alert('Today: ' + now + '\nOADate: ' + oaNow + '\noaNow to Date: ' + now2);

OADate的规范令人困惑,尤其是负数的处理方式。

编辑2019年2月

更新了函数版本,使用本地日期值。

/* Convert a Microsoft OADate to ECMAScript Date
** Treat all values as local.
** @param {string|number} oaDate - OADate value
** @returns {Date}
*/
function dateFromOADate (oaDate) {
  // Treat integer part is whole days
  var days = parseInt(oaDate);
  // Treat decimal part as part of 24hr day, always +ve
  var ms = Math.abs((oaDate - days) * 8.64e7);
  // Add days and add ms
  return new Date(1899, 11, 30 + days, 0, 0, 0, ms);
}


/* Convert an ECMAScript Date to a Microsoft OADate
** Treat all dates as local.
** @param {Date} date - Date to convert
** @returns {Date}
*/
function dateToOADate (date) {
  var temp = new Date(date);
  // Set temp to start of day and get whole days between dates,
  var days = Math.round((temp.setHours(0,0,0,0) - new Date(1899, 11, 30)) / 8.64e7);
  // Get decimal part of day, OADate always assumes 24 hours in day
  var partDay = Math.abs((date - temp) % 8.64e7) / 8.64e7;
  return (days + partDay).toFixed(10);
}

var now = new Date();
var x = dateToOADate(now);
console.log('Now: ' + now.toString());
console.log('As an OADate: ' + x);
console.log('Back to date: ' + dateFromOADate(x).toString());