From: Iskren Chernev Date: Wed, 6 Jan 2016 23:44:36 +0000 (+0200) Subject: Fix months parsing for stranger locales X-Git-Tag: 2.11.1~4^2~2 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=6e0b7a9363d4f52ef819f8fa4e6fac06f4ce1d8b;p=thirdparty%2Fmoment.git Fix months parsing for stranger locales --- diff --git a/src/lib/locale/prototype.js b/src/lib/locale/prototype.js index ed02d4f3b..6c59d5edb 100644 --- a/src/lib/locale/prototype.js +++ b/src/lib/locale/prototype.js @@ -30,14 +30,22 @@ proto.set = set; import { localeMonthsParse, defaultLocaleMonths, localeMonths, - defaultLocaleMonthsShort, localeMonthsShort + defaultLocaleMonthsShort, localeMonthsShort, + defaultMonthsRegex, monthsRegex, + defaultMonthsShortRegex, monthsShortRegex, + computeMonthsParse } from '../units/month'; -proto.months = localeMonths; -proto._months = defaultLocaleMonths; -proto.monthsShort = localeMonthsShort; -proto._monthsShort = defaultLocaleMonthsShort; -proto.monthsParse = localeMonthsParse; +proto.months = localeMonths; +proto._months = defaultLocaleMonths; +proto.monthsShort = localeMonthsShort; +proto._monthsShort = defaultLocaleMonthsShort; +proto.monthsParse = localeMonthsParse; +proto._monthsRegex = defaultMonthsRegex; +proto.monthsRegex = monthsRegex; +proto._monthsShortRegex = defaultMonthsShortRegex; +proto.monthsShortRegex = monthsShortRegex; +proto._computeMonthsParse = computeMonthsParse; // Week import { localeWeek, defaultLocaleWeek, localeFirstDayOfYear, localeFirstDayOfWeek } from '../units/week'; diff --git a/src/lib/parse/regex.js b/src/lib/parse/regex.js index a168de6f2..b1dc7529e 100644 --- a/src/lib/parse/regex.js +++ b/src/lib/parse/regex.js @@ -20,7 +20,7 @@ export var matchTimestamp = /[+-]?\d+(\.\d{1,3})?/; // 123456789 123456789.123 // any word (or two) characters or numbers including two/three word month in arabic. // includes scottish gaelic two word and hyphenated months -export var matchWord = /[0-9]*(a[mn]\s?)?['a-z\u00A0-\u05FF\u0700-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF\-]+|[\u0600-\u06FF\/]+(\s*?[\u0600-\u06FF]+){1,2}/i; +export var matchWord = /[0-9]*['a-z\u00A0-\u05FF\u0700-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]+|[\u0600-\u06FF\/]+(\s*?[\u0600-\u06FF]+){1,2}/i; import hasOwnProp from '../utils/has-own-prop'; @@ -29,7 +29,7 @@ import isFunction from '../utils/is-function'; var regexes = {}; export function addRegexToken (token, regex, strictRegex) { - regexes[token] = isFunction(regex) ? regex : function (isStrict) { + regexes[token] = isFunction(regex) ? regex : function (isStrict, localeData) { return (isStrict && strictRegex) ? strictRegex : regex; }; } @@ -44,7 +44,11 @@ export function getParseRegexForToken (token, config) { // Code from http://stackoverflow.com/questions/3561493/is-there-a-regexp-escape-function-in-javascript function unescapeFormat(s) { - return s.replace('\\', '').replace(/\\(\[)|\\(\])|\[([^\]\[]*)\]|\\(.)/g, function (matched, p1, p2, p3, p4) { + return regexEscape(s.replace('\\', '').replace(/\\(\[)|\\(\])|\[([^\]\[]*)\]|\\(.)/g, function (matched, p1, p2, p3, p4) { return p1 || p2 || p3 || p4; - }).replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&'); + })); +} + +export function regexEscape(s) { + return s.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&'); } diff --git a/src/lib/units/month.js b/src/lib/units/month.js index 18e42cff8..7d3234717 100644 --- a/src/lib/units/month.js +++ b/src/lib/units/month.js @@ -1,7 +1,8 @@ import { get } from '../moment/get-set'; +import hasOwnProp from '../utils/has-own-prop'; import { addFormatToken } from '../format/format'; import { addUnitAlias } from './aliases'; -import { addRegexToken, match1to2, match2, matchWord } from '../parse/regex'; +import { addRegexToken, match1to2, match2, matchWord, regexEscape } from '../parse/regex'; import { addParseToken } from '../parse/token'; import { hooks } from '../utils/hooks'; import { MONTH } from './constants'; @@ -36,8 +37,12 @@ addUnitAlias('month', 'M'); addRegexToken('M', match1to2); addRegexToken('MM', match1to2, match2); -addRegexToken('MMM', matchWord); -addRegexToken('MMMM', matchWord); +addRegexToken('MMM', function (isStrict, locale) { + return locale.monthsShortRegex(isStrict); +}); +addRegexToken('MMMM', function (isStrict, locale) { + return locale.monthsRegex(isStrict); +}); addParseToken(['M', 'MM'], function (input, array) { array[MONTH] = toInt(input) - 1; @@ -136,3 +141,54 @@ export function getSetMonth (value) { export function getDaysInMonth () { return daysInMonth(this.year(), this.month()); } + +export var defaultMonthsShortRegex = matchWord; +export function monthsShortRegex (isStrict) { + if (this._monthsParseExact) { + this._computeMonthsParse(); + if (isStrict) { + return this._monthsShortStrictRegex; + } else { + return this._monthsShortRegex; + } + } else { + return this._monthsShortStrictRegex && isStrict ? + this._monthsShortStrictRegex : this._monthsShortRegex; + } +} + +export var defaultMonthsRegex = matchWord; +export function monthsRegex (isStrict) { + if (this._monthsParseExact) { + this._computeMonthsParse(); + if (isStrict) { + return this._monthsStrictRegex; + } else { + return this._monthsRegex; + } + } else { + return this._monthsStrictRegex && isStrict ? + this._monthsStrictRegex : this._monthsRegex; + } +} + +export function computeMonthsParse () { + if (!hasOwnProp(this, '_monthsRegex')) { + var shortOnly = '', longOnly = '', mixed = '', i, mom; + for (i = 0; i < 12; i++) { + // make the regex if we don't have it already + mom = createUTC([2000, i]); + shortOnly += '|' + regexEscape(this.monthsShort(mom, '')); + longOnly += '|' + regexEscape(this.months(mom, '')); + mixed += '|' + regexEscape(this.months(mom, '')) + '|' + regexEscape(this.monthsShort(mom, '')); + } + shortOnly = shortOnly.substr(1); + longOnly = longOnly.substr(1); + mixed = mixed.substr(1); + + this._monthsRegex = new RegExp('^(' + mixed + ')', 'i'); + this._monthsShortRegex = this._monthsRegex; + this._monthsStrictRegex = new RegExp('^(' + longOnly + ')$', 'i'); + this._monthsShortStrictRegex = new RegExp('^(' + shortOnly + ')$', 'i'); + } +} diff --git a/src/locale/gd.js b/src/locale/gd.js index d4fdff180..b7689f98a 100644 --- a/src/locale/gd.js +++ b/src/locale/gd.js @@ -5,18 +5,7 @@ import moment from '../moment'; var months = [ - 'Am Faoilleach', - 'An Gearran', - 'Am Màrt', - 'An Giblean', - 'An Cèitean', - 'An t-Ògmhios', - 'An t-Iuchar', - 'An Lùnastal', - 'An t-Sultain', - 'An Dàmhair', - 'An t-Samhain', - 'An Dùbhlachd' + 'Am Faoilleach', 'An Gearran', 'Am Màrt', 'An Giblean', 'An Cèitean', 'An t-Ògmhios', 'An t-Iuchar', 'An Lùnastal', 'An t-Sultain', 'An Dàmhair', 'An t-Samhain', 'An Dùbhlachd' ]; var monthsShort = ['Faoi', 'Gear', 'Màrt', 'Gibl', 'Cèit', 'Ògmh', 'Iuch', 'Lùn', 'Sult', 'Dàmh', 'Samh', 'Dùbh']; @@ -30,6 +19,7 @@ var weekdaysMin = ['Dò', 'Lu', 'Mà', 'Ci', 'Ar', 'Ha', 'Sa']; export default moment.defineLocale('gd', { months : months, monthsShort : monthsShort, + monthsParseExact : true, weekdays : weekdays, weekdaysShort : weekdaysShort, weekdaysMin : weekdaysMin, diff --git a/src/test/locale/gd.js b/src/test/locale/gd.js index 583d574dd..b3d468fd6 100644 --- a/src/test/locale/gd.js +++ b/src/test/locale/gd.js @@ -19,7 +19,7 @@ var months = [ test('parse', function (assert) { function equalTest(monthName, monthFormat, monthNum) { - assert.equal(moment(monthName, monthFormat).month(), monthNum, monthName + ' should be month ' + monthNum + 1); + assert.equal(moment(monthName, monthFormat).month(), monthNum, monthName + ' should be month ' + (monthNum + 1)); } for (var i = 0; i < 12; i++) {