return value;
}
- function applyWeekData(m) {
- var apply = function () {
- var i, unit, norm, val, found = false;
- for (i in arguments) {
- unit = arguments[i];
- norm = normalizeUnits(unit);
- if (m._w[unit]) {
- found = true;
- val = m._w[unit];
- val = i === '0' && val.length < 3 ? (parseInt(val, 10) > 68 ? '19' + val : '20' + val) : val;
- m.set(norm, val);
- }
- else if (found) {
- m.set(norm, unit === 'e' ? 0 : 1);
- }
+ function daysInMonth(year, month) {
- return moment.utc([year, month + 1, 0]).date();
++ return new Date(Date.UTC(year, month + 1, 0)).getUTCDate();
++ }
++
++ function daysInYear(year) {
++ return isLeapYear(year) ? 366 : 365;
+ }
+
+ function isLeapYear(year) {
+ return (year % 4 === 0 && year % 100 !== 0) || year % 400 === 0;
+ }
+
+ function checkOverflow(m) {
+ var overflow;
+ if (m._a && m._pf.overflow === -2) {
+ overflow =
+ m._a[MONTH] < 0 || m._a[MONTH] > 11 ? MONTH :
+ m._a[DATE] < 1 || m._a[DATE] > daysInMonth(m._a[YEAR], m._a[MONTH]) ? DATE :
+ m._a[HOUR] < 0 || m._a[HOUR] > 23 ? HOUR :
+ m._a[MINUTE] < 0 || m._a[MINUTE] > 59 ? MINUTE :
+ m._a[SECOND] < 0 || m._a[SECOND] > 59 ? SECOND :
+ m._a[MILLISECOND] < 0 || m._a[MILLISECOND] > 999 ? MILLISECOND :
+ -1;
+
+ if (m._pf._overflowDayOfYear && (overflow < YEAR || overflow > DATE)) {
+ overflow = DATE;
}
- };
- apply('gg', 'w', 'e');
- apply('GG', 'W', 'E');
+ m._pf.overflow = overflow;
+ }
+ }
+
+ function initializeParsingFlags(config) {
+ config._pf = {
+ empty : false,
+ unusedTokens : [],
+ unusedInput : [],
+ overflow : -2,
+ charsLeftOver : 0,
+ nullInput : false,
+ invalidMonth : null,
+ userInvalidated : false,
+ };
+ }
- if (m._w['d']) {
- m.day(m._w['d']);
+ function isValid(m) {
+ if (m._isValid == null) {
+ m._isValid = !isNaN(m._d.getTime()) &&
+ m._pf.overflow < 0 &&
+ !m._pf.empty &&
+ !m._pf.invalidMonth &&
+ !m._pf.nullInput &&
+ !m._pf.userInvalidated;
+
+ if (m._strict) {
+ m._isValid = m._isValid &&
+ m._pf.charsLeftOver === 0 &&
+ m._pf.unusedTokens.length === 0;
+ }
}
+ return m._isValid;
+ }
+
+ function normalizeLanguage(key) {
+ return key ? key.toLowerCase().replace('_', '-') : key;
}
/************************************
week : function (mom) {
return weekOfYear(mom, this._week.dow, this._week.doy).week;
},
++
_week : {
dow : 0, // Sunday is the first day of the week.
doy : 6 // The week that contains Jan 1st is the first week of the year.
case 'h':
case 'm':
case 's':
+ case 'w':
+ case 'ww':
+ case 'W':
+ case 'WW':
+ case 'e':
+ case 'ee':
+ case 'E':
+ case 'EE':
return parseTokenOneOrTwoDigits;
default :
- return new RegExp(regexpEscape(token.replace('\\', '')));
+ a = new RegExp(regexpEscape(unescapeFormat(token.replace('\\', '')), "i"));
+ return a;
}
}
config._useUTC = true;
config._tzm = timezoneMinutesFromString(input);
break;
+ case 'w':
+ case 'ww':
+ case 'W':
+ case 'WW':
+ case 'd':
+ case 'dd':
+ case 'ddd':
+ case 'dddd':
+ case 'e':
+ case 'E':
+ token = token.substr(0, 1);
+ /* falls through */
+ case 'gg':
+ case 'gggg':
+ case 'GG':
+ case 'GGGG':
+ case 'GGGGG':
+ token = token.substr(0, 2);
+ if (input) {
+ config._w = config._w || {};
+ config._w[token] = input;
+ }
+ break;
}
-
- // if the input is null, the date is not valid
- if (input == null) {
- config._isValid = false;
- }
}
// convert an array to a date.
// the array should mirror the parameters below
// note: all values past the year are optional and will default to the lowest possible value.
// [year, month, day , hour, minute, second, millisecond]
- function dateFromArray(config) {
- var i, date, input = [], currentDate;
+ function dateFromConfig(config) {
- var i, date, input = [], currentDate, yearToUse;
++ var i, date, input = [], currentDate, yearToUse, fixYear, w, temp, lang;
if (config._d) {
return;
}
- if (config._dayOfYear > (isLeapYear(yearToUse) ? 364 : 365)) {
+ currentDate = currentDateArray(config);
+
++ //compute day of the year form weeks and weekdays
++ if (config._w && config._a[DATE] == null && config._a[MONTH] == null) {
++ fixYear = function (val) {
++ return val ?
++ (val.length < 3 ? (parseInt(val, 10) > 68 ? '19' + val : '20' + val) : val) :
++ (config._a[YEAR] != null ? currentDate[YEAR] :
++ (config._a[YEAR] == null ? currentDate[YEAR] : config._a[YEAR]));
++ };
++
++ w = config._w;
++ if (w.GG != null || w.W != null || w.E != null) {
++ temp = dayOfYearFromWeeks(fixYear(w.GG), w.W, parseWeekday(w.E, config._l), 4, 1);
++ }
++ else {
++ lang = getLangDefinition(config._l);
++ temp = dayOfYearFromWeeks(fixYear(w.gg), w.w, parseWeekday(w.e || w.d, lang), lang._week.doy, lang._week.dow);
++ }
++
++ config._a[YEAR] = temp.year;
++ config._dayOfYear = temp.dayOfYear;
++ }
++
+ //if the day of the year is set, figure out what it is
+ if (config._dayOfYear) {
+ yearToUse = config._a[YEAR] == null ? currentDate[YEAR] : config._a[YEAR];
+
++ if (config._dayOfYear > daysInYear(yearToUse)) {
+ config._pf._overflowDayOfYear = true;
+ }
+
+ date = makeUTCDate(yearToUse, 0, config._dayOfYear);
+ config._a[MONTH] = date.getUTCMonth();
+ config._a[DATE] = date.getUTCDate();
+ }
+
// Default to current date.
// * if no year, month, day of month are given, default to today
// * if day of month is given, default month and year
// date from string and format string
function makeDateFromStringAndFormat(config) {
- if (config._strict) {
- makeDateFromStringAndStrictFormat(config);
- return;
- }
+
+ config._a = [];
+ config._pf.empty = true;
// This array is used to make a Date, either with `new Date` or `Date.UTC`
var lang = getLangDefinition(config._l),
}
}
+ function makeDate(y, m, d, h, M, s, ms) {
+ //can't just apply() to create a date:
+ //http://stackoverflow.com/questions/181348/instantiating-a-javascript-object-by-calling-prototype-constructor-apply
+ var date = new Date(y, m, d, h, M, s, ms);
+
+ //the date constructor doesn't accept years < 1970
+ if (y < 1970) {
+ date.setFullYear(y);
+ }
+ return date;
+ }
+
+ function makeUTCDate(y) {
+ var date = new Date(Date.UTC.apply(null, arguments));
+ if (y < 1970) {
+ date.setUTCFullYear(y);
+ }
+ return date;
+ }
+
++ function parseWeekday(input, language) {
++ if (typeof input === 'string') {
++ if (!isNaN(input)) {
++ input = parseInt(input, 10);
++ }
++ else {
++ input = language.weekdaysParse(input);
++ if (typeof input !== 'number') {
++ return null;
++ }
++ }
++ }
++ return input;
++ }
+
/************************************
Relative Time
************************************/
};
}
++ function dayOfYearFromWeeks(year, week, weekday, firstDayOfWeekOfYear, firstDayOfWeek) {
++ var d = new Date(year, 0).getUTCDay(),
++ daysToAdd, dayOfYear;
++
++ week = week || 1;
++ weekday = weekday != null ? weekday : firstDayOfWeek;
++ daysToAdd = firstDayOfWeek - d + (d > firstDayOfWeekOfYear ? 7 : 0);
++ dayOfYear = 7 * (week - 1) + (weekday - firstDayOfWeek) + daysToAdd + 1;
++
++ return {
++ year: dayOfYear > 0 ? year : year - 1,
++ dayOfYear: dayOfYear > 0 ? dayOfYear : daysInYear(year - 1) + dayOfYear
++ };
++ }
/************************************
Top Level Functions
day : function (input) {
var day = this._isUTC ? this._d.getUTCDay() : this._d.getDay();
if (input != null) {
-- if (typeof input === 'string') {
- if (!isNaN(input)) {
- input = parseInt(input, 10);
- }
- else {
- input = this.lang().weekdaysParse(input);
- if (typeof input !== 'number') {
- return this;
- }
- input = this.lang().weekdaysParse(input);
- if (typeof input !== 'number') {
- return this;
-- }
-- }
++ input = parseWeekday(input, this.lang());
return this.add({ d : input - day });
} else {
return day;
test.equal(moment('2012 july', 'YYYY MMM', 'en').month(), 6, "should be able to parse in a specific language");
moment.lang('parselang', null);
- test.equal(moment('99', 'gg').format('YYYY MM DD'), "1998 12 27", 'week-year two digits');
- test.equal(moment('1999', 'gggg').format('YYYY MM DD'), "1998 12 27", 'week-year four digits');
+ test.done();
+ },
+
+ "parsing week and weekday information" : function (test) {
+
+ //year
- test.equal(moment('3', 'ee').weekday(), 3, "day sets the day by itself");
- test.equal(moment('2013 07 03', 'YYYY MM ee').month(), 6, "weekday keeps the parsed year and month");
-
- test.equal(moment('3', 'EE').isoWeekday(), 3, "iso day sets the day by itself");
- test.equal(moment('2013 07 03', 'YYYY MM EE').month(), 6, "iso weekday keeps the parsed year and month");
-
++ test.equal(moment('12', 'gg').format('YYYY MM DD'), "2012 01 01", 'week-year two digits');
++ test.equal(moment('2012', 'gggg').format('YYYY MM DD'), "2012 01 01", 'week-year four digits');
++
++ test.equal(moment('99', 'gg').format('YYYY MM DD'), "1998 12 27", 'week-year two digits previous year');
++ test.equal(moment('1999', 'gggg').format('YYYY MM DD'), "1998 12 27", 'week-year four digits previous year');
++
+ test.equal(moment('99', 'GG').format('YYYY MM DD'), "1999 01 04", 'iso week-year two digits');
+ test.equal(moment('1999', 'GGGG').format('YYYY MM DD'), "1999 01 04", 'iso week-year four digits');
+
++ test.equal(moment('13', 'GG').format('YYYY MM DD'), "2012 12 31", 'iso week-year two digits previous year');
++ test.equal(moment('2013', 'GGGG').format('YYYY MM DD'), "2012 12 31", 'iso week-year four digits previous year');
++
+ //year + week
+ test.equal(moment('1999 37', 'gggg w').format('YYYY MM DD'), "1999 09 05", 'week');
+ test.equal(moment('1999 37', 'gggg ww').format('YYYY MM DD'), "1999 09 05", 'week double');
+ test.equal(moment('1999 37', 'GGGG W').format('YYYY MM DD'), "1999 09 13", 'iso week');
+ test.equal(moment('1999 37', 'GGGG WW').format('YYYY MM DD'), "1999 09 13", 'iso week double');
+
+ //year + week + day
+ test.equal(moment('1999 37 4', 'gggg ww e').format('YYYY MM DD'), "1999 09 09", 'day');
+ test.equal(moment('1999 37 4', 'gggg ww ee').format('YYYY MM DD'), "1999 09 09", 'day double');
+ test.equal(moment('1999 37 4', 'GGGG WW E').format('YYYY MM DD'), "1999 09 16", 'iso day');
+ test.equal(moment('1999 37 4', 'GGGG WW EE').format('YYYY MM DD'), "1999 09 16", 'iso day double');
+
+ //d
+ test.equal(moment('1999 37 4', 'gggg ww d').format('YYYY MM DD'), "1999 09 09", 'd');
+ test.equal(moment('1999 37 Th', 'gggg ww dd').format('YYYY MM DD'), "1999 09 09", 'dd');
+ test.equal(moment('1999 37 Thu', 'gggg ww ddd').format('YYYY MM DD'), "1999 09 09", 'ddd');
+ test.equal(moment('1999 37 Thursday', 'gggg ww dddd').format('YYYY MM DD'), "1999 09 09", 'dddd');
+
+ //lower-order only
+ test.equal(moment('22', 'ww').week(), 22, "week sets the week by itself");
+ test.equal(moment('22', 'ww').year(), moment().year(), "week keeps this year");
+ test.equal(moment('2013 22', 'YYYY ww').year(), 2013, "week keeps parsed year");
+
+ test.equal(moment('22', 'WW').isoWeek(), 22, "iso week sets the week by itself");
+ test.equal(moment('2013 22', 'YYYY WW').year(), 2013, "iso week keeps parsed year");
+ test.equal(moment('22', 'WW').year(), moment().year(), "iso week keeps this year");
+
+ //order
+ test.equal(moment('6 2013 2', 'e gggg w').format('YYYY MM DD'), "2013 01 12", "order doesn't matter");
+ test.equal(moment('6 2013 2', 'E GGGG W').format('YYYY MM DD'), "2013 01 12", "iso order doesn't matter");
+
test.done();
}
};
test.equal(moment(" ", "X").isValid(), false, 'string space');
test.done();
- }
+ },
+
+ "empty" : function (test) {
+ test.equal(moment(null).isValid(), false, 'null');
+ test.equal(moment('').isValid(), false, 'empty string');
+ test.equal(moment(' ').isValid(), false, 'empty when trimmed');
+
+ test.equal(moment(null, 'YYYY').isValid(), false, 'format + null');
+ test.equal(moment('', 'YYYY').isValid(), false, 'format + empty string');
+ test.equal(moment(' ', 'YYYY').isValid(), false, 'format + empty when trimmed');
+ test.done();
+ },
+
+ "days of the year" : function (test) {
+ test.equal(moment('2010 300', 'YYYY DDDD').isValid(), true, 'day 300 of year valid');
+ test.equal(moment('2010 365', 'YYYY DDDD').isValid(), true, 'day 365 of year valid');
+ test.equal(moment('2010 366', 'YYYY DDDD').isValid(), false, 'day 366 of year invalid');
- test.equal(moment('2012 364', 'YYYY DDDD').isValid(), true, 'day 364 of leap year valid');
- test.equal(moment('2012 365', 'YYYY DDDD').isValid(), false, 'day 365 of leap year invalid');
++ test.equal(moment('2012 365', 'YYYY DDDD').isValid(), true, 'day 365 of leap year valid');
++ test.equal(moment('2012 366', 'YYYY DDDD').isValid(), true, 'day 366 of leap year valid');
++ test.equal(moment('2012 367', 'YYYY DDDD').isValid(), false, 'day 367 of leap year invalid');
+
+ test.done();
+ },
+
+ "oddball permissiveness" : function (test) {
+ //https://github.com/moment/moment/issues/1128
+ test.ok(moment("2010-10-3199", ["MM/DD/YYYY", "MM-DD-YYYY", "YYYY-MM-DD"]).isValid());
+
+ //https://github.com/moment/moment/issues/1122
+ test.ok(moment("3:25", ["h:mma", "hh:mma", "H:mm", "HH:mm"]).isValid());
+
+ test.done();
+ },
};
--- /dev/null
- test.equal(flags('2012 364', 'YYYY DDDD').overflow, -1, 'day 364 of leap year valid');
- test.equal(flags('2012 365', 'YYYY DDDD').overflow, 2, 'day 365 of leap year invalid');
+ var moment = require('../../moment'),
+ flags = function () {
+ return moment.apply(null, arguments).parsingFlags();
+ };
+
+ exports.parsing_flags = {
+
+ 'overflow with array' : function (test) {
+
+ //months
+ test.equal(flags([2010, 0]).overflow, -1, 'month 0 valid');
+ test.equal(flags([2010, 1]).overflow, -1, 'month 1 valid');
+ test.equal(flags([2010, -1]).overflow, 1, 'month -1 invalid');
+ test.equal(flags([2100, 12]).overflow, 1, 'month 12 invalid');
+
+ //days
+ test.equal(flags([2010, 1, 16]).overflow, -1, 'date valid');
+ test.equal(flags([2010, 1, -1]).overflow, 2, 'date -1 invalid');
+ test.equal(flags([2010, 1, 0]).overflow, 2, 'date 0 invalid');
+ test.equal(flags([2010, 1, 32]).overflow, 2, 'date 32 invalid');
+ test.equal(flags([2012, 1, 29]).overflow, -1, 'date leap year valid');
+ test.equal(flags([2010, 1, 29]).overflow, 2, 'date leap year invalid');
+
+ //hours
+ test.equal(flags([2010, 1, 1, 8]).overflow, -1, 'hour valid');
+ test.equal(flags([2010, 1, 1, 0]).overflow, -1, 'hour 0 valid');
+ test.equal(flags([2010, 1, 1, -1]).overflow, 3, 'hour -1 invalid');
+ test.equal(flags([2010, 1, 1, 24]).overflow, 3, 'hour 24 invalid');
+
+ //minutes
+ test.equal(flags([2010, 1, 1, 8, 15]).overflow, -1, 'minute valid');
+ test.equal(flags([2010, 1, 1, 8, 0]).overflow, -1, 'minute 0 valid');
+ test.equal(flags([2010, 1, 1, 8, -1]).overflow, 4, 'minute -1 invalid');
+ test.equal(flags([2010, 1, 1, 8, 60]).overflow, 4, 'minute 60 invalid');
+
+ //seconds
+ test.equal(flags([2010, 1, 1, 8, 15, 12]).overflow, -1, 'second valid');
+ test.equal(flags([2010, 1, 1, 8, 15, 0]).overflow, -1, 'second 0 valid');
+ test.equal(flags([2010, 1, 1, 8, 15, -1]).overflow, 5, 'second -1 invalid');
+ test.equal(flags([2010, 1, 1, 8, 15, 60]).overflow, 5, 'second 60 invalid');
+
+ //milliseconds
+ test.equal(flags([2010, 1, 1, 8, 15, 12, 345]).overflow, -1, 'millisecond valid');
+ test.equal(flags([2010, 1, 1, 8, 15, 12, 0]).overflow, -1, 'millisecond 0 valid');
+ test.equal(flags([2010, 1, 1, 8, 15, 12, -1]).overflow, 6, 'millisecond -1 invalid');
+ test.equal(flags([2010, 1, 1, 8, 15, 12, 1000]).overflow, 6, 'millisecond 1000 invalid');
+
+ test.done();
+ },
+
+ 'overflow without format' : function (test) {
+
+ //months
+ test.equal(flags('2001-01', 'YYYY-MM').overflow, -1, 'month 1 valid');
+ test.equal(flags('2001-12', 'YYYY-MM').overflow, -1, 'month 12 valid');
+ test.equal(flags('2001-13', 'YYYY-MM').overflow, 1, 'month 13 invalid');
+
+ //days
+ test.equal(flags('2010-01-16', 'YYYY-MM-DD').overflow, -1, 'date 16 valid');
+ test.equal(flags('2010-01-0', 'YYYY-MM-DD').overflow, 2, 'date 0 invalid');
+ test.equal(flags('2010-01-32', 'YYYY-MM-DD').overflow, 2, 'date 32 invalid');
+ test.equal(flags('2012-02-29', 'YYYY-MM-DD').overflow, -1, 'date leap year valid');
+ test.equal(flags('2010-02-29', 'YYYY-MM-DD').overflow, 2, 'date leap year invalid');
+
+ //days of the year
+ test.equal(flags('2010 300', 'YYYY DDDD').overflow, -1, 'day 300 of year valid');
+ test.equal(flags('2010 365', 'YYYY DDDD').overflow, -1, 'day 365 of year valid');
+ test.equal(flags('2010 366', 'YYYY DDDD').overflow, 2, 'day 366 of year invalid');
++ test.equal(flags('2012 366', 'YYYY DDDD').overflow, -1, 'day 366 of leap year valid');
++ test.equal(flags('2012 367', 'YYYY DDDD').overflow, 2, 'day 367 of leap year invalid');
+
+ //hours
+ test.equal(flags('08', 'HH').overflow, -1, 'hour valid');
+ test.equal(flags('00', 'HH').overflow, -1, 'hour 0 valid');
+ test.equal(flags('24', 'HH').overflow, 3, 'hour 24 invalid');
+
+ //minutes
+ test.equal(flags('08:15', 'HH:mm').overflow, -1, 'minute valid');
+ test.equal(flags('08:00', 'HH:mm').overflow, -1, 'minute 0 valid');
+ test.equal(flags('08:60', 'HH:mm').overflow, 4, 'minute 60 invalid');
+
+ //seconds
+ test.equal(flags('08:15:12', 'HH:mm:ss').overflow, -1, 'second valid');
+ test.equal(flags('08:15:00', 'HH:mm:ss').overflow, -1, 'second 0 valid');
+ test.equal(flags('08:15:60', 'HH:mm:ss').overflow, 5, 'second 60 invalid');
+
+ //milliseconds
+ test.equal(flags('08:15:12:345', 'HH:mm:ss:SSSS').overflow, -1, 'millisecond valid');
+ test.equal(flags('08:15:12:000', 'HH:mm:ss:SSSS').overflow, -1, 'millisecond 0 valid');
+
+ //this is OK because we don't match the last digit, so it's 100 ms
+ test.equal(flags('08:15:12:1000', 'HH:mm:ss:SSSS').overflow, -1, 'millisecond 1000 actually valid');
+
+ test.done();
+ },
+
+ 'extra tokens' : function (test) {
+
+ test.deepEqual(flags('1982-05-25', 'YYYY-MM-DD').unusedTokens, [], 'nothing extra');
+ test.deepEqual(flags('1982-05', 'YYYY-MM-DD').unusedTokens, ['DD'], 'extra formatting token');
+ test.deepEqual(flags('1982', 'YYYY-MM-DD').unusedTokens, ['MM', 'DD'], 'multiple extra formatting tokens');
+ test.deepEqual(flags('1982-05', 'YYYY-MM-').unusedTokens, [], 'extra non-formatting token');
+ test.deepEqual(flags('1982-05-', 'YYYY-MM-DD').unusedTokens, ['DD'], 'non-extra non-formatting token');
+ test.deepEqual(flags('1982 05 1982', 'YYYY-MM-DD').unusedTokens, [], 'different non-formatting token');
+
+ test.done();
+ },
+
+ 'extra tokens strict' : function (test) {
+
+ test.deepEqual(flags('1982-05-25', 'YYYY-MM-DD', true).unusedTokens, [], 'nothing extra');
+ test.deepEqual(flags('1982-05', 'YYYY-MM-DD', true).unusedTokens, ['-', 'DD'], 'extra formatting token');
+ test.deepEqual(flags('1982', 'YYYY-MM-DD', true).unusedTokens, ['-', 'MM', '-', 'DD'], 'multiple extra formatting tokens');
+ test.deepEqual(flags('1982-05', 'YYYY-MM-', true).unusedTokens, ['-'], 'extra non-formatting token');
+ test.deepEqual(flags('1982-05-', 'YYYY-MM-DD', true).unusedTokens, ['DD'], 'non-extra non-formatting token');
+ test.deepEqual(flags('1982 05 1982', 'YYYY-MM-DD', true).unusedTokens, ['-', '-'], 'different non-formatting token');
+
+ test.done();
+ },
+
+ 'unused input' : function (test) {
+ test.deepEqual(flags('1982-05-25', 'YYYY-MM-DD').unusedInput, [], 'normal input');
+ test.deepEqual(flags('1982-05-25 this is more stuff', 'YYYY-MM-DD').unusedInput, [' this is more stuff'], 'trailing nonsense');
+ test.deepEqual(flags('1982-05-25 09:30', 'YYYY-MM-DD').unusedInput, [' 09:30'], ['trailing legit-looking input']);
+ test.deepEqual(flags('1982-05-25 some junk', 'YYYY-MM-DD [some junk]').unusedInput, [], 'junk that actually gets matched');
+ test.deepEqual(flags('stuff at beginning 1982-05-25', 'YYYY-MM-DD').unusedInput, ['stuff at beginning '], 'leading junk');
+ test.deepEqual(flags('junk 1982 more junk 05 yet more junk25', 'YYYY-MM-DD').unusedInput, ['junk ', ' more junk ', ' yet more junk'], 'interstitial junk');
+
+ test.done();
+ },
+
+ 'unused input strict' : function (test) {
+ test.deepEqual(flags('1982-05-25', 'YYYY-MM-DD', true).unusedInput, [], 'normal input');
+ test.deepEqual(flags('1982-05-25 this is more stuff', 'YYYY-MM-DD', true).unusedInput, [' this is more stuff'], 'trailing nonsense');
+ test.deepEqual(flags('1982-05-25 09:30', 'YYYY-MM-DD', true).unusedInput, [' 09:30'], ['trailing legit-looking input']);
+ test.deepEqual(flags('1982-05-25 some junk', 'YYYY-MM-DD [some junk]', true).unusedInput, [], 'junk that actually gets matched');
+ test.deepEqual(flags('stuff at beginning 1982-05-25', 'YYYY-MM-DD', true).unusedInput, ['stuff at beginning '], 'leading junk');
+ test.deepEqual(flags('junk 1982 more junk 05 yet more junk25', 'YYYY-MM-DD', true).unusedInput, ['junk ', ' more junk ', ' yet more junk'], 'interstitial junk');
+
+ test.done();
+ },
+
+ 'chars left over' : function (test) {
+ test.equal(flags('1982-05-25', 'YYYY-MM-DD').charsLeftOver, 0, 'normal input');
+ test.equal(flags('1982-05-25 this is more stuff', 'YYYY-MM-DD').charsLeftOver, ' this is more stuff'.length, 'trailing nonsense');
+ test.equal(flags('1982-05-25 09:30', 'YYYY-MM-DD').charsLeftOver, ' 09:30'.length, 'trailing legit-looking input');
+ test.equal(flags('stuff at beginning 1982-05-25', 'YYYY-MM-DD').charsLeftOver, 'stuff at beginning '.length, 'leading junk');
+ test.equal(flags('1982 junk 05 more junk25', 'YYYY-MM-DD').charsLeftOver, [' junk ', ' more junk'].join('').length, 'interstitial junk');
+ test.equal(flags('stuff at beginning 1982 junk 05 more junk25', 'YYYY-MM-DD').charsLeftOver, ['stuff at beginning ', ' junk ', ' more junk'].join('').length, 'leading and interstitial junk');
+
+ test.done();
+ },
+
+ 'empty' : function (test) {
+ test.equal(flags('1982-05-25', 'YYYY-MM-DD').empty, false, 'normal input');
+ test.equal(flags('nothing here', 'YYYY-MM-DD').empty, true, 'pure garbage');
+ test.equal(flags('junk but has the number 2000 in it', 'YYYY-MM-DD').empty, false, 'only mostly garbage');
+ test.equal(flags('', 'YYYY-MM-DD').empty, true, 'empty string');
+ test.equal(flags('', 'YYYY-MM-DD').empty, true, 'blank string');
+
+ test.done();
+ },
+
+ 'null' : function (test) {
+ test.equal(flags('1982-05-25', 'YYYY-MM-DD').nullInput, false, 'normal input');
+ test.equal(flags(null).nullInput, true, 'just null');
+ test.equal(flags(null, 'YYYY-MM-DD').nullInput, true, 'null with format');
+
+ test.done();
+ },
+
+ 'invalid month' : function (test) {
+ test.equal(flags('1982 May', 'YYYY MMMM').invalidMonth, null, 'normal input');
+ test.equal(flags('1982 Laser', 'YYYY MMMM').invalidMonth, 'Laser', 'bad month name');
+
+ test.done();
+ }
+ };