From: Iskren Chernev Date: Tue, 29 Sep 2015 05:19:17 +0000 (-0700) Subject: Implement basic format and comma as ms separator in ISO 8601 X-Git-Tag: 2.11.0~69^2~3 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=95d8a69f5af8a13552f64ca1a85df62e7f01a12b;p=thirdparty%2Fmoment.git Implement basic format and comma as ms separator in ISO 8601 --- diff --git a/src/lib/create/from-string.js b/src/lib/create/from-string.js index 4a7163b2d..be30c8a11 100644 --- a/src/lib/create/from-string.js +++ b/src/lib/create/from-string.js @@ -6,22 +6,32 @@ import getParsingFlags from './parsing-flags'; // iso 8601 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 or +00) -var isoRegex = /^\s*(?:[+-]\d{6}|\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)?|\s*Z)?)?$/; +var isoRegex = /^\s*((?:[+-]\d{6}|\d{4})-?(?:\d\d$|\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)?|\s*Z)?)?$/; var isoDates = [ - ['YYYYYY-MM-DD', /[+-]\d{6}-\d{2}-\d{2}/], - ['YYYY-MM-DD', /\d{4}-\d{2}-\d{2}/], - ['GGGG-[W]WW-E', /\d{4}-W\d{2}-\d/], - ['GGGG-[W]WW', /\d{4}-W\d{2}/], - ['YYYY-DDD', /\d{4}-\d{3}/] + ['YYYYYY-MM-DD', /[+-]\d{6}-\d{2}-\d{2}/, true], + ['YYYY-MM-DD', /\d{4}-\d{2}-\d{2}/, true], + ['GGGG-[W]WW-E', /\d{4}-W\d{2}-\d/, true], + ['GGGG-[W]WW', /\d{4}-W\d{2}/, true], + ['YYYY-DDD', /\d{4}-\d{3}/, true], + ['YYYYYYMMDD', /[+-]\d{6}\d{2}\d{2}/, false], + ['YYYYMMDD', /\d{4}\d{2}\d{2}/, false], + // YYYYMM is NOT allowed by the standard + ['GGGG[W]WWE', /\d{4}W\d{2}\d/, false], + ['GGGG[W]WW', /\d{4}W\d{2}/, false], + ['YYYYDDD', /\d{4}\d{3}/, false] ]; // iso time formats and regexes var isoTimes = [ - ['HH:mm:ss.SSSS', /(T| )\d\d:\d\d:\d\d\.\d+/], - ['HH:mm:ss', /(T| )\d\d:\d\d:\d\d/], - ['HH:mm', /(T| )\d\d:\d\d/], - ['HH', /(T| )\d\d/] + ['HH:mm:ss.SSSS', /\d\d:\d\d:\d\d\.\d+/, true], + ['HH:mm:ss', /\d\d:\d\d:\d\d/, true], + ['HH:mm', /\d\d:\d\d/, true], + ['HHmmss.SSSS', /\d\d\d\d\d\d\.\d+/, false], + ['HHmmss,SSSS', /\d\d\d\d\d\d,\d+/, false], + ['HHmmss', /\d\d\d\d\d\d/, false], + ['HHmm', /\d\d\d\d/, false], + ['HH', /\d\d/, null] ]; var aspNetJsonRegex = /^\/?Date\((\-?\d+)/i; @@ -30,24 +40,36 @@ var aspNetJsonRegex = /^\/?Date\((\-?\d+)/i; export function configFromISO(config) { var i, l, string = config._i, - match = isoRegex.exec(string); + match = isoRegex.exec(string), + extendedDate, extendedTime; if (match) { getParsingFlags(config).iso = true; + for (i = 0, l = isoDates.length; i < l; i++) { - if (isoDates[i][1].exec(string)) { + if (isoDates[i][1].exec(match[1])) { config._f = isoDates[i][0]; + extendedDate = isoDates[i][2]; break; } } for (i = 0, l = isoTimes.length; i < l; i++) { - if (isoTimes[i][1].exec(string)) { - // match[6] should be 'T' or space - config._f += (match[6] || ' ') + isoTimes[i][0]; + if (isoTimes[i][1].exec(match[3])) { + // match[2] should be 'T' or space + config._f += (match[2] || ' ') + isoTimes[i][0]; + extendedTime = isoTimes[i][2]; break; } } - if (string.match(matchOffset)) { + if (extendedDate != null && + extendedTime != null && + extendedDate !== extendedTime) { + // extended and basic formats for date and time can NOT be mixed + config._isValid = false; + return; + } + matchOffset.lastIndex = 0; + if (matchOffset.exec(match[4])) { config._f += 'Z'; } configFromStringAndFormat(config); diff --git a/src/test/moment/create.js b/src/test/moment/create.js index 9afe7b673..a3260c173 100644 --- a/src/test/moment/create.js +++ b/src/test/moment/create.js @@ -499,7 +499,82 @@ test('parsing iso', function (assert) { ['2011-281 18:04:20' + tz3, '2011-10-08T18:04:20.000' + tz], ['2011-281 18:04:20.1' + tz2, '2011-10-08T18:04:20.100' + tz], ['2011-281 18:04:20.11' + tz2, '2011-10-08T18:04:20.110' + tz], - ['2011-281 18:04:20.111' + tz2, '2011-10-08T18:04:20.111' + tz] + ['2011-281 18:04:20.111' + tz2, '2011-10-08T18:04:20.111' + tz], + ['20111008T18', '2011-10-08T18:00:00.000' + tz], + ['20111008T1804', '2011-10-08T18:04:00.000' + tz], + ['20111008T180420', '2011-10-08T18:04:20.000' + tz], + ['20111008T1804' + tz, '2011-10-08T18:04:00.000' + tz], + ['20111008T180420' + tz, '2011-10-08T18:04:20.000' + tz], + ['20111008T1804' + tz2, '2011-10-08T18:04:00.000' + tz], + ['20111008T180420' + tz2, '2011-10-08T18:04:20.000' + tz], + ['20111008T1804' + tz3, '2011-10-08T18:04:00.000' + tz], + ['20111008T180420' + tz3, '2011-10-08T18:04:20.000' + tz], + ['20111008T180420,1' + tz2, '2011-10-08T18:04:20.100' + tz], + ['20111008T180420,11' + tz2, '2011-10-08T18:04:20.110' + tz], + ['20111008T180420,111' + tz2, '2011-10-08T18:04:20.111' + tz], + ['20111008 18', '2011-10-08T18:00:00.000' + tz], + ['20111008 1804', '2011-10-08T18:04:00.000' + tz], + ['20111008 180420', '2011-10-08T18:04:20.000' + tz], + ['20111008 1804' + tz, '2011-10-08T18:04:00.000' + tz], + ['20111008 180420' + tz, '2011-10-08T18:04:20.000' + tz], + ['20111008 1804' + tz2, '2011-10-08T18:04:00.000' + tz], + ['20111008 180420' + tz2, '2011-10-08T18:04:20.000' + tz], + ['20111008 1804' + tz3, '2011-10-08T18:04:00.000' + tz], + ['20111008 180420' + tz3, '2011-10-08T18:04:20.000' + tz], + ['20111008 180420,1' + tz2, '2011-10-08T18:04:20.100' + tz], + ['20111008 180420,11' + tz2, '2011-10-08T18:04:20.110' + tz], + ['20111008 180420,111' + tz2, '2011-10-08T18:04:20.111' + tz], + ['2011W40', '2011-10-03T00:00:00.000' + tz], + ['2011W406', '2011-10-08T00:00:00.000' + tz], + ['2011W406T18', '2011-10-08T18:00:00.000' + tz], + ['2011W406T1804', '2011-10-08T18:04:00.000' + tz], + ['2011W406T180420', '2011-10-08T18:04:20.000' + tz], + ['2011W406 1804' + tz2, '2011-10-08T18:04:00.000' + tz], + ['2011W406T1804' + tz, '2011-10-08T18:04:00.000' + tz], + ['2011W406T180420' + tz, '2011-10-08T18:04:20.000' + tz], + ['2011W406T1804' + tz2, '2011-10-08T18:04:00.000' + tz], + ['2011W406T180420' + tz2, '2011-10-08T18:04:20.000' + tz], + ['2011W406T1804' + tz3, '2011-10-08T18:04:00.000' + tz], + ['2011W406T180420' + tz3, '2011-10-08T18:04:20.000' + tz], + ['2011W406T180420,1' + tz2, '2011-10-08T18:04:20.100' + tz], + ['2011W406T180420,11' + tz2, '2011-10-08T18:04:20.110' + tz], + ['2011W406T180420,111' + tz2, '2011-10-08T18:04:20.111' + tz], + ['2011W406 18', '2011-10-08T18:00:00.000' + tz], + ['2011W406 1804', '2011-10-08T18:04:00.000' + tz], + ['2011W406 180420', '2011-10-08T18:04:20.000' + tz], + ['2011W406 1804' + tz, '2011-10-08T18:04:00.000' + tz], + ['2011W406 180420' + tz, '2011-10-08T18:04:20.000' + tz], + ['2011W406 180420' + tz2, '2011-10-08T18:04:20.000' + tz], + ['2011W406 1804' + tz3, '2011-10-08T18:04:00.000' + tz], + ['2011W406 180420' + tz3, '2011-10-08T18:04:20.000' + tz], + ['2011W406 180420,1' + tz2, '2011-10-08T18:04:20.100' + tz], + ['2011W406 180420,11' + tz2, '2011-10-08T18:04:20.110' + tz], + ['2011W406 180420,111' + tz2, '2011-10-08T18:04:20.111' + tz], + ['2011281', '2011-10-08T00:00:00.000' + tz], + ['2011281T18', '2011-10-08T18:00:00.000' + tz], + ['2011281T1804', '2011-10-08T18:04:00.000' + tz], + ['2011281T180420', '2011-10-08T18:04:20.000' + tz], + ['2011281T1804' + tz, '2011-10-08T18:04:00.000' + tz], + ['2011281T180420' + tz, '2011-10-08T18:04:20.000' + tz], + ['2011281T1804' + tz2, '2011-10-08T18:04:00.000' + tz], + ['2011281T180420' + tz2, '2011-10-08T18:04:20.000' + tz], + ['2011281T1804' + tz3, '2011-10-08T18:04:00.000' + tz], + ['2011281T180420' + tz3, '2011-10-08T18:04:20.000' + tz], + ['2011281T180420,1' + tz2, '2011-10-08T18:04:20.100' + tz], + ['2011281T180420,11' + tz2, '2011-10-08T18:04:20.110' + tz], + ['2011281T180420,111' + tz2, '2011-10-08T18:04:20.111' + tz], + ['2011281 18', '2011-10-08T18:00:00.000' + tz], + ['2011281 1804', '2011-10-08T18:04:00.000' + tz], + ['2011281 180420', '2011-10-08T18:04:20.000' + tz], + ['2011281 1804' + tz, '2011-10-08T18:04:00.000' + tz], + ['2011281 180420' + tz, '2011-10-08T18:04:20.000' + tz], + ['2011281 1804' + tz2, '2011-10-08T18:04:00.000' + tz], + ['2011281 180420' + tz2, '2011-10-08T18:04:20.000' + tz], + ['2011281 1804' + tz3, '2011-10-08T18:04:00.000' + tz], + ['2011281 180420' + tz3, '2011-10-08T18:04:20.000' + tz], + ['2011281 180420,1' + tz2, '2011-10-08T18:04:20.100' + tz], + ['2011281 180420,11' + tz2, '2011-10-08T18:04:20.110' + tz], + ['2011281 180420,111' + tz2, '2011-10-08T18:04:20.111' + tz] ], i; for (i = 0; i < formats.length; i++) { assert.equal(moment(formats[i][0]).format('YYYY-MM-DDTHH:mm:ss.SSSZ'), formats[i][1], 'moment should be able to parse ISO ' + formats[i][0]); diff --git a/src/test/moment/is_valid.js b/src/test/moment/is_valid.js index 2c1b13ea4..07999a0d9 100644 --- a/src/test/moment/is_valid.js +++ b/src/test/moment/is_valid.js @@ -103,7 +103,8 @@ test('invalid string iso 8601 + timezone', function (assert) { '2010-01-40T24:01+00:00', '2010-01-40T23:60+00:00', '2010-01-40T23:59:60+00:00', - '2010-01-40T23:59:59.9999+00:00' + '2010-01-40T23:59:59.9999+00:00', + '2010-01-40T23:59:59,9999+00:00' ], i; for (i = 0; i < tests.length; i++) { @@ -112,6 +113,26 @@ test('invalid string iso 8601 + timezone', function (assert) { } }); +test('valid string iso 8601 - not strict', function (assert) { + var tests = [ + '2010-01-30 00:00:00,000Z', + '20100101', + '20100130', + '20100130T23+00:00', + '20100130T2359+0000', + '20100130T235959+0000', + '20100130T235959,999+0000', + '20100130T235959,999-0700', + '20100130T000000,000+0700', + '20100130 000000,000Z' + ]; + + for (var i = 0; i < tests.length; i++) { + assert.equal(moment(tests[i]).isValid(), true, tests[i] + ' should be valid in normal'); + assert.equal(moment.utc(tests[i]).isValid(), true, tests[i] + ' should be valid in normal'); + } +}); + test('valid string iso 8601 + timezone', function (assert) { var tests = [ '2010-01-01', diff --git a/src/test/qunit.js b/src/test/qunit.js index 81a95e6fc..5a43df461 100644 --- a/src/test/qunit.js +++ b/src/test/qunit.js @@ -8,8 +8,8 @@ export function module (name, lifecycle) { QUnit.module(name, { setup : function () { moment.locale('en'); - moment.createFromInputFallback = function () { - throw new Error('input not handled by moment'); + moment.createFromInputFallback = function (config) { + throw new Error('input not handled by moment: ' + config._i); }; if (lifecycle && lifecycle.setup) { lifecycle.setup(); @@ -27,8 +27,8 @@ export function localeModule (name, lifecycle) { QUnit.module('locale:' + name, { setup : function () { moment.locale(name); - moment.createFromInputFallback = function () { - throw new Error('input not handled by moment'); + moment.createFromInputFallback = function (config) { + throw new Error('input not handled by moment: ' + config._i); }; if (lifecycle && lifecycle.setup) { lifecycle.setup();