Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

The exported date is 43 seconds longer #2350

Closed
yangrongzhou opened this issue Aug 11, 2021 · 2 comments
Closed

The exported date is 43 seconds longer #2350

yangrongzhou opened this issue Aug 11, 2021 · 2 comments

Comments

@yangrongzhou
Copy link

yangrongzhou commented Aug 11, 2021

Test code:

var sheetData = {
    '!ref': 'A1:A2',
    'A1': { v: '2021-08-12 00:00:00', t: 'd', z: 'yyyy-mm-dd hh:mm:ss' },
    'A2': { v: '2021-08-12 00:27:02', t: 'd', z: 'yyyy-mm-dd hh:mm:ss' },
};

var sheetName = 'Sheet1';
var filename = "test.xlsx";

var workbook = {
    SheetNames: [sheetName],
    Sheets: {}
};

workbook.Sheets[sheetName] = sheetData;

XLSX.writeFile(workbook, filename, { compression: true });

But the Excel view result is:

2021-08-12 00:00:43
2021-08-12 00:27:45

My PC timezone is UTC+8.
Maybe this code can help you find the bug:

var basedate = new Date(1899, 11, 30, 0, 0, 0);
console.log(basedate.getTimezoneOffset()); // -485
console.log(basedate.toISOString()); // "1899-12-29T15:54:17.000Z"

For the date 1899-12-30 00:00:00, method getTimezoneOffset returns 43 seconds less.

@woshiguabi
Copy link

woshiguabi commented Aug 12, 2021

This article(language:Chinese) explained the issue. https://zhuanlan.zhihu.com/p/89914219

The time difference between a time zone and a zero time zone is different in various historical periods.
image

@SheetJSDev
Sheetjs use getTimezoneOffset to fix this issue, but getTimezoneOffset only returns minutes, not include seconds.

var basedate = new Date(1899, 11, 30, 0, 0, 0); // 2209161600000
function datenum(v/*:Date*/, date1904/*:?boolean*/)/*:number*/ {
var epoch = v.getTime();
if(date1904) epoch -= 1462*24*60*60*1000;
var dnthresh = basedate.getTime() + (v.getTimezoneOffset() - basedate.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();
function numdate(v/*:number*/)/*:Date*/ {
var out = new Date();
out.setTime(v * 24 * 60 * 60 * 1000 + dnthresh);
if (out.getTimezoneOffset() !== refoffset) {
out.setTime(out.getTime() + (out.getTimezoneOffset() - refoffset) * 60000);
}
return out;
}

image

So every Date before 1901-01-01 00:00:00 in timezone Shanghai will be 43 seconds ahead.

Maybe we can use Date.UTC to fix this issue.
image

Related

#1470 (comment)


Update

I use an extra offset to fix this bug.
Notice: Only xlsx ext needs to fix.

const baseDate = new Date(1899, 11, 30, 0, 0, 0);
const baseDateUtc = new Date(Date.UTC(1899, 11, 30, 0, 0, 0));
const timezoneOffsetFix =
  baseDateUtc.valueOf() +
  baseDate.getTimezoneOffset() * 60000 -
  baseDate.valueOf();

const date = moment('2021-08-12 00:00:00').toDate();
const needFix = new Date(date.valueOf() - timezoneOffsetFix).getTimezoneOffset() !== baseDate.getTimezoneOffset();
const fixedDate = needFix ? new Date(date.valueOf() - timezoneOffsetFix) : date;
console.log(moment(fixedDate).format('YYYY-MM-DD HH:mm:ss')); // 2021-08-11 23:59:17

@SheetJSDev
Copy link
Contributor

The date bug is well known, #1918 (comment) was a comment from last year. Closing as dupe of #1565

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants