forked from sheetjs/sheetjs
added test cases from #2560's thread; fixed more rounding edge cases
This commit is contained in:
parent
c580ffcbc2
commit
456c403c09
@ -55,7 +55,7 @@ function write_date(type/*:number*/, fmt/*:string*/, val, ss0/*:?number*/)/*:str
|
||||
switch(fmt) {
|
||||
case '[h]': case '[hh]': out = val.D*24+val.H; break;
|
||||
case '[m]': case '[mm]': out = (val.D*24+val.H)*60+val.M; break;
|
||||
case '[s]': case '[ss]': out = ((val.D*24+val.H)*60+val.M)*60+Math.round(val.S+val.u); break;
|
||||
case '[s]': case '[ss]': out = ((val.D*24+val.H)*60+val.M)*60+(ss0 < 1 ? Math.round(val.S+val.u) : val.S); break;
|
||||
default: throw 'bad abstime format: ' + fmt;
|
||||
} outl = fmt.length === 3 ? 1 : 2; break;
|
||||
case 101: /* 'e' era */
|
||||
|
@ -99,23 +99,14 @@ function eval_fmt(fmt/*:string*/, v/*:any*/, opts/*:any*/, flen/*:number*/) {
|
||||
}
|
||||
}
|
||||
/* time rounding depends on presence of minute / second / usec fields */
|
||||
switch(bt) {
|
||||
case 0: break;
|
||||
case 1:
|
||||
/*::if(!dt) break;*/
|
||||
if(dt.u >= 0.5) { dt.u = 0; ++dt.S; }
|
||||
if(dt.S >= 60) { dt.S = 0; ++dt.M; }
|
||||
if(dt.M >= 60) { dt.M = 0; ++dt.H; }
|
||||
break;
|
||||
case 2:
|
||||
/*::if(!dt) break;*/
|
||||
if(dt.u >= 0.5) { dt.u = 0; ++dt.S; }
|
||||
if(dt.S >= 60) { dt.S = 0; ++dt.M; }
|
||||
break;
|
||||
if (bt > 0 && bt < 3 && dt.u >= 0.5) {
|
||||
round_up_date(dt, opts);
|
||||
}
|
||||
|
||||
/* replace fields */
|
||||
var {nstr,out} = replace_fields(out, dt, ss0, v, opts);
|
||||
var replaced = replace_fields(out, dt, ss0, v, opts);
|
||||
var nstr = replaced.nstr;
|
||||
out = replaced.out;
|
||||
var vv = "", myv, ostr;
|
||||
if(nstr.length > 0) {
|
||||
if(nstr.charCodeAt(0) == 40) /* '(' */ {
|
||||
@ -183,7 +174,7 @@ function eval_fmt(fmt/*:string*/, v/*:any*/, opts/*:any*/, flen/*:number*/) {
|
||||
}
|
||||
function replace_fields(fields, dt, ss0, v, opts) {
|
||||
var out = [];
|
||||
for (var i = 0; i < fields.length; i++) {out[i] = {t: fields[i].t, v: fields[i].v}}
|
||||
for (var i = 0; i < fields.length; i++) {out[i] = {t: fields[i].t, v: fields[i].v};}
|
||||
var nstr = "", jj;
|
||||
for(i=0; i < out.length; ++i) {
|
||||
switch(out[i].t) {
|
||||
|
@ -335,7 +335,7 @@ function write_date(type/*:number*/, fmt/*:string*/, val, ss0/*:?number*/)/*:str
|
||||
switch(fmt) {
|
||||
case '[h]': case '[hh]': out = val.D*24+val.H; break;
|
||||
case '[m]': case '[mm]': out = (val.D*24+val.H)*60+val.M; break;
|
||||
case '[s]': case '[ss]': out = ((val.D*24+val.H)*60+val.M)*60+Math.round(val.S+val.u); break;
|
||||
case '[s]': case '[ss]': out = ((val.D*24+val.H)*60+val.M)*60+(ss0 < 1 ? Math.round(val.S+val.u) : val.S); break;
|
||||
default: throw 'bad abstime format: ' + fmt;
|
||||
} outl = fmt.length === 3 ? 1 : 2; break;
|
||||
case 101: /* 'e' era */
|
||||
@ -793,23 +793,14 @@ function eval_fmt(fmt/*:string*/, v/*:any*/, opts/*:any*/, flen/*:number*/) {
|
||||
}
|
||||
}
|
||||
/* time rounding depends on presence of minute / second / usec fields */
|
||||
switch(bt) {
|
||||
case 0: break;
|
||||
case 1:
|
||||
/*::if(!dt) break;*/
|
||||
if(dt.u >= 0.5) { dt.u = 0; ++dt.S; }
|
||||
if(dt.S >= 60) { dt.S = 0; ++dt.M; }
|
||||
if(dt.M >= 60) { dt.M = 0; ++dt.H; }
|
||||
break;
|
||||
case 2:
|
||||
/*::if(!dt) break;*/
|
||||
if(dt.u >= 0.5) { dt.u = 0; ++dt.S; }
|
||||
if(dt.S >= 60) { dt.S = 0; ++dt.M; }
|
||||
break;
|
||||
if (bt > 0 && bt < 3 && dt.u >= 0.5) {
|
||||
round_up_date(dt, opts);
|
||||
}
|
||||
|
||||
/* replace fields */
|
||||
var {nstr,out} = replace_fields(out, dt, ss0, v, opts);
|
||||
var replaced = replace_fields(out, dt, ss0, v, opts);
|
||||
var nstr = replaced.nstr;
|
||||
out = replaced.out;
|
||||
var vv = "", myv, ostr;
|
||||
if(nstr.length > 0) {
|
||||
if(nstr.charCodeAt(0) == 40) /* '(' */ {
|
||||
@ -877,7 +868,7 @@ function eval_fmt(fmt/*:string*/, v/*:any*/, opts/*:any*/, flen/*:number*/) {
|
||||
}
|
||||
function replace_fields(fields, dt, ss0, v, opts) {
|
||||
var out = [];
|
||||
for (var i = 0; i < fields.length; i++) {out[i] = {t: fields[i].t, v: fields[i].v}}
|
||||
for (var i = 0; i < fields.length; i++) {out[i] = {t: fields[i].t, v: fields[i].v};}
|
||||
var nstr = "", jj;
|
||||
for(i=0; i < out.length; ++i) {
|
||||
switch(out[i].t) {
|
||||
|
@ -330,7 +330,7 @@ if(ss0 >= 2) tt = ss0 === 3 ? 1000 : 100;
|
||||
switch(fmt) {
|
||||
case '[h]': case '[hh]': out = val.D*24+val.H; break;
|
||||
case '[m]': case '[mm]': out = (val.D*24+val.H)*60+val.M; break;
|
||||
case '[s]': case '[ss]': out = ((val.D*24+val.H)*60+val.M)*60+Math.round(val.S+val.u); break;
|
||||
case '[s]': case '[ss]': out = ((val.D*24+val.H)*60+val.M)*60+(ss0 < 1 ? Math.round(val.S+val.u) : val.S); break;
|
||||
default: throw 'bad abstime format: ' + fmt;
|
||||
} outl = fmt.length === 3 ? 1 : 2; break;
|
||||
case 101: /* 'e' era */
|
||||
@ -786,21 +786,14 @@ function eval_fmt(fmt, v, opts, flen) {
|
||||
}
|
||||
}
|
||||
/* time rounding depends on presence of minute / second / usec fields */
|
||||
switch(bt) {
|
||||
case 0: break;
|
||||
case 1:
|
||||
if(dt.u >= 0.5) { dt.u = 0; ++dt.S; }
|
||||
if(dt.S >= 60) { dt.S = 0; ++dt.M; }
|
||||
if(dt.M >= 60) { dt.M = 0; ++dt.H; }
|
||||
break;
|
||||
case 2:
|
||||
if(dt.u >= 0.5) { dt.u = 0; ++dt.S; }
|
||||
if(dt.S >= 60) { dt.S = 0; ++dt.M; }
|
||||
break;
|
||||
if (bt > 0 && bt < 3 && dt.u >= 0.5) {
|
||||
round_up_date(dt, opts);
|
||||
}
|
||||
|
||||
/* replace fields */
|
||||
var {nstr,out} = replace_fields(out, dt, ss0, v, opts);
|
||||
var replaced = replace_fields(out, dt, ss0, v, opts);
|
||||
var nstr = replaced.nstr;
|
||||
out = replaced.out;
|
||||
var vv = "", myv, ostr;
|
||||
if(nstr.length > 0) {
|
||||
if(nstr.charCodeAt(0) == 40) /* '(' */ {
|
||||
@ -868,7 +861,7 @@ if(dt.u >= 0.5) { dt.u = 0; ++dt.S; }
|
||||
}
|
||||
function replace_fields(fields, dt, ss0, v, opts) {
|
||||
var out = [];
|
||||
for (var i = 0; i < fields.length; i++) {out[i] = {t: fields[i].t, v: fields[i].v}}
|
||||
for (var i = 0; i < fields.length; i++) {out[i] = {t: fields[i].t, v: fields[i].v};}
|
||||
var nstr = "", jj;
|
||||
for(i=0; i < out.length; ++i) {
|
||||
switch(out[i].t) {
|
||||
|
@ -49,10 +49,34 @@ describe('time format rounding', function() {
|
||||
[{date1904: true}, {date1904: false}].forEach(opts => {
|
||||
testCases.forEach(testCase => {
|
||||
it(testCase.desc + ` (1904: ${opts.date1904})`,
|
||||
() => testRow([testCase.value, testCase.date1904[`${opts.date1904}`]], headers, opts))
|
||||
})
|
||||
})
|
||||
})
|
||||
() => testRow([testCase.value, testCase.date1904[`${opts.date1904}`]], headers, opts));
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('time format precision rounding', function() {
|
||||
var value = "4018.99999998843";
|
||||
var testCases = [
|
||||
{desc: "end-of-year thousandths rounding", format: "mm/dd/yyyy hh:mm:ss.000", expected: "12/31/1910 23:59:59.999"},
|
||||
{desc: "end-of-year hundredths round up", format: "mm/dd/yyyy hh:mm:ss.00", expected: "01/01/1911 00:00:00.00"},
|
||||
{desc: "end-of-year minutes round up", format: "mm/dd/yyyy hh:mm", expected: "01/01/1911 00:00"},
|
||||
{desc: "hour duration thousandths rounding", format: "[hh]:mm:ss.000", expected: "96455:59:59.999"},
|
||||
{desc: "hour duration hundredths round up", format: "[hh]:mm:ss.00", expected: "96456:00:00.00"},
|
||||
{desc: "hour duration minute round up (w/ ss)", format: "[hh]:mm:ss", expected: "96456:00:00"},
|
||||
{desc: "hour duration minute round up", format: "[hh]:mm", expected: "96456:00"},
|
||||
{desc: "hour duration round up", format: "[hh]", expected: "96456"},
|
||||
{desc: "minute duration thousandths rounding", format: "[mm]:ss.000", expected: "5787359:59.999"},
|
||||
{desc: "minute duration hundredths round up", format: "[mm]:ss.00", expected: "5787360:00.00"},
|
||||
{desc: "minute duration round up", format: "[mm]:ss", expected: "5787360:00"},
|
||||
{desc: "second duration thousandths rounding", format: "[ss].000", expected: "347241599.999"},
|
||||
{desc: "second duration hundredths round up", format: "[ss].00", expected: "347241600.00"},
|
||||
{desc: "second duration round up", format: "[ss]", expected: "347241600"},
|
||||
];
|
||||
testCases.forEach(testCase => {
|
||||
var headers = ["value", testCase.format];
|
||||
it(testCase.desc, () => {testRow([value, testCase.expected], headers, {})});
|
||||
});
|
||||
});
|
||||
|
||||
describe('date formats', function() {
|
||||
doit(process.env.MINTEST ? dates.slice(0,4000) : dates);
|
||||
|
Loading…
Reference in New Issue
Block a user