4

私は正反対のことをしようとします:

javascriptのDateTime.ToOADate()に相当するものは何ですか?

OADate (double 値として 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); 
}

したがって、私が正しければ、1970 年 1 月 1 日の値が OADate 形式で必要です。私が間違っている場合は、別の変換方法を提案してもらえますか?

4

1 に答える 1

6

Javascriptの日付は、1970-01-01T00:00:00Zからのミリ秒の時間値を使用します。日付1899-12-30の時刻値は-2209197600000です。

それ以降の日数を取得するには、今日の開始時の真夜中のミリ秒を取得し、それをOAエポックから減算し、1日のミリ秒で除算して、絶対値を取得します。時間の値はすべて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

ここでいくつかの日付に対してテストできます(これらの日付は紛らわしい米国のm / d / yy形式であることに注意してください)。

編集

申し訳ありませんが、感覚が逆になりました。双方向に使用できるいくつかの関数を次に示します。

また、「OLEオートメーションの日付は、1899年12月30日の深夜0時前後の日数を小数部とする浮動小数点数として実装される」と書かれている場合、実際には1899年12月30日以降を意味することを理解するのに少し時間がかかりました。 00:00:00であり、「小数成分はその日の時刻を24で割ったものを表します」。つまり、1899-12-29 00:00:00は-1ですが、 `899-12-29 06:00:00の値は-0.75ではなく、-1.25です。

とにかく、これらの機能は現在機能しているようですが、徹底的にテストしてください。

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>

于 2013-03-21T14:28:52.517 に答える