From 45d57acb039bf186a5be240cb96b684ca36da6a9 Mon Sep 17 00:00:00 2001 From: Iskren Chernev Date: Thu, 24 Oct 2013 02:09:59 -0700 Subject: [PATCH] Allow arbitrary number of milliseconds in iso format According to the standard (I'm not sure actually), arbitrary number of subsecond precision digits can be specified. Read all of those and ignore everything after the third. This makes sure that iso formats actualy consume the whole string. --- moment.js | 13 ++++++++++--- test/moment/create.js | 17 +++++++++++++++-- 2 files changed, 25 insertions(+), 5 deletions(-) diff --git a/moment.js b/moment.js index a256f1b02..63698b33d 100644 --- a/moment.js +++ b/moment.js @@ -38,7 +38,7 @@ isoDurationRegex = /^(-)?P(?:(?:([0-9,.]*)Y)?(?:([0-9,.]*)M)?(?:([0-9,.]*)D)?(?:T(?:([0-9,.]*)H)?(?:([0-9,.]*)M)?(?:([0-9,.]*)S)?)?|([0-9,.]*)W)$/, // format tokens - formattingTokens = /(\[[^\[]*\])|(\\)?(Mo|MM?M?M?|Do|DDDo|DD?D?D?|ddd?d?|do?|w[o|w]?|W[o|W]?|YYYYY|YYYY|YY|gg(ggg?)?|GG(GGG?)?|e|E|a|A|hh?|HH?|mm?|ss?|SS?S?|X|zz?|ZZ?|.)/g, + formattingTokens = /(\[[^\[]*\])|(\\)?(Mo|MM?M?M?|Do|DDDo|DD?D?D?|ddd?d?|do?|w[o|w]?|W[o|W]?|YYYYY|YYYY|YY|gg(ggg?)?|GG(GGG?)?|e|E|a|A|hh?|HH?|mm?|ss?|S{1,4}|X|zz?|ZZ?|.)/g, localFormattingTokens = /(\[[^\[]*\])|(\\)?(LT|LL?L?L?|l{1,4})/g, // parsing token regexes @@ -47,6 +47,7 @@ parseTokenThreeDigits = /\d{3}/, // 000 - 999 parseTokenFourDigits = /\d{1,4}/, // 0 - 9999 parseTokenSixDigits = /[+\-]?\d{1,6}/, // -999,999 - 999,999 + parseTokenDigits = /\d+/, // nonzero number of digits parseTokenWord = /[0-9]*['a-z\u00A0-\u05FF\u0700-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]+|[\u0600-\u06FF\/]+(\s*?[\u0600-\u06FF]+){1,2}/i, // any word (or two) characters or numbers including two/three word month in arabic. parseTokenTimezone = /Z|[\+\-]\d\d:?\d\d/i, // +00:00 -00:00 +0000 -0000 or Z parseTokenT = /T/i, // T (ISO seperator) @@ -54,7 +55,7 @@ // preliminary iso regex // 0000-00-00 0000-W00 or 0000-W00-0 + T + 00 or 00:00 or 00:00:00 or 00:00:00.000 + +00:00 or +0000) - isoRegex = /^\s*\d{4}-(?:(\d\d-\d\d)|(W\d\d$)|(W\d\d-\d)|(\d\d\d))((T| )(\d\d(:\d\d(:\d\d(\.\d\d?\d?)?)?)?)?([\+\-]\d\d:?\d\d|Z)?)?$/, + isoRegex = /^\s*\d{4}-(?:(\d\d-\d\d)|(W\d\d$)|(W\d\d-\d)|(\d\d\d))((T| )(\d\d(:\d\d(:\d\d(\.\d+)?)?)?)?([\+\-]\d\d:?\d\d|Z)?)?$/, isoFormat = 'YYYY-MM-DDTHH:mm:ssZ', @@ -67,7 +68,7 @@ // iso time formats and regexes isoTimes = [ - ['HH:mm:ss.S', /(T| )\d\d:\d\d:\d\d\.\d{1,3}/], + ['HH:mm:ss.SSSS', /(T| )\d\d:\d\d:\d\d\.\d{1,3}/], ['HH:mm:ss', /(T| )\d\d:\d\d:\d\d/], ['HH:mm', /(T| )\d\d:\d\d/], ['HH', /(T| )\d\d/] @@ -215,6 +216,9 @@ SSS : function () { return leftZeroFill(this.milliseconds(), 3); }, + SSSS : function () { + return leftZeroFill(this.milliseconds(), 3); + }, Z : function () { var a = -this.zone(), b = "+"; @@ -931,6 +935,8 @@ return parseTokenTimezone; case 'T': return parseTokenT; + case 'SSSS': + return parseTokenDigits; case 'MM': case 'DD': case 'YY': @@ -1039,6 +1045,7 @@ case 'S' : case 'SS' : case 'SSS' : + case 'SSSS' : datePartArray[MILLISECOND] = toInt(('0.' + input) * 1000); break; // UNIX TIMESTAMP WITH MS diff --git a/test/moment/create.js b/test/moment/create.js index b02e8d5f7..420c10ab4 100644 --- a/test/moment/create.js +++ b/test/moment/create.js @@ -269,6 +269,19 @@ exports.create = { test.done(); }, + "milliseconds format" : function (test) { + test.expect(5); + test.equal(moment('1', 'S').get('ms'), 100, 'deciseconds'); + // test.equal(moment('10', 'S', true).isValid(), false, 'deciseconds with two digits'); + // test.equal(moment('1', 'SS', true).isValid(), false, 'centiseconds with one digits'); + test.equal(moment('12', 'SS').get('ms'), 120, 'centiseconds'); + // test.equal(moment('123', 'SS', true).isValid(), false, 'centiseconds with three digits'); + test.equal(moment('123', 'SSS').get('ms'), 123, 'milliseconds'); + test.equal(moment('1234', 'SSSS').get('ms'), 123, 'milliseconds with SSSS') + test.equal(moment('123456789101112', 'SSSS').get('ms'), 123, 'milliseconds with SSSS') + test.done(); + }, + "string with format no separators" : function (test) { moment.lang('en'); var a = [ @@ -520,12 +533,12 @@ exports.create = { test.equal(moment('2011-10-08T18')._f, "YYYY-MM-DDTHH", "should include 'T' in the format"); test.equal(moment('2011-10-08T18:20')._f, "YYYY-MM-DDTHH:mm", "should include 'T' in the format"); test.equal(moment('2011-10-08T18:20:13')._f, "YYYY-MM-DDTHH:mm:ss", "should include 'T' in the format"); - test.equal(moment('2011-10-08T18:20:13.321')._f, "YYYY-MM-DDTHH:mm:ss.S", "should include 'T' in the format"); + test.equal(moment('2011-10-08T18:20:13.321')._f, "YYYY-MM-DDTHH:mm:ss.SSSS", "should include 'T' in the format"); test.equal(moment('2011-10-08 18')._f, "YYYY-MM-DD HH", "should not include 'T' in the format"); test.equal(moment('2011-10-08 18:20')._f, "YYYY-MM-DD HH:mm", "should not include 'T' in the format"); test.equal(moment('2011-10-08 18:20:13')._f, "YYYY-MM-DD HH:mm:ss", "should not include 'T' in the format"); - test.equal(moment('2011-10-08 18:20:13.321')._f, "YYYY-MM-DD HH:mm:ss.S", "should not include 'T' in the format"); + test.equal(moment('2011-10-08 18:20:13.321')._f, "YYYY-MM-DD HH:mm:ss.SSSS", "should not include 'T' in the format"); test.done(); }, -- 2.47.2