/node_modules/moment/src/lib/units/month.js

https://bitbucket.org/coleman333/smartsite · JavaScript · 290 lines · 238 code · 34 blank · 18 comment · 60 complexity · 02f2c0c16099fe74f8152e2735689956 MD5 · raw file

  1. import { get } from '../moment/get-set';
  2. import hasOwnProp from '../utils/has-own-prop';
  3. import { addFormatToken } from '../format/format';
  4. import { addUnitAlias } from './aliases';
  5. import { addUnitPriority } from './priorities';
  6. import { addRegexToken, match1to2, match2, matchWord, regexEscape } from '../parse/regex';
  7. import { addParseToken } from '../parse/token';
  8. import { hooks } from '../utils/hooks';
  9. import { MONTH } from './constants';
  10. import toInt from '../utils/to-int';
  11. import isArray from '../utils/is-array';
  12. import isNumber from '../utils/is-number';
  13. import mod from '../utils/mod';
  14. import indexOf from '../utils/index-of';
  15. import { createUTC } from '../create/utc';
  16. import getParsingFlags from '../create/parsing-flags';
  17. import { isLeapYear } from '../units/year';
  18. export function daysInMonth(year, month) {
  19. if (isNaN(year) || isNaN(month)) {
  20. return NaN;
  21. }
  22. var modMonth = mod(month, 12);
  23. year += (month - modMonth) / 12;
  24. return modMonth === 1 ? (isLeapYear(year) ? 29 : 28) : (31 - modMonth % 7 % 2);
  25. }
  26. // FORMATTING
  27. addFormatToken('M', ['MM', 2], 'Mo', function () {
  28. return this.month() + 1;
  29. });
  30. addFormatToken('MMM', 0, 0, function (format) {
  31. return this.localeData().monthsShort(this, format);
  32. });
  33. addFormatToken('MMMM', 0, 0, function (format) {
  34. return this.localeData().months(this, format);
  35. });
  36. // ALIASES
  37. addUnitAlias('month', 'M');
  38. // PRIORITY
  39. addUnitPriority('month', 8);
  40. // PARSING
  41. addRegexToken('M', match1to2);
  42. addRegexToken('MM', match1to2, match2);
  43. addRegexToken('MMM', function (isStrict, locale) {
  44. return locale.monthsShortRegex(isStrict);
  45. });
  46. addRegexToken('MMMM', function (isStrict, locale) {
  47. return locale.monthsRegex(isStrict);
  48. });
  49. addParseToken(['M', 'MM'], function (input, array) {
  50. array[MONTH] = toInt(input) - 1;
  51. });
  52. addParseToken(['MMM', 'MMMM'], function (input, array, config, token) {
  53. var month = config._locale.monthsParse(input, token, config._strict);
  54. // if we didn't find a month name, mark the date as invalid.
  55. if (month != null) {
  56. array[MONTH] = month;
  57. } else {
  58. getParsingFlags(config).invalidMonth = input;
  59. }
  60. });
  61. // LOCALES
  62. var MONTHS_IN_FORMAT = /D[oD]?(\[[^\[\]]*\]|\s)+MMMM?/;
  63. export var defaultLocaleMonths = 'January_February_March_April_May_June_July_August_September_October_November_December'.split('_');
  64. export function localeMonths (m, format) {
  65. if (!m) {
  66. return isArray(this._months) ? this._months :
  67. this._months['standalone'];
  68. }
  69. return isArray(this._months) ? this._months[m.month()] :
  70. this._months[(this._months.isFormat || MONTHS_IN_FORMAT).test(format) ? 'format' : 'standalone'][m.month()];
  71. }
  72. export var defaultLocaleMonthsShort = 'Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec'.split('_');
  73. export function localeMonthsShort (m, format) {
  74. if (!m) {
  75. return isArray(this._monthsShort) ? this._monthsShort :
  76. this._monthsShort['standalone'];
  77. }
  78. return isArray(this._monthsShort) ? this._monthsShort[m.month()] :
  79. this._monthsShort[MONTHS_IN_FORMAT.test(format) ? 'format' : 'standalone'][m.month()];
  80. }
  81. function handleStrictParse(monthName, format, strict) {
  82. var i, ii, mom, llc = monthName.toLocaleLowerCase();
  83. if (!this._monthsParse) {
  84. // this is not used
  85. this._monthsParse = [];
  86. this._longMonthsParse = [];
  87. this._shortMonthsParse = [];
  88. for (i = 0; i < 12; ++i) {
  89. mom = createUTC([2000, i]);
  90. this._shortMonthsParse[i] = this.monthsShort(mom, '').toLocaleLowerCase();
  91. this._longMonthsParse[i] = this.months(mom, '').toLocaleLowerCase();
  92. }
  93. }
  94. if (strict) {
  95. if (format === 'MMM') {
  96. ii = indexOf.call(this._shortMonthsParse, llc);
  97. return ii !== -1 ? ii : null;
  98. } else {
  99. ii = indexOf.call(this._longMonthsParse, llc);
  100. return ii !== -1 ? ii : null;
  101. }
  102. } else {
  103. if (format === 'MMM') {
  104. ii = indexOf.call(this._shortMonthsParse, llc);
  105. if (ii !== -1) {
  106. return ii;
  107. }
  108. ii = indexOf.call(this._longMonthsParse, llc);
  109. return ii !== -1 ? ii : null;
  110. } else {
  111. ii = indexOf.call(this._longMonthsParse, llc);
  112. if (ii !== -1) {
  113. return ii;
  114. }
  115. ii = indexOf.call(this._shortMonthsParse, llc);
  116. return ii !== -1 ? ii : null;
  117. }
  118. }
  119. }
  120. export function localeMonthsParse (monthName, format, strict) {
  121. var i, mom, regex;
  122. if (this._monthsParseExact) {
  123. return handleStrictParse.call(this, monthName, format, strict);
  124. }
  125. if (!this._monthsParse) {
  126. this._monthsParse = [];
  127. this._longMonthsParse = [];
  128. this._shortMonthsParse = [];
  129. }
  130. // TODO: add sorting
  131. // Sorting makes sure if one month (or abbr) is a prefix of another
  132. // see sorting in computeMonthsParse
  133. for (i = 0; i < 12; i++) {
  134. // make the regex if we don't have it already
  135. mom = createUTC([2000, i]);
  136. if (strict && !this._longMonthsParse[i]) {
  137. this._longMonthsParse[i] = new RegExp('^' + this.months(mom, '').replace('.', '') + '$', 'i');
  138. this._shortMonthsParse[i] = new RegExp('^' + this.monthsShort(mom, '').replace('.', '') + '$', 'i');
  139. }
  140. if (!strict && !this._monthsParse[i]) {
  141. regex = '^' + this.months(mom, '') + '|^' + this.monthsShort(mom, '');
  142. this._monthsParse[i] = new RegExp(regex.replace('.', ''), 'i');
  143. }
  144. // test the regex
  145. if (strict && format === 'MMMM' && this._longMonthsParse[i].test(monthName)) {
  146. return i;
  147. } else if (strict && format === 'MMM' && this._shortMonthsParse[i].test(monthName)) {
  148. return i;
  149. } else if (!strict && this._monthsParse[i].test(monthName)) {
  150. return i;
  151. }
  152. }
  153. }
  154. // MOMENTS
  155. export function setMonth (mom, value) {
  156. var dayOfMonth;
  157. if (!mom.isValid()) {
  158. // No op
  159. return mom;
  160. }
  161. if (typeof value === 'string') {
  162. if (/^\d+$/.test(value)) {
  163. value = toInt(value);
  164. } else {
  165. value = mom.localeData().monthsParse(value);
  166. // TODO: Another silent failure?
  167. if (!isNumber(value)) {
  168. return mom;
  169. }
  170. }
  171. }
  172. dayOfMonth = Math.min(mom.date(), daysInMonth(mom.year(), value));
  173. mom._d['set' + (mom._isUTC ? 'UTC' : '') + 'Month'](value, dayOfMonth);
  174. return mom;
  175. }
  176. export function getSetMonth (value) {
  177. if (value != null) {
  178. setMonth(this, value);
  179. hooks.updateOffset(this, true);
  180. return this;
  181. } else {
  182. return get(this, 'Month');
  183. }
  184. }
  185. export function getDaysInMonth () {
  186. return daysInMonth(this.year(), this.month());
  187. }
  188. var defaultMonthsShortRegex = matchWord;
  189. export function monthsShortRegex (isStrict) {
  190. if (this._monthsParseExact) {
  191. if (!hasOwnProp(this, '_monthsRegex')) {
  192. computeMonthsParse.call(this);
  193. }
  194. if (isStrict) {
  195. return this._monthsShortStrictRegex;
  196. } else {
  197. return this._monthsShortRegex;
  198. }
  199. } else {
  200. if (!hasOwnProp(this, '_monthsShortRegex')) {
  201. this._monthsShortRegex = defaultMonthsShortRegex;
  202. }
  203. return this._monthsShortStrictRegex && isStrict ?
  204. this._monthsShortStrictRegex : this._monthsShortRegex;
  205. }
  206. }
  207. var defaultMonthsRegex = matchWord;
  208. export function monthsRegex (isStrict) {
  209. if (this._monthsParseExact) {
  210. if (!hasOwnProp(this, '_monthsRegex')) {
  211. computeMonthsParse.call(this);
  212. }
  213. if (isStrict) {
  214. return this._monthsStrictRegex;
  215. } else {
  216. return this._monthsRegex;
  217. }
  218. } else {
  219. if (!hasOwnProp(this, '_monthsRegex')) {
  220. this._monthsRegex = defaultMonthsRegex;
  221. }
  222. return this._monthsStrictRegex && isStrict ?
  223. this._monthsStrictRegex : this._monthsRegex;
  224. }
  225. }
  226. function computeMonthsParse () {
  227. function cmpLenRev(a, b) {
  228. return b.length - a.length;
  229. }
  230. var shortPieces = [], longPieces = [], mixedPieces = [],
  231. i, mom;
  232. for (i = 0; i < 12; i++) {
  233. // make the regex if we don't have it already
  234. mom = createUTC([2000, i]);
  235. shortPieces.push(this.monthsShort(mom, ''));
  236. longPieces.push(this.months(mom, ''));
  237. mixedPieces.push(this.months(mom, ''));
  238. mixedPieces.push(this.monthsShort(mom, ''));
  239. }
  240. // Sorting makes sure if one month (or abbr) is a prefix of another it
  241. // will match the longer piece.
  242. shortPieces.sort(cmpLenRev);
  243. longPieces.sort(cmpLenRev);
  244. mixedPieces.sort(cmpLenRev);
  245. for (i = 0; i < 12; i++) {
  246. shortPieces[i] = regexEscape(shortPieces[i]);
  247. longPieces[i] = regexEscape(longPieces[i]);
  248. }
  249. for (i = 0; i < 24; i++) {
  250. mixedPieces[i] = regexEscape(mixedPieces[i]);
  251. }
  252. this._monthsRegex = new RegExp('^(' + mixedPieces.join('|') + ')', 'i');
  253. this._monthsShortRegex = this._monthsRegex;
  254. this._monthsStrictRegex = new RegExp('^(' + longPieces.join('|') + ')', 'i');
  255. this._monthsShortStrictRegex = new RegExp('^(' + shortPieces.join('|') + ')', 'i');
  256. }