diff --git a/src/lib/create/from-string-and-format.js b/src/lib/create/from-string-and-format.js index 87eecafb3c..bbaab0de31 100644 --- a/src/lib/create/from-string-and-format.js +++ b/src/lib/create/from-string-and-format.js @@ -70,6 +70,9 @@ export function configFromStringAndFormat(config) { config._a[HOUR] > 0) { getParsingFlags(config).bigHour = undefined; } + + getParsingFlags(config).parsedDateParts = config._a.slice(0); + getParsingFlags(config).meridiem = config._meridiem; // handle meridiem config._a[HOUR] = meridiemFixWrap(config._locale, config._a[HOUR], config._meridiem); diff --git a/src/lib/create/parsing-flags.js b/src/lib/create/parsing-flags.js index 2bfbcb3414..5a4220013a 100644 --- a/src/lib/create/parsing-flags.js +++ b/src/lib/create/parsing-flags.js @@ -10,7 +10,9 @@ function defaultParsingFlags() { invalidMonth : null, invalidFormat : false, userInvalidated : false, - iso : false + iso : false, + parsedDateParts : [], + meridiem : null }; } diff --git a/src/lib/create/valid.js b/src/lib/create/valid.js index ad56bfe063..4c621168ca 100644 --- a/src/lib/create/valid.js +++ b/src/lib/create/valid.js @@ -1,10 +1,14 @@ import extend from '../utils/extend'; import { createUTC } from './utc'; import getParsingFlags from '../create/parsing-flags'; +import some from '../utils/some'; export function isValid(m) { if (m._isValid == null) { var flags = getParsingFlags(m); + var parsedParts = some.call(flags.parsedDateParts, function (i) { + return i != null; + }); m._isValid = !isNaN(m._d.getTime()) && flags.overflow < 0 && !flags.empty && @@ -12,7 +16,8 @@ export function isValid(m) { !flags.invalidWeekday && !flags.nullInput && !flags.invalidFormat && - !flags.userInvalidated; + !flags.userInvalidated && + (!flags.meridiem || (flags.meridiem && parsedParts)); if (m._strict) { m._isValid = m._isValid && diff --git a/src/lib/utils/some.js b/src/lib/utils/some.js new file mode 100644 index 0000000000..1bd318675f --- /dev/null +++ b/src/lib/utils/some.js @@ -0,0 +1,19 @@ +var some; +if (Array.prototype.some) { + some = Array.prototype.some; +} else { + some = function (fun) { + var t = Object(this); + var len = t.length >>> 0; + + for (var i = 0; i < len; i++) { + if (i in t && fun.call(this, t[i], i, t)) { + return true; + } + } + + return false; + }; +} + +export { some as default }; diff --git a/src/test/moment/create.js b/src/test/moment/create.js index 02181e40b6..1e6d2b6f81 100644 --- a/src/test/moment/create.js +++ b/src/test/moment/create.js @@ -1041,3 +1041,19 @@ test('hmm', function (assert) { test('Y token', function (assert) { assert.equal(moment('1-1-2010', 'M-D-Y', true).year(), 2010, 'parsing Y'); }); + +test('parsing flags retain parsed date parts', function (assert) { + var a = moment('10 p', 'hh:mm a'); + assert.equal(a.parsingFlags().parsedDateParts[3], 10, 'parsed 10 as the hour'); + assert.equal(a.parsingFlags().parsedDateParts[0], undefined, 'year was not parsed'); + assert.equal(a.parsingFlags().meridiem, 'p', 'meridiem flag was added'); + var b = moment('10:30', ['MMDDYY', 'HH:mm']); + assert.equal(b.parsingFlags().parsedDateParts[3], 10, 'multiple format parshing matched hour'); + assert.equal(b.parsingFlags().parsedDateParts[0], undefined, 'array is properly copied, no residual data from first token parse'); +}); + +test('parsing only meridiem results in invalid date', function (assert) { + assert.ok(!moment('alkj', 'hh:mm a').isValid(), 'because an a token is used, a meridiem will be parsed but nothing else was so invalid'); + assert.ok(moment('02:30 p more extra stuff', 'hh:mm a').isValid(), 'because other tokens were parsed, date is valid'); + assert.ok(moment('1/1/2016 extra data', ['a', 'M/D/YYYY']).isValid(), 'took second format, does not pick up on meridiem parsed from first format (good copy)'); +});