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>