Comparing version 0.5.11 to 0.6.0
{ | ||
"name": "ssf", | ||
"version": "0.5.11", | ||
"version": "0.6.0", | ||
"author": "SheetJS", | ||
@@ -5,0 +5,0 @@ "description": "pure-JS library to format data using ECMA-376 spreadsheet Format Codes", |
48
ssf.js
@@ -8,3 +8,3 @@ /* ssf.js (C) 2013-2014 SheetJS -- http://sheetjs.com */ | ||
function rpad(v,d,c){var t=String(v);return t.length>=d?t:(t+fill(c||0,d-t.length));} | ||
SSF.version = '0.5.11'; | ||
SSF.version = '0.6.0'; | ||
/* Options */ | ||
@@ -124,2 +124,6 @@ var opts_fmt = {}; | ||
if(date > 2958465) return null; | ||
if(out.u > .999) { | ||
out.u = 0; | ||
if(++time == 86400) { time = 0; ++date; } | ||
} | ||
if(date === 60) {dout = [1900,2,29]; dow=3;} | ||
@@ -147,3 +151,3 @@ else if(date === 0) {dout = [1900,1,0]; dow=6;} | ||
if(val < 0) return ""; | ||
var o; | ||
var o, ss; | ||
switch(type) { | ||
@@ -183,7 +187,7 @@ case 'y': switch(fmt) { /* year */ | ||
case 's': switch(fmt) { /* seconds */ | ||
case 's': return Math.round(val.S+val.u); | ||
case 'ss': return pad(Math.round(val.S+val.u), 2); | ||
case 'ss.0': o = pad(Math.round(10*(val.S+val.u)),3); return o.substr(0,2)+"." + o.substr(2); | ||
case 'ss.00': o = pad(Math.round(100*(val.S+val.u)),4); return o.substr(0,2)+"." + o.substr(2); | ||
case 'ss.000': o = pad(Math.round(1000*(val.S+val.u)),5); return o.substr(0,2)+"." + o.substr(2); | ||
case 's': ss=Math.round(val.S+val.u); return ss >= 60 ? 0 : ss; | ||
case 'ss': ss=Math.round(val.S+val.u); if(ss>=60) ss=0; return pad(ss,2); | ||
case 'ss.0': ss=Math.round(10*(val.S+val.u)); if(ss>=600) ss = 0; o = pad(ss,3); return o.substr(0,2)+"." + o.substr(2); | ||
case 'ss.00': ss=Math.round(100*(val.S+val.u)); if(ss>=6000) ss = 0; o = pad(ss,4); return o.substr(0,2)+"." + o.substr(2); | ||
case 'ss.000': ss=Math.round(1000*(val.S+val.u)); if(ss>=60000) ss = 0; o = pad(ss,5); return o.substr(0,2)+"." + o.substr(2); | ||
default: throw 'bad second format: ' + fmt; | ||
@@ -365,12 +369,28 @@ } | ||
} | ||
/* walk backwards */ | ||
var bt = 0; | ||
for(i=out.length-1, lst='t'; i >= 0; --i) { | ||
switch(out[i].t) { | ||
case 'h': case 'H': out[i].t = hr; lst='h'; break; | ||
case 'd': case 'y': case 's': case 'M': case 'e': lst=out[i].t; break; | ||
case 'm': if(lst === 's') out[i].t = 'M'; break; | ||
case 'h': case 'H': out[i].t = hr; lst='h'; if(bt < 1) bt = 1; break; | ||
case 's': if(bt < 3) bt = 3; | ||
/* falls through */ | ||
case 'd': case 'y': case 'M': case 'e': lst=out[i].t; break; | ||
case 'm': if(lst === 's') { out[i].t = 'M'; if(bt < 2) bt = 2; } break; | ||
case 'Z': | ||
if(bt < 1 && out[i].v.match(/[Hh]/)) bt = 1; | ||
if(bt < 2 && out[i].v.match(/[Mm]/)) bt = 2; | ||
if(bt < 3 && out[i].v.match(/[Ss]/)) bt = 3; | ||
} | ||
} | ||
switch(bt) { | ||
case 0: break; | ||
case 1: | ||
if(dt.u >= .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 >= .5) { dt.u = 0; ++dt.S; } | ||
if(dt.S >= 60) { dt.S = 0; ++dt.M; } | ||
break; | ||
} | ||
/* replace fields */ | ||
@@ -381,3 +401,3 @@ for(i=0; i < out.length; ++i) { | ||
case 'd': case 'm': case 'y': case 'h': case 'H': case 'M': case 's': case 'e': case 'Z': | ||
out[i].v = write_date(out[i].t, out[i].v, dt); | ||
out[i].v = write_date(out[i].t, out[i].v, dt, bt); | ||
out[i].t = 't'; break; | ||
@@ -384,0 +404,0 @@ case 'n': case '(': case '?': |
69
ssf.md
@@ -296,2 +296,11 @@ # SSF | ||
Due to floating point issues, correct for subseconds: | ||
``` | ||
if(out.u > .999) { | ||
out.u = 0; | ||
if(++time == 86400) { time = 0; ++date; } | ||
} | ||
``` | ||
Due to a bug in Lotus 1-2-3 which was propagated by Excel and other variants, | ||
@@ -673,11 +682,45 @@ the year 1900 is recognized as a leap year. JS has no way of representing that | ||
/* walk backwards */ | ||
``` | ||
In order to identify cases like `MMSS`, where the fact that this is a minute | ||
appears after the minute itself, scan backwards. At the same time, we can | ||
identify the smallest time unit (0 = no time, 1 = hour, 2 = minute, 3 = second): | ||
``` | ||
var bt = 0; | ||
for(i=out.length-1, lst='t'; i >= 0; --i) { | ||
switch(out[i].t) { | ||
case 'h': case 'H': out[i].t = hr; lst='h'; break; | ||
case 'd': case 'y': case 's': case 'M': case 'e': lst=out[i].t; break; | ||
case 'm': if(lst === 's') out[i].t = 'M'; break; | ||
case 'h': case 'H': out[i].t = hr; lst='h'; if(bt < 1) bt = 1; break; | ||
case 's': if(bt < 3) bt = 3; | ||
/* falls through */ | ||
case 'd': case 'y': case 'M': case 'e': lst=out[i].t; break; | ||
case 'm': if(lst === 's') { out[i].t = 'M'; if(bt < 2) bt = 2; } break; | ||
case 'Z': | ||
if(bt < 1 && out[i].v.match(/[Hh]/)) bt = 1; | ||
if(bt < 2 && out[i].v.match(/[Mm]/)) bt = 2; | ||
if(bt < 3 && out[i].v.match(/[Ss]/)) bt = 3; | ||
} | ||
} | ||
``` | ||
Having determined the smallest time unit, round appropriately: | ||
``` | ||
switch(bt) { | ||
case 0: break; | ||
case 1: | ||
if(dt.u >= .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 >= .5) { dt.u = 0; ++dt.S; } | ||
if(dt.S >= 60) { dt.S = 0; ++dt.M; } | ||
break; | ||
} | ||
``` | ||
Finally, actually write the numbers: | ||
``` | ||
/* replace fields */ | ||
@@ -688,3 +731,3 @@ for(i=0; i < out.length; ++i) { | ||
case 'd': case 'm': case 'y': case 'h': case 'H': case 'M': case 's': case 'e': case 'Z': | ||
out[i].v = write_date(out[i].t, out[i].v, dt); | ||
out[i].v = write_date(out[i].t, out[i].v, dt, bt); | ||
out[i].t = 't'; break; | ||
@@ -731,3 +774,3 @@ case 'n': case '(': case '?': | ||
if(val < 0) return ""; | ||
var o; | ||
var o, ss; | ||
switch(type) { | ||
@@ -782,7 +825,7 @@ case 'y': switch(fmt) { /* year */ | ||
case 's': switch(fmt) { /* seconds */ | ||
case 's': return Math.round(val.S+val.u); | ||
case 'ss': return pad(Math.round(val.S+val.u), 2); | ||
case 'ss.0': o = pad(Math.round(10*(val.S+val.u)),3); return o.substr(0,2)+"." + o.substr(2); | ||
case 'ss.00': o = pad(Math.round(100*(val.S+val.u)),4); return o.substr(0,2)+"." + o.substr(2); | ||
case 'ss.000': o = pad(Math.round(1000*(val.S+val.u)),5); return o.substr(0,2)+"." + o.substr(2); | ||
case 's': ss=Math.round(val.S+val.u); return ss >= 60 ? 0 : ss; | ||
case 'ss': ss=Math.round(val.S+val.u); if(ss>=60) ss=0; return pad(ss,2); | ||
case 'ss.0': ss=Math.round(10*(val.S+val.u)); if(ss>=600) ss = 0; o = pad(ss,3); return o.substr(0,2)+"." + o.substr(2); | ||
case 'ss.00': ss=Math.round(100*(val.S+val.u)); if(ss>=6000) ss = 0; o = pad(ss,4); return o.substr(0,2)+"." + o.substr(2); | ||
case 'ss.000': ss=Math.round(1000*(val.S+val.u)); if(ss>=60000) ss = 0; o = pad(ss,5); return o.substr(0,2)+"." + o.substr(2); | ||
default: throw 'bad second format: ' + fmt; | ||
@@ -1022,3 +1065,3 @@ } | ||
"name": "ssf", | ||
"version": "0.5.11", | ||
"version": "0.6.0", | ||
"author": "SheetJS", | ||
@@ -1159,3 +1202,3 @@ "description": "pure-JS library to format data using ECMA-376 spreadsheet Format Codes", | ||
} | ||
describe('time formats', function() { doit(times.slice(0,1000)); }); | ||
describe('time formats', function() { doit(process.env.MINTEST ? times.slice(0,4000) : times); }); | ||
describe('date formats', function() { | ||
@@ -1162,0 +1205,0 @@ doit(process.env.MINTEST ? dates.slice(0,1000) : dates); |
@@ -24,3 +24,3 @@ /* vim: set ts=2: */ | ||
} | ||
describe('time formats', function() { doit(times.slice(0,1000)); }); | ||
describe('time formats', function() { doit(process.env.MINTEST ? times.slice(0,4000) : times); }); | ||
describe('date formats', function() { | ||
@@ -27,0 +27,0 @@ doit(process.env.MINTEST ? dates.slice(0,1000) : dates); |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
108623
1974
9