From c14e1712ea7e42bdb7b2d246a9fcad3ca81aa048 Mon Sep 17 00:00:00 2001 From: Ivan Trusov Date: Fri, 13 May 2022 11:00:36 +0300 Subject: [PATCH 1/5] Fix basedate calculation Correct numdate / datenum calculation to eliminate problems with timezones that equal nowadays but were different in the past (e.g. Europe/Minsk and Europe/Moscow) --- xlsx.js | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/xlsx.js b/xlsx.js index 5cc5758c2..45b1a0efd 100644 --- a/xlsx.js +++ b/xlsx.js @@ -3214,16 +3214,19 @@ function evert_arr(obj) { return o; } -var basedate = new Date(1899, 11, 30, 0, 0, 0); // 2209161600000 +var basedate = new Date(); // 2209161600000 +basedate.setUTCFullYear(1899, 11, 30); +basedate.setUTCHours(0, 0, 0); + function datenum(v, date1904) { var epoch = v.getTime(); if(date1904) epoch -= 1462*24*60*60*1000; - var dnthresh = basedate.getTime() + (v.getTimezoneOffset() - basedate.getTimezoneOffset()) * 60000; + var dnthresh = basedate.getTime() + v.getTimezoneOffset() * 60000; return (epoch - dnthresh) / (24 * 60 * 60 * 1000); } var refdate = new Date(); -var dnthresh = basedate.getTime() + (refdate.getTimezoneOffset() - basedate.getTimezoneOffset()) * 60000; var refoffset = refdate.getTimezoneOffset(); +var dnthresh = basedate.getTime() + refoffset * 60000; function numdate(v) { var out = new Date(); out.setTime(v * 24 * 60 * 60 * 1000 + dnthresh); From 1dfabe74b1403d2dc48729103afb2b9dd2df28fd Mon Sep 17 00:00:00 2001 From: Ivan Trusov Date: Tue, 31 May 2022 17:26:54 +0300 Subject: [PATCH 2/5] Fix basedate calculation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Philippe Rivière --- xlsx.js | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/xlsx.js b/xlsx.js index 45b1a0efd..c83e754e6 100644 --- a/xlsx.js +++ b/xlsx.js @@ -3214,9 +3214,7 @@ function evert_arr(obj) { return o; } -var basedate = new Date(); // 2209161600000 -basedate.setUTCFullYear(1899, 11, 30); -basedate.setUTCHours(0, 0, 0); +var basedate = new Date(Date.UTC(1899, 11, 30, 0, 0, 0)); // 2209161600000 function datenum(v, date1904) { var epoch = v.getTime(); From 64e8998e59ff668e353ed764c06de3c106089734 Mon Sep 17 00:00:00 2001 From: Ivan Trusov Date: Fri, 13 May 2022 11:00:36 +0300 Subject: [PATCH 3/5] Fix basedate calculation Correct numdate / datenum calculation to eliminate problems with timezones that equal nowadays but were different in the past (e.g. Europe/Minsk and Europe/Moscow) --- xlsx.js | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/xlsx.js b/xlsx.js index 8eb774273..b1bedd338 100644 --- a/xlsx.js +++ b/xlsx.js @@ -3213,16 +3213,19 @@ function evert_arr(obj) { return o; } -var basedate = new Date(1899, 11, 30, 0, 0, 0); // 2209161600000 +var basedate = new Date(); // 2209161600000 +basedate.setUTCFullYear(1899, 11, 30); +basedate.setUTCHours(0, 0, 0); + function datenum(v, date1904) { var epoch = v.getTime(); if(date1904) epoch -= 1462*24*60*60*1000; - var dnthresh = basedate.getTime() + (v.getTimezoneOffset() - basedate.getTimezoneOffset()) * 60000; + var dnthresh = basedate.getTime() + v.getTimezoneOffset() * 60000; return (epoch - dnthresh) / (24 * 60 * 60 * 1000); } var refdate = new Date(); -var dnthresh = basedate.getTime() + (refdate.getTimezoneOffset() - basedate.getTimezoneOffset()) * 60000; var refoffset = refdate.getTimezoneOffset(); +var dnthresh = basedate.getTime() + refoffset * 60000; function numdate(v) { var out = new Date(); out.setTime(v * 24 * 60 * 60 * 1000 + dnthresh); From db81ca6594cb69aca97aa828809f459f01619600 Mon Sep 17 00:00:00 2001 From: Ivan Trusov Date: Tue, 31 May 2022 17:26:54 +0300 Subject: [PATCH 4/5] Fix basedate calculation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Philippe Rivière --- xlsx.js | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/xlsx.js b/xlsx.js index b1bedd338..1f2f7bdfc 100644 --- a/xlsx.js +++ b/xlsx.js @@ -3213,9 +3213,7 @@ function evert_arr(obj) { return o; } -var basedate = new Date(); // 2209161600000 -basedate.setUTCFullYear(1899, 11, 30); -basedate.setUTCHours(0, 0, 0); +var basedate = new Date(Date.UTC(1899, 11, 30, 0, 0, 0)); // 2209161600000 function datenum(v, date1904) { var epoch = v.getTime(); From b1c5037ca819227bc940ca905ab2d5b18d7e4fe1 Mon Sep 17 00:00:00 2001 From: Ivan Trusov Date: Thu, 2 Jun 2022 13:28:52 +0300 Subject: [PATCH 5/5] Refactor OADate handling --- xlsx.js | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/xlsx.js b/xlsx.js index 1f2f7bdfc..dc86c89f2 100644 --- a/xlsx.js +++ b/xlsx.js @@ -3213,23 +3213,21 @@ function evert_arr(obj) { return o; } -var basedate = new Date(Date.UTC(1899, 11, 30, 0, 0, 0)); // 2209161600000 +var base1900 = Date.UTC(1899, 11, 30); +var base1904 = Date.UTC(1904, 0, 1); +// According to https://docs.microsoft.com/ru-ru/archive/blogs/ericlippert/erics-complete-guide-to-vt_date +// we must treat OLE Automation Date as it has no timezone at all. +// So to avoid any possible TZ/DST issues do calculations in UTC function datenum(v, date1904) { - var epoch = v.getTime(); - if(date1904) epoch -= 1462*24*60*60*1000; - var dnthresh = basedate.getTime() + v.getTimezoneOffset() * 60000; - return (epoch - dnthresh) / (24 * 60 * 60 * 1000); + var start = date1904 ? base1904 : base1900; + var vTime = Date.UTC(v.getFullYear(), v.getMonth(), v.getDate(), v.getHours(), v.getMinutes(), v.getSeconds(), v.getMilliseconds()); + return (vTime - start) / 86400000; } -var refdate = new Date(); -var refoffset = refdate.getTimezoneOffset(); -var dnthresh = basedate.getTime() + refoffset * 60000; function numdate(v) { - var out = new Date(); - out.setTime(v * 24 * 60 * 60 * 1000 + dnthresh); - if (out.getTimezoneOffset() !== refoffset) { - out.setTime(out.getTime() + (out.getTimezoneOffset() - refoffset) * 60000); - } + var out = new Date(base1900 + v * 86400000); + // De-adjust timezone offset + out.setTime(out.getTime() + out.getTimezoneOffset() * 60000); return out; }