【问题标题】:OADate to Milliseconds timestamp in JavascriptJavascript中的OADate到毫秒时间戳
【发布时间】:2013-03-11 02:21:45
【问题描述】:

我尝试做完全相反的事情:

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

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

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

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 的值。 如果我错了,请您建议另一种转换方法吗?

【问题讨论】:

  • 只需使用该问题中给出的公式计算即可。如果你传入new Date(0),你就会退出oaDate 25569
  • 它应该是从 1899 年 12 月 30 日到 1970 年 1 月 1 日的确切天数。 ://
  • @Mark 它与我正在寻找的完全相反的操作
  • 哦,是的,谢谢你这么简单,为什么我没想到 XD ^^ 所以你同意我的功能吗?

标签: javascript datetime timestamp


【解决方案1】:

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

要获取从那时起的天数,获取今天开始时午夜的毫秒数,从 OA 纪元中减去它,然后除以一天中的毫秒,然后得到绝对值。请注意,时间值都是 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).toFixed(10);
  return days + partDay.substr(1);
}

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

window.onload = function(){ 
  var el = document.getElementById('in')
  el.addEventListener('change', function() {
    var oaDate = dateToOADate(new Date(new Date(el.value)));
    document.getElementById('out').value = oaDate;
    document.getElementById('out2').value = dateFromOADate(oaDate);
  });
}
input {width: 25em}
<table>
  <tr>
    <td>Input date:<br>(DD MMM YYYY HH:mm)
    <td><input id="in" value="29 Dec 1899 06:00">
  <tr>
    <td>OA Date:
    <td><input id="out" readonly>
  <tr>
    <td>Back to standard date:
    <td><input id="out2" readonly>
</table>

【讨论】:

  • +1,虽然你需要使用Date.UTC 来构造epoch - 否则只有住在格林威治标准时间的人才会开心
  • 我考虑过,但是所有日期都是本地创建的,所以会考虑本地偏移量,所以它应该取消。不过严格来说,它们可能都应该使用 UTC 值,但我在 Microsoft documentation 中看不到对 UTC 的任何引用。
  • 使用 UTC 的主要原因是通过使用公共基准来允许时区,但是 OA 日期没有任何时区允许,因此尝试考虑时区似乎不明智它。将 2013-03T23:59:59 转换为 OA 日期将返回 41355.99998842592,反转它会返回相同的日期和时间(都在当前时区)。在内部转换为 UTC 并返回将给出完全相同的结果。如果跨时区使用 OA 日期值,则它实际上与跨时区传递日期和时间字符串相同,而没有时区偏移信息。
  • "它实际上与跨时区传递日期和时间字符串相同,没有时区偏移信息" - 好的,只是我不知道这是否可取:- ) 我对 .NET 不熟悉,尽管看起来您可以设置 DateTimeKind 以让它们代表本地日期或 UTC 日期。至少你应该记录你的函数,说明它们编码/解码本地时间值
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-06-25
  • 1970-01-01
  • 1970-01-01
  • 2016-06-05
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多