From c299585bfb627edd4fb0345dd1814c66fee35c26 Mon Sep 17 00:00:00 2001 From: SheetJS Date: Sun, 12 Jan 2014 03:31:44 -0500 Subject: [PATCH] version bump 0.5.1: more fixes needed for xls - Updated frac to 0.3.1 (issue with numbers exceeding 2**32) - Invalid dates render empty string - Sub-second string format - First steps towards Engineering format - Fraction formats don't render blanks in the case of zero - Trailing spaces removed - More implied tests --- package.json | 5 +- ssf.js | 43 ++- ssf.md | 69 ++-- test/implied.js | 7 +- test/implied.json | 803 ++++++++++++++++++++++++++++++++++++++++++---- 5 files changed, 826 insertions(+), 101 deletions(-) diff --git a/package.json b/package.json index 498b94b..24732fe 100644 --- a/package.json +++ b/package.json @@ -1,13 +1,14 @@ { "name": "ssf", - "version": "0.5.0", + "version": "0.5.1", "author": "SheetJS", "description": "pure-JS library to format data using ECMA-376 spreadsheet Format Codes", "keywords": [ "format", "sprintf", "spreadsheet" ], "main": "ssf.js", "dependencies": { "voc":"", - "colors":"" + "colors":"", + "frac":"0.3.1" }, "devDependencies": { "mocha":"" diff --git a/ssf.js b/ssf.js index 43299de..afa2252 100644 --- a/ssf.js +++ b/ssf.js @@ -70,9 +70,9 @@ var frac = function frac(x, D, mixed) { var B = x * sgn; var P_2 = 0, P_1 = 1, P = 0; var Q_2 = 1, Q_1 = 0, Q = 0; - var A = B|0; + var A = Math.floor(B); while(Q_1 < D) { - A = B|0; + A = Math.floor(B); P = A * P_1 + P_2; Q = A * Q_1 + Q_2; if((B - A) < 0.0000000005) break; @@ -83,6 +83,7 @@ var frac = function frac(x, D, mixed) { if(Q > D) { Q = Q_1; P = P_1; } if(Q > D) { Q = Q_2; P = P_2; } if(!mixed) return [0, sgn * P, Q]; + if(Q==0) throw "Unexpected state: "+P+" "+P_1+" "+P_2+" "+Q+" "+Q_1+" "+Q_2; var q = Math.floor(sgn * P/Q); return [q, sgn*P - q*Q, Q]; }; @@ -96,13 +97,13 @@ var general_fmt = function(v) { else if(V >= 0.0001 && V < 0.001) o = v.toPrecision(6); else if(V >= Math.pow(10,10) && V < Math.pow(10,11)) o = v.toFixed(10).substr(0,12); else if(V > Math.pow(10,-9) && V < Math.pow(10,11)) { - o = v.toFixed(12).replace(/(\.[0-9]*[1-9])0*$/,"$1").replace(/\.$/,""); + o = v.toFixed(12).replace(/(\.[0-9]*[1-9])0*$/,"$1").replace(/\.$/,""); if(o.length > 11+(v<0?1:0)) o = v.toPrecision(10); if(o.length > 11+(v<0?1:0)) o = v.toExponential(5); - } + } else { o = v.toFixed(11).replace(/(\.[0-9]*[1-9])0*$/,"$1"); - if(o.length > 11 + (v<0?1:0)) o = v.toPrecision(6); + if(o.length > 11 + (v<0?1:0)) o = v.toPrecision(6); } o = o.replace(/(\.[0-9]*[1-9])0+e/,"$1e").replace(/\.0*e/,"e"); return o.replace("e","E").replace(/\.0*$/,"").replace(/\.([0-9]*[^0])0*$/,".$1").replace(/(E[+-])([0-9])$/,"$1"+"0"+"$2"); @@ -112,9 +113,10 @@ var general_fmt = function(v) { }; SSF._general = general_fmt; var parse_date_code = function parse_date_code(v,opts) { - var date = Math.floor(v), time = Math.round(86400 * (v - date)), dow=0; + var date = Math.floor(v), time = Math.floor(86400 * (v - date)), dow=0; var dout=[], out={D:date, T:time, u:86400*(v-date)-time}; fixopts(opts = (opts||{})); if(opts.date1904) date += 1462; + if(date > 2958465) return null; if(date === 60) {dout = [1900,2,29]; dow=3;} else if(date === 0) {dout = [1900,1,0]; dow=6;} else { @@ -173,8 +175,8 @@ var write_date = function(type, fmt, val) { } break; case 's': switch(fmt) { /* seconds */ case 's': return val.S; - case 'ss': return pad(val.S, 2); - case 'ss.0': return pad(val.S,2) + "." + Math.round(10*val.u); + case 'ss': return pad(Math.round(val.S+val.u), 2); + case 'ss.0': var o = pad(Math.round(10*(val.S+val.u)),3); return o.substr(0,2)+"." + o.substr(2); default: throw 'bad second format: ' + fmt; } break; case 'Z': switch(fmt) { @@ -201,8 +203,14 @@ var write_num = function(type, fmt, val) { if(fmt.indexOf("E") > -1) { var idx = fmt.indexOf("E") - fmt.indexOf(".") - 1; if(fmt == '##0.0E+0') { - var ee = Number(val.toExponential(0).substr(3))%3; - o = (val/Math.pow(10,ee%3)).toPrecision(idx+1+(ee%3)).replace(/^([+-]?)([0-9]*)\.([0-9]*)[Ee]/,function($$,$1,$2,$3) { return $1 + $2 + $3.substr(0,ee) + "." + $3.substr(ee) + "E"; }); + var ee = (Number(val.toExponential(0).substr(2+(val<0))))%3; + o = (val/Math.pow(10,ee)).toPrecision(idx+1+(3+ee)%3); + if(!o.match(/[Ee]/)) { + var fakee = (Number(val.toExponential(0).substr(2+(val<0)))); + if(o.indexOf(".") === -1) o = o[0] + "." + o.substr(1) + "E+" + (fakee - o.length+ee); + else throw "missing E"; + } + o = o.replace(/^([+-]?)([0-9]*)\.([0-9]*)[Ee]/,function($$,$1,$2,$3) { return $1 + $2 + $3.substr(0,(3+ee)%3) + "." + $3.substr(ee) + "E"; }); } else o = val.toExponential(idx); if(fmt.match(/E\+00$/) && o.match(/e[+-][0-9]$/)) o = o.substr(0,o.length-1) + "0" + o[o.length-1]; if(fmt.match(/E\-/) && o.match(/e\+/)) o = o.replace(/e\+/,"e"); @@ -226,9 +234,9 @@ var write_num = function(type, fmt, val) { case "#,##0": return sign + commaify(String(Math.round(aval))); case "#,##0.0": r = Math.round((val-Math.floor(val))*10); return val < 0 ? "-" + write_num(type, fmt, -val) : commaify(String(Math.floor(val))) + "." + r; case "#,##0.00": r = Math.round((val-Math.floor(val))*100); return val < 0 ? "-" + write_num(type, fmt, -val) : commaify(String(Math.floor(val))) + "." + (r < 10 ? "0"+r:r); - case "# ? / ?": ff = frac(aval, 9, true); return sign + (ff[0]||"") + " " + (ff[1] === 0 ? " " : ff[1] + "/" + ff[2]); - case "# ?? / ??": ff = frac(aval, 99, true); return sign + (ff[0]||"") + " " + (ff[1] ? pad(ff[1],2," ") + "/" + rpad(ff[2],2," ") : " "); - case "# ??? / ???": ff = frac(aval, 999, true); return sign + (ff[0]||"") + " " + (ff[1] ? pad(ff[1],3," ") + "/" + rpad(ff[2],3," ") : " "); + case "# ? / ?": ff = frac(aval, 9, true); return sign + (ff[0]||(ff[1] ? "" : "0")) + " " + (ff[1] === 0 ? " " : ff[1] + "/" + ff[2]); + case "# ?? / ??": ff = frac(aval, 99, true); return sign + (ff[0]||(ff[1] ? "" : "0")) + " " + (ff[1] ? pad(ff[1],2," ") + "/" + rpad(ff[2],2," ") : " "); + case "# ??? / ???": ff = frac(aval, 999, true); return sign + (ff[0]||(ff[1] ? "" : "0")) + " " + (ff[1] ? pad(ff[1],3," ") + "/" + rpad(ff[2],3," ") : " "); default: } throw new Error("unsupported format |" + fmt + "|"); @@ -268,6 +276,7 @@ function eval_fmt(fmt, v, opts, flen) { case 'm': case 'd': case 'y': case 'h': case 's': case 'e': if(v < 0) return ""; if(!dt) dt = parse_date_code(v, opts); + if(!dt) return ""; o = fmt[i]; while(fmt[++i] === c) o+=c; if(c === 's' && fmt[i] === '.' && fmt[i+1] === '0') { o+='.'; while(fmt[++i] === '0') o+= '0'; } if(c === 'm' && lst.toLowerCase() === 'h') c = 'M'; /* m = minute */ @@ -275,6 +284,7 @@ function eval_fmt(fmt, v, opts, flen) { q={t:c, v:o}; out.push(q); lst = c; break; case 'A': if(!dt) dt = parse_date_code(v, opts); + if(!dt) return ""; q={t:c,v:"A"}; if(fmt.substr(i, 3) === "A/P") {q.v = dt.H >= 12 ? "P" : "A"; q.t = 'T'; hr='h';i+=3;} else if(fmt.substr(i,5) === "AM/PM") { q.v = dt.H >= 12 ? "PM" : "AM"; q.t = 'T'; i+=5; hr='h'; } @@ -323,17 +333,16 @@ function eval_fmt(fmt, v, opts, flen) { out[i].t = 't'; break; case 'n': case '(': var jj = i+1; - while(out[jj] && ("? D".indexOf(out[jj].t) > -1 || out[i].t == '(' && (out[jj].t == ')' || out[jj].t == 'n') || out[jj].t == 't' && (out[jj].v == '/' || out[jj].v == '$' || (out[jj].v == ' ' && (out[jj+1]||{}).t == '?')))) { + while(out[jj] && ("?D".indexOf(out[jj].t) > -1 || (out[jj].t == " " && (out[jj+1]||{}).t === "?" ) || out[i].t == '(' && (out[jj].t == ')' || out[jj].t == 'n') || out[jj].t == 't' && (out[jj].v == '/' || out[jj].v == '$' || (out[jj].v == ' ' && (out[jj+1]||{}).t == '?')))) { if(out[jj].v!==' ') out[i].v += ' ' + out[jj].v; delete out[jj]; ++jj; } out[i].v = write_num(out[i].t, out[i].v, v); out[i].t = 't'; - i = jj; break; + i = jj-1; break; default: throw "unrecognized type " + out[i].t; } } - return out.map(function(x){return x.v;}).join(""); } SSF._eval = eval_fmt; @@ -364,7 +373,7 @@ SSF._table = table_fmt; SSF.load = function(fmt, idx) { table_fmt[idx] = fmt; }; SSF.format = format; SSF.get_table = function() { return table_fmt; }; -SSF.load_table = function(tbl) { for(var i=0; i!=0x0188; ++i) if(table_fmt[i]) SSF.load(i, table_fmt[i]); }; +SSF.load_table = function(tbl) { for(var i=0; i!=0x0188; ++i) if(tbl[i]) SSF.load(tbl[i], i); }; }; make_ssf(SSF); if(typeof module !== 'undefined' && typeof DO_NOT_EXPORT_SSF === 'undefined') module.exports = SSF; diff --git a/ssf.md b/ssf.md index a52738d..54b4502 100644 --- a/ssf.md +++ b/ssf.md @@ -146,13 +146,13 @@ For numbers, try to display up to 11 digits of the number (the original code else if(V >= 0.0001 && V < 0.001) o = v.toPrecision(6); else if(V >= Math.pow(10,10) && V < Math.pow(10,11)) o = v.toFixed(10).substr(0,12); else if(V > Math.pow(10,-9) && V < Math.pow(10,11)) { - o = v.toFixed(12).replace(/(\.[0-9]*[1-9])0*$/,"$1").replace(/\.$/,""); + o = v.toFixed(12).replace(/(\.[0-9]*[1-9])0*$/,"$1").replace(/\.$/,""); if(o.length > 11+(v<0?1:0)) o = v.toPrecision(10); if(o.length > 11+(v<0?1:0)) o = v.toExponential(5); - } + } else { o = v.toFixed(11).replace(/(\.[0-9]*[1-9])0*$/,"$1"); - if(o.length > 11 + (v<0?1:0)) o = v.toPrecision(6); + if(o.length > 11 + (v<0?1:0)) o = v.toPrecision(6); } o = o.replace(/(\.[0-9]*[1-9])0+e/,"$1e").replace(/\.0*e/,"e"); return o.replace("e","E").replace(/\.0*$/,"").replace(/\.([0-9]*[^0])0*$/,".$1").replace(/(E[+-])([0-9])$/,"$1"+"0"+"$2"); @@ -262,7 +262,7 @@ portion of a 24 hour day). ```js>tmp/50_date.js var parse_date_code = function parse_date_code(v,opts) { - var date = Math.floor(v), time = Math.round(86400 * (v - date)), dow=0; + var date = Math.floor(v), time = Math.floor(86400 * (v - date)), dow=0; var dout=[], out={D:date, T:time, u:86400*(v-date)-time}; fixopts(opts = (opts||{})); ``` @@ -273,6 +273,12 @@ shifted by 1462 days. if(opts.date1904) date += 1462; ``` +Date codes beyond 12/31/9999 are invalid: + +``` + if(date > 2958465) return null; +``` + Due to a bug in Lotus 1-2-3 which was propagated by Excel and other variants, the year 1900 is recognized as a leap year. JS has no way of representing that abomination as a `Date`, so the easiest way is to store the data as a tuple. @@ -359,8 +365,19 @@ For the special case of engineering notation, "shift" the decimal: ``` if(fmt == '##0.0E+0') { - var ee = Number(val.toExponential(0).substr(3))%3; - o = (val/Math.pow(10,ee%3)).toPrecision(idx+1+(ee%3)).replace(/^([+-]?)([0-9]*)\.([0-9]*)[Ee]/,function($$,$1,$2,$3) { return $1 + $2 + $3.substr(0,ee) + "." + $3.substr(ee) + "E"; }); + var ee = (Number(val.toExponential(0).substr(2+(val<0))))%3; + o = (val/Math.pow(10,ee)).toPrecision(idx+1+(3+ee)%3); + if(!o.match(/[Ee]/)) { +``` + +TODO: something reasonable + +``` + var fakee = (Number(val.toExponential(0).substr(2+(val<0)))); + if(o.indexOf(".") === -1) o = o[0] + "." + o.substr(1) + "E+" + (fakee - o.length+ee); + else throw "missing E"; + } + o = o.replace(/^([+-]?)([0-9]*)\.([0-9]*)[Ee]/,function($$,$1,$2,$3) { return $1 + $2 + $3.substr(0,(3+ee)%3) + "." + $3.substr(ee) + "E"; }); } else o = val.toExponential(idx); if(fmt.match(/E\+00$/) && o.match(/e[+-][0-9]$/)) o = o.substr(0,o.length-1) + "0" + o[o.length-1]; if(fmt.match(/E\-/) && o.match(/e\+/)) o = o.replace(/e\+/,"e"); @@ -404,9 +421,9 @@ The default cases are hard-coded. TODO: actually parse them The frac helper function is used for fraction formats (defined below). ```js>tmp/60_number.js - case "# ? / ?": ff = frac(aval, 9, true); return sign + (ff[0]||"") + " " + (ff[1] === 0 ? " " : ff[1] + "/" + ff[2]); - case "# ?? / ??": ff = frac(aval, 99, true); return sign + (ff[0]||"") + " " + (ff[1] ? pad(ff[1],2," ") + "/" + rpad(ff[2],2," ") : " "); - case "# ??? / ???": ff = frac(aval, 999, true); return sign + (ff[0]||"") + " " + (ff[1] ? pad(ff[1],3," ") + "/" + rpad(ff[2],3," ") : " "); + case "# ? / ?": ff = frac(aval, 9, true); return sign + (ff[0]||(ff[1] ? "" : "0")) + " " + (ff[1] === 0 ? " " : ff[1] + "/" + ff[2]); + case "# ?? / ??": ff = frac(aval, 99, true); return sign + (ff[0]||(ff[1] ? "" : "0")) + " " + (ff[1] ? pad(ff[1],2," ") + "/" + rpad(ff[2],2," ") : " "); + case "# ??? / ???": ff = frac(aval, 999, true); return sign + (ff[0]||(ff[1] ? "" : "0")) + " " + (ff[1] ? pad(ff[1],3," ") + "/" + rpad(ff[2],3," ") : " "); default: } throw new Error("unsupported format |" + fmt + "|"); @@ -474,6 +491,7 @@ Merge strings like "mmmmm" or "hh" into one block: ``` if(!dt) dt = parse_date_code(v, opts); + if(!dt) return ""; o = fmt[i]; while(fmt[++i] === c) o+=c; ``` @@ -502,6 +520,7 @@ the HH/hh jazz. TODO: investigate this further. ``` case 'A': if(!dt) dt = parse_date_code(v, opts); + if(!dt) return ""; q={t:c,v:"A"}; if(fmt.substr(i, 3) === "A/P") {q.v = dt.H >= 12 ? "P" : "A"; q.t = 'T'; hr='h';i+=3;} else if(fmt.substr(i,5) === "AM/PM") { q.v = dt.H >= 12 ? "PM" : "AM"; q.t = 'T'; i+=5; hr='h'; } @@ -539,7 +558,7 @@ number 123.456 under format `|??| / |???| |???| foo` is `|15432| / |125| | | q={t:c, v:o}; out.push(q); lst = c; break; ``` -Due to how the CSV generation works, asterisk characters are discarded. TODO: +Due to how the CSV generation works, asterisk characters are discarded. TODO: communicate this somehow, possibly with an option ``` @@ -591,17 +610,16 @@ The default magic characters are listed in subsubsections 18.8.30-31 of ECMA376: out[i].t = 't'; break; case 'n': case '(': var jj = i+1; - while(out[jj] && ("? D".indexOf(out[jj].t) > -1 || out[i].t == '(' && (out[jj].t == ')' || out[jj].t == 'n') || out[jj].t == 't' && (out[jj].v == '/' || out[jj].v == '$' || (out[jj].v == ' ' && (out[jj+1]||{}).t == '?')))) { + while(out[jj] && ("?D".indexOf(out[jj].t) > -1 || (out[jj].t == " " && (out[jj+1]||{}).t === "?" ) || out[i].t == '(' && (out[jj].t == ')' || out[jj].t == 'n') || out[jj].t == 't' && (out[jj].v == '/' || out[jj].v == '$' || (out[jj].v == ' ' && (out[jj+1]||{}).t == '?')))) { if(out[jj].v!==' ') out[i].v += ' ' + out[jj].v; delete out[jj]; ++jj; } out[i].v = write_num(out[i].t, out[i].v, v); out[i].t = 't'; - i = jj; break; + i = jj-1; break; default: throw "unrecognized type " + out[i].t; } } - return out.map(function(x){return x.v;}).join(""); } SSF._eval = eval_fmt; @@ -655,8 +673,8 @@ var write_date = function(type, fmt, val) { } break; case 's': switch(fmt) { /* seconds */ case 's': return val.S; - case 'ss': return pad(val.S, 2); - case 'ss.0': return pad(val.S,2) + "." + Math.round(10*val.u); + case 'ss': return pad(Math.round(val.S+val.u), 2); + case 'ss.0': var o = pad(Math.round(10*(val.S+val.u)),3); return o.substr(0,2)+"." + o.substr(2); default: throw 'bad second format: ' + fmt; } break; ``` @@ -731,11 +749,11 @@ SSF.load = function(fmt, idx) { table_fmt[idx] = fmt; }; SSF.format = format; ``` -To support multiple SSF tables: +To support multiple SSF tables: ``` SSF.get_table = function() { return table_fmt; }; -SSF.load_table = function(tbl) { for(var i=0; i!=0x0188; ++i) if(table_fmt[i]) SSF.load(i, table_fmt[i]); }; +SSF.load_table = function(tbl) { for(var i=0; i!=0x0188; ++i) if(tbl[i]) SSF.load(tbl[i], i); }; ``` ## Fraction Library @@ -748,9 +766,9 @@ var frac = function frac(x, D, mixed) { var B = x * sgn; var P_2 = 0, P_1 = 1, P = 0; var Q_2 = 1, Q_1 = 0, Q = 0; - var A = B|0; + var A = Math.floor(B); while(Q_1 < D) { - A = B|0; + A = Math.floor(B); P = A * P_1 + P_2; Q = A * Q_1 + Q_2; if((B - A) < 0.0000000005) break; @@ -761,6 +779,7 @@ var frac = function frac(x, D, mixed) { if(Q > D) { Q = Q_1; P = P_1; } if(Q > D) { Q = Q_2; P = P_2; } if(!mixed) return [0, sgn * P, Q]; + if(Q==0) throw "Unexpected state: "+P+" "+P_1+" "+P_2+" "+Q+" "+Q_1+" "+Q_2; var q = Math.floor(sgn * P/Q); return [q, sgn*P - q*Q, Q]; }; @@ -818,14 +837,15 @@ test: ```json>package.json { "name": "ssf", - "version": "0.5.0", + "version": "0.5.1", "author": "SheetJS", "description": "pure-JS library to format data using ECMA-376 spreadsheet Format Codes", "keywords": [ "format", "sprintf", "spreadsheet" ], "main": "ssf.js", "dependencies": { "voc":"", - "colors":"" + "colors":"", + "frac":"0.3.1" }, "devDependencies": { "mocha":"" @@ -859,14 +879,17 @@ before_install: The mocha test driver tests the implied formats: ```js>test/implied.js -/* vim: set ts=2: */ var SSF = require('../'); var fs = require('fs'), assert = require('assert'); var data = JSON.parse(fs.readFileSync('./test/implied.json','utf8')); var skip = []; +function doit(d) { + d[1].forEach(function(r){if(!r[2])assert.equal(SSF.format(r[0],d[0]),r[1]);}); +} describe('implied formats', function() { data.forEach(function(d) { - it(d[1]+" for "+d[0], skip.indexOf(d[1]) > -1 ? null : function(){ + if(d.length == 2) it(d[0], function() { doit(d); }); + else it(d[1]+" for "+d[0], skip.indexOf(d[1]) > -1 ? null : function(){ assert.equal(SSF.format(d[1], d[0], {}), d[2]); }); }); diff --git a/test/implied.js b/test/implied.js index 5f9cb85..b3b668d 100644 --- a/test/implied.js +++ b/test/implied.js @@ -1,11 +1,14 @@ -/* vim: set ts=2: */ var SSF = require('../'); var fs = require('fs'), assert = require('assert'); var data = JSON.parse(fs.readFileSync('./test/implied.json','utf8')); var skip = []; +function doit(d) { + d[1].forEach(function(r){if(!r[2])assert.equal(SSF.format(r[0],d[0]),r[1]);}); +} describe('implied formats', function() { data.forEach(function(d) { - it(d[1]+" for "+d[0], skip.indexOf(d[1]) > -1 ? null : function(){ + if(d.length == 2) it(d[0], function() { doit(d); }); + else it(d[1]+" for "+d[0], skip.indexOf(d[1]) > -1 ? null : function(){ assert.equal(SSF.format(d[1], d[0], {}), d[2]); }); }); diff --git a/test/implied.json b/test/implied.json index d4d63f8..ce5b3c6 100644 --- a/test/implied.json +++ b/test/implied.json @@ -1,67 +1,756 @@ [ - [12345.6789, 0, "12345.6789"], - [12345.6789, 1, "12346"], - [12345.6789, 2, "12345.68"], - [12345.6789, 3, "12,346"], - [12345.6789, 4, "12,345.68"], - [12345.6789, 9, "1234568%"], - [12345.6789, 10, "1234567.89%"], - [12345.6789, 11, "1.23E+04"], - [12345.6789, 12, "12345 2/3"], - [12345.6789, 13, "12345 55/81"], - [12345.6789, 14, "10/18/33"], - [12345.6789, 15, "18-Oct-33"], - [12345.6789, 16, "18-Oct"], - [12345.6789, 17, "Oct-33"], - [12345.6789, 18, "4:17 PM"], - [12345.6789, 19, "4:17:37 PM"], - [12345.6789, 20, "16:17"], - [12345.6789, 21, "16:17:37"], - [12345.6789, 22, "10/18/33 16:17"], - [12345.6789, 37, "12,346"], - [12345.6789, 38, "12,346"], - [12345.6789, 39, "12,345.68"], - [12345.6789, 40, "12,345.68"], - [12345.6789, 45, "17:37"], - [12345.6789, 46, "296296:17:37"], - [12345.6789, 47, "1737.0"], - [12345.6789, 48, "12.3E+3"], - [12345.6789, 49, "12345.6789"], + [1234567890000, [ + [0, "1.23457E+12", true], + [1, "1234567890000"], + [2, "1234567890000.00"], + [3, "1,234,567,890,000"], + [4, "1,234,567,890,000.00"], + [9, "123456789000000%"], + [10, "123456789000000.00%"], + [11, "1.23E+12"], + [12, "1234567890000 "], + [13, "1234567890000 "], + [14, ""], + [15, ""], + [16, ""], + [17, ""], + [18, ""], + [19, ""], + [20, ""], + [21, ""], + [22, ""], + [37, "1,234,567,890,000 "], + [38, "1,234,567,890,000 "], + [39, "1,234,567,890,000.00"], + [40, "1,234,567,890,000.00"], + [45, ""], + [46, ""], + [47, ""], + [48, "1.2E+12"], + [49, "1.23457E+12", true] + ]], - [-12345.6789, 0, "-12345.6789"], - [-12345.6789, 1, "-12346"], - [-12345.6789, 2, "-12345.68"], - [-12345.6789, 3, "-12,346"], - [-12345.6789, 4, "-12,345.68"], - [-12345.6789, 9, "-1234568%"], - [-12345.6789, 10, "-1234567.89%"], - [-12345.6789, 11, "-1.23E+04"], - [-12345.6789, 12, "-12345 2/3"], - [-12345.6789, 13, "-12345 55/81"], - [-12345.6789, 14, ""], - [-12345.6789, 15, ""], - [-12345.6789, 16, ""], - [-12345.6789, 17, ""], - [-12345.6789, 18, ""], - [-12345.6789, 19, ""], - [-12345.6789, 20, ""], - [-12345.6789, 21, ""], - [-12345.6789, 22, ""], - [-12345.6789, 37, "(12,346)"], - [-12345.6789, 38, "(12,346)"], - [-12345.6789, 39, "(12,345.68)"], - [-12345.6789, 40, "(12,345.68)"], - [-12345.6789, 45, ""], - [-12345.6789, 46, ""], - [-12345.6789, 47, ""], - [-12345.6789, 48, "-12.3E+3"], - [-12345.6789, 49, "-12345.6789"], + [123456789000, [ + [0, "1.23457E+11"], + [1, "123456789000"], + [2, "123456789000.00"], + [3, "123,456,789,000"], + [4, "123,456,789,000.00"], + [9, "12345678900000%"], + [10, "12345678900000.00%"], + [11, "1.23E+11"], + [12, "123456789000 "], + [13, "123456789000 "], + [14, ""], + [15, ""], + [16, ""], + [17, ""], + [18, ""], + [19, ""], + [20, ""], + [21, ""], + [22, ""], + [37, "123,456,789,000 "], + [38, "123,456,789,000 "], + [39, "123,456,789,000.00"], + [40, "123,456,789,000.00"], + [45, ""], + [46, ""], + [47, ""], + [48, "123.5E+9", true], + [49, "1.23457E+11", true] + ]], + + [12345678900, [ + [0, "12345678900"], + [1, "12345678900"], + [2, "12345678900.00"], + [3, "12,345,678,900"], + [4, "12,345,678,900.00"], + [9, "1234567890000%"], + [10, "1234567890000.00%"], + [11, "1.23E+10"], + [12, "12345678900 "], + [13, "12345678900 "], + [14, ""], + [15, ""], + [16, ""], + [17, ""], + [18, ""], + [19, ""], + [20, ""], + [21, ""], + [22, ""], + [37, "12,345,678,900 "], + [38, "12,345,678,900 "], + [39, "12,345,678,900.00"], + [40, "12,345,678,900.00"], + [45, ""], + [46, ""], + [47, ""], + [48, "12.3E+9"], + [49, "12345678900"] + ]], + + [1234567890, [ + [0, "1234567890"], + [1, "1234567890"], + [2, "1234567890.00"], + [3, "1,234,567,890"], + [4, "1,234,567,890.00"], + [9, "123456789000%"], + [10, "123456789000.00%"], + [11, "1.23E+09"], + [12, "1234567890 "], + [13, "1234567890 "], + [14, ""], + [15, ""], + [16, ""], + [17, ""], + [18, ""], + [19, ""], + [20, ""], + [21, ""], + [22, ""], + [37, "1,234,567,890 "], + [38, "1,234,567,890 "], + [39, "1,234,567,890.00"], + [40, "1,234,567,890.00"], + [45, ""], + [46, ""], + [47, ""], + [48, "1.2E+9"], + [49, "1234567890"] + ]], + + [123456789, [ + [0, "123456789"], + [1, "123456789"], + [2, "123456789.00"], + [3, "123,456,789"], + [4, "123,456,789.00"], + [9, "12345678900%"], + [10, "12345678900.00%"], + [11, "1.23E+08"], + [12, "123456789 "], + [13, "123456789 "], + [14, ""], + [15, ""], + [16, ""], + [17, ""], + [18, ""], + [19, ""], + [20, ""], + [21, ""], + [22, ""], + [37, "123,456,789 "], + [38, "123,456,789 "], + [39, "123,456,789.00"], + [40, "123,456,789.00"], + [45, ""], + [46, ""], + [47, ""], + [48, "123.5E+6"], + [49, "123456789"] + ]], + + [12345678.9, [ + [0, "12345678.9"], + [1, "12345679"], + [2, "12345678.90"], + [3, "12,345,679"], + [4, "12,345,678.90"], + [9, "1234567890%"], + [10, "1234567890.00%"], + [11, "1.23E+07"], + [12, "12345679 "], + [13, "12345678 9/10"], + [14, ""], + [15, ""], + [16, ""], + [17, ""], + [18, ""], + [19, ""], + [20, ""], + [21, ""], + [22, ""], + [37, "12,345,679 "], + [38, "12,345,679 "], + [39, "12,345,678.90"], + [40, "12,345,678.90"], + [45, ""], + [46, ""], + [47, ""], + [48, "12.3E+6"], + [49, "12345678.9"] + ]], + + [1234567.89, [ + [0, "1234567.89"], + [1, "1234568"], + [2, "1234567.89"], + [3, "1,234,568"], + [4, "1,234,567.89"], + [9, "123456789%"], + [10, "123456789.00%"], + [11, "1.23E+06"], + [12, "1234567 8/9"], + [13, "1234567 8/9 "], + [14, "2/15/80"], + [15, "15-Feb-80"], + [16, "15-Feb"], + [17, "Feb-80"], + [18, "9:21 PM"], + [19, "9:21:36 PM"], + [20, "21:21"], + [21, "21:21:36"], + [22, "2/15/80 21:21"], + [37, "1,234,568 "], + [38, "1,234,568 "], + [39, "1,234,567.89"], + [40, "1,234,567.89"], + [45, "21:36"], + [46, "29629629:21:36"], + [47, "2136.0"], + [48, "1.2E+6"], + [49, "1234567.89"] + ]], + + [123456.789, [ + [0, "123456.789"], + [1, "123457"], + [2, "123456.79"], + [3, "123,457"], + [4, "123,456.79"], + [9, "12345679%"], + [10, "12345678.90%"], + [11, "1.23E+05"], + [12, "123456 4/5"], + [13, "123456 15/19"], + [14, "1/3/38"], + [15, "3-Jan-38"], + [16, "3-Jan"], + [17, "Jan-38"], + [18, "6:56 PM"], + [19, "6:56:10 PM"], + [20, "18:56"], + [21, "18:56:10"], + [22, "1/3/38 18:56"], + [37, "123,457 "], + [38, "123,457 "], + [39, "123,456.79"], + [40, "123,456.79"], + [45, "56:10"], + [46, "2962962:56:10"], + [47, "5609.6"], + [48, "123.5E+3"], + [49, "123456.789"] + ]], + + [12345.6789, [ + [0, "12345.6789"], + [1, "12346"], + [2, "12345.68"], + [3, "12,346"], + [4, "12,345.68"], + [9, "1234568%"], + [10, "1234567.89%"], + [11, "1.23E+04"], + [12, "12345 2/3"], + [13, "12345 55/81"], + [14, "10/18/33"], + [15, "18-Oct-33"], + [16, "18-Oct"], + [17, "Oct-33"], + [18, "4:17 PM"], + [19, "4:17:37 PM"], + [20, "16:17"], + [21, "16:17:37"], + [22, "10/18/33 16:17"], + [37, "12,346 "], + [38, "12,346 "], + [39, "12,345.68"], + [40, "12,345.68"], + [45, "17:37"], + [46, "296296:17:37"], + [47, "1737.0"], + [48, "12.3E+3"], + [49, "12345.6789"] + ]], + + [1234.56789, [ + [0, "1234.56789"], + [1, "1235"], + [2, "1234.57"], + [3, "1,235"], + [4, "1,234.57"], + [9, "123457%"], + [10, "123456.79%"], + [11, "1.23E+03"], + [12, "1234 4/7"], + [13, "1234 46/81"], + [14, "5/18/03"], + [15, "18-May-03"], + [16, "18-May"], + [17, "May-03"], + [18, "1:37 PM"], + [19, "1:37:46 PM"], + [20, "13:37"], + [21, "13:37:46"], + [22, "5/18/03 13:37"], + [37, "1,235 "], + [38, "1,235 "], + [39, "1,234.57"], + [40, "1,234.57"], + [45, "37:46"], + [46, "29629:37:46"], + [47, "3745.7"], + [48, "1.2E+3"], + [49, "1234.56789"] + ]], + + [123.456789, [ + [0, "123.456789"], + [1, "123"], + [2, "123.46"], + [3, "123"], + [4, "123.46"], + [9, "12346%"], + [10, "12345.68%"], + [11, "1.23E+02"], + [12, "123 1/2"], + [13, "123 37/81"], + [14, "5/2/00"], + [15, "2-May-00"], + [16, "2-May"], + [17, "May-00"], + [18, "10:57 AM"], + [19, "10:57:47 AM"], + [20, "10:57"], + [21, "10:57:47"], + [22, "5/2/00 10:57"], + [37, "123 "], + [38, "123 "], + [39, "123.46"], + [40, "123.46"], + [45, "57:47"], + [46, "2962:57:47"], + [47, "5746.6"], + [48, "123.5E+0", true], + [49, "123.456789"] + ]], + + [12.3456789, [ + [0, "12.3456789"], + [1, "12"], + [2, "12.35"], + [3, "12"], + [4, "12.35"], + [9, "1235%"], + [10, "1234.57%"], + [11, "1.23E+01"], + [12, "12 1/3"], + [13, "12 28/81"], + [14, "1/12/00"], + [15, "12-Jan-00"], + [16, "12-Jan"], + [17, "Jan-00"], + [18, "8:17 AM"], + [19, "8:17:47 AM"], + [20, "8:17"], + [21, "8:17:47"], + [22, "1/12/00 8:17"], + [37, "12 "], + [38, "12 "], + [39, "12.35"], + [40, "12.35"], + [45, "17:47"], + [46, "296:17:47"], + [47, "1746.7"], + [48, "12.3E+0", true], + [49, "12.3456789"] + ]], + + [1.23456789, [ + [0, "1.23456789"], + [1, "1"], + [2, "1.23"], + [3, "1"], + [4, "1.23"], + [9, "123%"], + [10, "123.46%"], + [11, "1.23E+00"], + [12, "1 1/4"], + [13, "1 19/81"], + [14, "1/1/00"], + [15, "1-Jan-00"], + [16, "1-Jan"], + [17, "Jan-00"], + [18, "5:37 AM"], + [19, "5:37:47 AM"], + [20, "5:37"], + [21, "5:37:47"], + [22, "1/1/00 5:37"], + [37, "1 "], + [38, "1 "], + [39, "1.23"], + [40, "1.23"], + [45, "37:47"], + [46, "29:37:47"], + [47, "3746.7"], + [48, "1.2E+0", true], + [49, "1.23456789"] + ]], + + [0.123456789, [ + [0, "0.123456789"], + [1, "0"], + [2, "0.12"], + [3, "0"], + [4, "0.12"], + [9, "12%"], + [10, "12.35%"], + [11, "1.23E-01"], + [12, " 1/8"], + [13, " 10/81"], + [14, "1/0/00"], + [15, "0-Jan-00"], + [16, "0-Jan"], + [17, "Jan-00"], + [18, "2:57 AM"], + [19, "2:57:47 AM"], + [20, "2:57"], + [21, "2:57:47"], + [22, "1/0/00 2:57"], + [37, "0 "], + [38, "0 "], + [39, "0.12"], + [40, "0.12"], + [45, "57:47"], + [46, "2:57:47"], + [47, "5746.7"], + [48, "123.5E-3", true], + [49, "0.123456789", true] + ]], + + [0.0123456789, [ + [0, "0.012345679"], + [1, "0"], + [2, "0.01"], + [3, "0"], + [4, "0.01"], + [9, "1%"], + [10, "1.23%"], + [11, "1.23E-02"], + [12, "0 "], + [13, " 1/81"], + [14, "1/0/00"], + [15, "0-Jan-00"], + [16, "0-Jan"], + [17, "Jan-00"], + [18, "12:17 AM"], + [19, "12:17:47 AM"], + [20, "0:17"], + [21, "0:17:47"], + [22, "1/0/00 0:17"], + [37, "0 "], + [38, "0 "], + [39, "0.01"], + [40, "0.01"], + [45, "17:47"], + [46, "0:17:47"], + [47, "1746.7"], + [48, "12.3E-3", true], + [49, "0.012345679", true] + ]], + + [0.00123456789, [ + [0, "0.001234568"], + [1, "0"], + [2, "0.00"], + [3, "0"], + [4, "0.00"], + [9, "0%"], + [10, "0.12%"], + [11, "1.23E-03"], + [12, "0 "], + [13, "0 "], + [14, "1/0/00"], + [15, "0-Jan-00"], + [16, "0-Jan"], + [17, "Jan-00"], + [18, "12:01 AM"], + [19, "12:01:47 AM"], + [20, "0:01"], + [21, "0:01:47"], + [22, "1/0/00 0:01"], + [37, "0 "], + [38, "0 "], + [39, "0.00"], + [40, "0.00"], + [45, "01:47"], + [46, "0:01:47"], + [47, "0146.7"], + [48, "1.2E-3", true], + [49, "0.001234568", true] + ]], + + [0.000123456789, [ + [0, "0.000123457"], + [1, "0"], + [2, "0.00"], + [3, "0"], + [4, "0.00"], + [9, "0%"], + [10, "0.01%"], + [11, "1.23E-04"], + [12, "0 "], + [13, "0 "], + [14, "1/0/00"], + [15, "0-Jan-00"], + [16, "0-Jan"], + [17, "Jan-00"], + [18, "12:00 AM"], + [19, "12:00:11 AM"], + [20, "0:00"], + [21, "0:00:11"], + [22, "1/0/00 0:00"], + [37, "0 "], + [38, "0 "], + [39, "0.00"], + [40, "0.00"], + [45, "00:11"], + [46, "0:00:11"], + [47, "0010.7"], + [48, "123.5E-6", true], + [49, "0.000123457", true] + ]], + + [0.0000123456789, [ + [0, "1.23457E-05"], + [1, "0"], + [2, "0.00"], + [3, "0"], + [4, "0.00"], + [9, "0%"], + [10, "0.00%"], + [11, "1.23E-05"], + [12, "0 "], + [13, "0 "], + [14, "1/0/00"], + [15, "0-Jan-00"], + [16, "0-Jan"], + [17, "Jan-00"], + [18, "12:00 AM"], + [19, "12:00:01 AM"], + [20, "0:00"], + [21, "0:00:01"], + [22, "1/0/00 0:00"], + [37, "0 "], + [38, "0 "], + [39, "0.00"], + [40, "0.00"], + [45, "00:01"], + [46, "0:00:01"], + [47, "0001.1"], + [48, "12.3E-6", true], + [49, "1.23457E-05", true] + ]], + + [0.00000123456789, [ + [0, "1.23457E-06"], + [1, "0"], + [2, "0.00"], + [3, "0"], + [4, "0.00"], + [9, "0%"], + [10, "0.00%"], + [11, "1.23E-06"], + [12, "0 "], + [13, "0 "], + [14, "1/0/00"], + [15, "0-Jan-00"], + [16, "0-Jan"], + [17, "Jan-00"], + [18, "12:00 AM"], + [19, "12:00:00 AM"], + [20, "0:00"], + [21, "0:00:00"], + [22, "1/0/00 0:00"], + [37, "0 "], + [38, "0 "], + [39, "0.00"], + [40, "0.00"], + [45, "00:00"], + [46, "0:00:00"], + [47, "0000.1"], + [48, "1.2E-6", true], + [49, "1.23457E-06", true] + ]], + + [0.000000123456789, [ + [0, "1.23457E-07"], + [1, "0"], + [2, "0.00"], + [3, "0"], + [4, "0.00"], + [9, "0%"], + [10, "0.00%"], + [11, "1.23E-07"], + [12, "0 "], + [13, "0 "], + [14, "1/0/00"], + [15, "0-Jan-00"], + [16, "0-Jan"], + [17, "Jan-00"], + [18, "12:00 AM"], + [19, "12:00:00 AM"], + [20, "0:00"], + [21, "0:00:00"], + [22, "1/0/00 0:00"], + [37, "0 "], + [38, "0 "], + [39, "0.00"], + [40, "0.00"], + [45, "00:00"], + [46, "0:00:00"], + [47, "0000.0"], + [48, "123.5E-9", true], + [49, "1.23457E-07", true] + ]], + + [0.0000000123456789, [ + [0, "1.23457E-08"], + [1, "0"], + [2, "0.00"], + [3, "0"], + [4, "0.00"], + [9, "0%"], + [10, "0.00%"], + [11, "1.23E-08"], + [12, "0 "], + [13, "0 "], + [14, "1/0/00"], + [15, "0-Jan-00"], + [16, "0-Jan"], + [17, "Jan-00"], + [18, "12:00 AM"], + [19, "12:00:00 AM"], + [20, "0:00"], + [21, "0:00:00"], + [22, "1/0/00 0:00"], + [37, "0 "], + [38, "0 "], + [39, "0.00"], + [40, "0.00"], + [45, "00:00"], + [46, "0:00:00"], + [47, "0000.0"], + [48, "12.3E-9", true], + [49, "1.23457E-08", true] + ]], + + [0.00000000123456789, [ + [0, "1.23457E-09"], + [1, "0"], + [2, "0.00"], + [3, "0"], + [4, "0.00"], + [9, "0%"], + [10, "0.00%"], + [11, "1.23E-09"], + [12, "0 "], + [13, "0 "], + [14, "1/0/00"], + [15, "0-Jan-00"], + [16, "0-Jan"], + [17, "Jan-00"], + [18, "12:00 AM"], + [19, "12:00:00 AM"], + [20, "0:00"], + [21, "0:00:00"], + [22, "1/0/00 0:00"], + [37, "0 "], + [38, "0 "], + [39, "0.00"], + [40, "0.00"], + [45, "00:00"], + [46, "0:00:00"], + [47, "0000.0"], + [48, "1.2E-9", true], + [49, "1.23457E-09", true] + ]], + + [0.000000000123456789, [ + [0, "1.23457E-10"], + [1, "0"], + [2, "0.00"], + [3, "0"], + [4, "0.00"], + [9, "0%"], + [10, "0.00%"], + [11, "1.23E-10"], + [12, "0 "], + [13, "0 "], + [14, "1/0/00"], + [15, "0-Jan-00"], + [16, "0-Jan"], + [17, "Jan-00"], + [18, "12:00 AM"], + [19, "12:00:00 AM"], + [20, "0:00"], + [21, "0:00:00"], + [22, "1/0/00 0:00"], + [37, "0 "], + [38, "0 "], + [39, "0.00"], + [40, "0.00"], + [45, "00:00"], + [46, "0:00:00"], + [47, "0000.0"], + [48, "123.5E-12", true], + [49, "1.23457E-10", true] + ]], + + + + + [-12345.6789, [ + [0, "-12345.6789"], + [1, "-12346"], + [2, "-12345.68"], + [3, "-12,346"], + [4, "-12,345.68"], + [9, "-1234568%"], + [10, "-1234567.89%"], + [11, "-1.23E+04"], + [12, "-12345 2/3"], + [13, "-12345 55/81"], + [14, ""], + [15, ""], + [16, ""], + [17, ""], + [18, ""], + [19, ""], + [20, ""], + [21, ""], + [22, ""], + [37, "(12,346)"], + [38, "(12,346)"], + [39, "(12,345.68)"], + [40, "(12,345.68)"], + [45, ""], + [46, ""], + [47, ""], + [48, "-12.3E+3"], + [49, "-12345.6789"] + ]], [11.666666666666666, 0, "11.66666667"], [5.057996968497839, 0, "5.057996968"], [4.380353866983808, 0, "4.380353867"], [12.333333333333343, 0, "12.33333333"], [-0.000006211546860868111, 0, "-6.21155E-06"], - + [12345.67876, 47, "1724.9"], [0, 0, "0"] ]