index.js 43 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503
  1. import getUTCWeekYear from "../../../_lib/getUTCWeekYear/index.js";
  2. import setUTCDay from "../../../_lib/setUTCDay/index.js";
  3. import setUTCISODay from "../../../_lib/setUTCISODay/index.js";
  4. import setUTCISOWeek from "../../../_lib/setUTCISOWeek/index.js";
  5. import setUTCWeek from "../../../_lib/setUTCWeek/index.js";
  6. import startOfUTCISOWeek from "../../../_lib/startOfUTCISOWeek/index.js";
  7. import startOfUTCWeek from "../../../_lib/startOfUTCWeek/index.js";
  8. var MILLISECONDS_IN_HOUR = 3600000;
  9. var MILLISECONDS_IN_MINUTE = 60000;
  10. var MILLISECONDS_IN_SECOND = 1000;
  11. var numericPatterns = {
  12. month: /^(1[0-2]|0?\d)/,
  13. // 0 to 12
  14. date: /^(3[0-1]|[0-2]?\d)/,
  15. // 0 to 31
  16. dayOfYear: /^(36[0-6]|3[0-5]\d|[0-2]?\d?\d)/,
  17. // 0 to 366
  18. week: /^(5[0-3]|[0-4]?\d)/,
  19. // 0 to 53
  20. hour23h: /^(2[0-3]|[0-1]?\d)/,
  21. // 0 to 23
  22. hour24h: /^(2[0-4]|[0-1]?\d)/,
  23. // 0 to 24
  24. hour11h: /^(1[0-1]|0?\d)/,
  25. // 0 to 11
  26. hour12h: /^(1[0-2]|0?\d)/,
  27. // 0 to 12
  28. minute: /^[0-5]?\d/,
  29. // 0 to 59
  30. second: /^[0-5]?\d/,
  31. // 0 to 59
  32. singleDigit: /^\d/,
  33. // 0 to 9
  34. twoDigits: /^\d{1,2}/,
  35. // 0 to 99
  36. threeDigits: /^\d{1,3}/,
  37. // 0 to 999
  38. fourDigits: /^\d{1,4}/,
  39. // 0 to 9999
  40. anyDigitsSigned: /^-?\d+/,
  41. singleDigitSigned: /^-?\d/,
  42. // 0 to 9, -0 to -9
  43. twoDigitsSigned: /^-?\d{1,2}/,
  44. // 0 to 99, -0 to -99
  45. threeDigitsSigned: /^-?\d{1,3}/,
  46. // 0 to 999, -0 to -999
  47. fourDigitsSigned: /^-?\d{1,4}/ // 0 to 9999, -0 to -9999
  48. };
  49. var timezonePatterns = {
  50. basicOptionalMinutes: /^([+-])(\d{2})(\d{2})?|Z/,
  51. basic: /^([+-])(\d{2})(\d{2})|Z/,
  52. basicOptionalSeconds: /^([+-])(\d{2})(\d{2})((\d{2}))?|Z/,
  53. extended: /^([+-])(\d{2}):(\d{2})|Z/,
  54. extendedOptionalSeconds: /^([+-])(\d{2}):(\d{2})(:(\d{2}))?|Z/
  55. };
  56. function parseNumericPattern(pattern, string, valueCallback) {
  57. var matchResult = string.match(pattern);
  58. if (!matchResult) {
  59. return null;
  60. }
  61. var value = parseInt(matchResult[0], 10);
  62. return {
  63. value: valueCallback ? valueCallback(value) : value,
  64. rest: string.slice(matchResult[0].length)
  65. };
  66. }
  67. function parseTimezonePattern(pattern, string) {
  68. var matchResult = string.match(pattern);
  69. if (!matchResult) {
  70. return null;
  71. } // Input is 'Z'
  72. if (matchResult[0] === 'Z') {
  73. return {
  74. value: 0,
  75. rest: string.slice(1)
  76. };
  77. }
  78. var sign = matchResult[1] === '+' ? 1 : -1;
  79. var hours = matchResult[2] ? parseInt(matchResult[2], 10) : 0;
  80. var minutes = matchResult[3] ? parseInt(matchResult[3], 10) : 0;
  81. var seconds = matchResult[5] ? parseInt(matchResult[5], 10) : 0;
  82. return {
  83. value: sign * (hours * MILLISECONDS_IN_HOUR + minutes * MILLISECONDS_IN_MINUTE + seconds * MILLISECONDS_IN_SECOND),
  84. rest: string.slice(matchResult[0].length)
  85. };
  86. }
  87. function parseAnyDigitsSigned(string, valueCallback) {
  88. return parseNumericPattern(numericPatterns.anyDigitsSigned, string, valueCallback);
  89. }
  90. function parseNDigits(n, string, valueCallback) {
  91. switch (n) {
  92. case 1:
  93. return parseNumericPattern(numericPatterns.singleDigit, string, valueCallback);
  94. case 2:
  95. return parseNumericPattern(numericPatterns.twoDigits, string, valueCallback);
  96. case 3:
  97. return parseNumericPattern(numericPatterns.threeDigits, string, valueCallback);
  98. case 4:
  99. return parseNumericPattern(numericPatterns.fourDigits, string, valueCallback);
  100. default:
  101. return parseNumericPattern(new RegExp('^\\d{1,' + n + '}'), string, valueCallback);
  102. }
  103. }
  104. function parseNDigitsSigned(n, string, valueCallback) {
  105. switch (n) {
  106. case 1:
  107. return parseNumericPattern(numericPatterns.singleDigitSigned, string, valueCallback);
  108. case 2:
  109. return parseNumericPattern(numericPatterns.twoDigitsSigned, string, valueCallback);
  110. case 3:
  111. return parseNumericPattern(numericPatterns.threeDigitsSigned, string, valueCallback);
  112. case 4:
  113. return parseNumericPattern(numericPatterns.fourDigitsSigned, string, valueCallback);
  114. default:
  115. return parseNumericPattern(new RegExp('^-?\\d{1,' + n + '}'), string, valueCallback);
  116. }
  117. }
  118. function dayPeriodEnumToHours(enumValue) {
  119. switch (enumValue) {
  120. case 'morning':
  121. return 4;
  122. case 'evening':
  123. return 17;
  124. case 'pm':
  125. case 'noon':
  126. case 'afternoon':
  127. return 12;
  128. case 'am':
  129. case 'midnight':
  130. case 'night':
  131. default:
  132. return 0;
  133. }
  134. }
  135. function normalizeTwoDigitYear(twoDigitYear, currentYear) {
  136. var isCommonEra = currentYear > 0; // Absolute number of the current year:
  137. // 1 -> 1 AC
  138. // 0 -> 1 BC
  139. // -1 -> 2 BC
  140. var absCurrentYear = isCommonEra ? currentYear : 1 - currentYear;
  141. var result;
  142. if (absCurrentYear <= 50) {
  143. result = twoDigitYear || 100;
  144. } else {
  145. var rangeEnd = absCurrentYear + 50;
  146. var rangeEndCentury = Math.floor(rangeEnd / 100) * 100;
  147. var isPreviousCentury = twoDigitYear >= rangeEnd % 100;
  148. result = twoDigitYear + rangeEndCentury - (isPreviousCentury ? 100 : 0);
  149. }
  150. return isCommonEra ? result : 1 - result;
  151. }
  152. var DAYS_IN_MONTH = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
  153. var DAYS_IN_MONTH_LEAP_YEAR = [31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]; // User for validation
  154. function isLeapYearIndex(year) {
  155. return year % 400 === 0 || year % 4 === 0 && year % 100 !== 0;
  156. }
  157. /*
  158. * | | Unit | | Unit |
  159. * |-----|--------------------------------|-----|--------------------------------|
  160. * | a | AM, PM | A* | Milliseconds in day |
  161. * | b | AM, PM, noon, midnight | B | Flexible day period |
  162. * | c | Stand-alone local day of week | C* | Localized hour w/ day period |
  163. * | d | Day of month | D | Day of year |
  164. * | e | Local day of week | E | Day of week |
  165. * | f | | F* | Day of week in month |
  166. * | g* | Modified Julian day | G | Era |
  167. * | h | Hour [1-12] | H | Hour [0-23] |
  168. * | i! | ISO day of week | I! | ISO week of year |
  169. * | j* | Localized hour w/ day period | J* | Localized hour w/o day period |
  170. * | k | Hour [1-24] | K | Hour [0-11] |
  171. * | l* | (deprecated) | L | Stand-alone month |
  172. * | m | Minute | M | Month |
  173. * | n | | N | |
  174. * | o! | Ordinal number modifier | O* | Timezone (GMT) |
  175. * | p | | P | |
  176. * | q | Stand-alone quarter | Q | Quarter |
  177. * | r* | Related Gregorian year | R! | ISO week-numbering year |
  178. * | s | Second | S | Fraction of second |
  179. * | t! | Seconds timestamp | T! | Milliseconds timestamp |
  180. * | u | Extended year | U* | Cyclic year |
  181. * | v* | Timezone (generic non-locat.) | V* | Timezone (location) |
  182. * | w | Local week of year | W* | Week of month |
  183. * | x | Timezone (ISO-8601 w/o Z) | X | Timezone (ISO-8601) |
  184. * | y | Year (abs) | Y | Local week-numbering year |
  185. * | z* | Timezone (specific non-locat.) | Z* | Timezone (aliases) |
  186. *
  187. * Letters marked by * are not implemented but reserved by Unicode standard.
  188. *
  189. * Letters marked by ! are non-standard, but implemented by date-fns:
  190. * - `o` modifies the previous token to turn it into an ordinal (see `parse` docs)
  191. * - `i` is ISO day of week. For `i` and `ii` is returns numeric ISO week days,
  192. * i.e. 7 for Sunday, 1 for Monday, etc.
  193. * - `I` is ISO week of year, as opposed to `w` which is local week of year.
  194. * - `R` is ISO week-numbering year, as opposed to `Y` which is local week-numbering year.
  195. * `R` is supposed to be used in conjunction with `I` and `i`
  196. * for universal ISO week-numbering date, whereas
  197. * `Y` is supposed to be used in conjunction with `w` and `e`
  198. * for week-numbering date specific to the locale.
  199. */
  200. var parsers = {
  201. // Era
  202. G: {
  203. priority: 140,
  204. parse: function (string, token, match, _options) {
  205. switch (token) {
  206. // AD, BC
  207. case 'G':
  208. case 'GG':
  209. case 'GGG':
  210. return match.era(string, {
  211. width: 'abbreviated'
  212. }) || match.era(string, {
  213. width: 'narrow'
  214. });
  215. // A, B
  216. case 'GGGGG':
  217. return match.era(string, {
  218. width: 'narrow'
  219. });
  220. // Anno Domini, Before Christ
  221. case 'GGGG':
  222. default:
  223. return match.era(string, {
  224. width: 'wide'
  225. }) || match.era(string, {
  226. width: 'abbreviated'
  227. }) || match.era(string, {
  228. width: 'narrow'
  229. });
  230. }
  231. },
  232. set: function (date, flags, value, _options) {
  233. flags.era = value;
  234. date.setUTCFullYear(value, 0, 1);
  235. date.setUTCHours(0, 0, 0, 0);
  236. return date;
  237. },
  238. incompatibleTokens: ['R', 'u', 't', 'T']
  239. },
  240. // Year
  241. y: {
  242. // From http://www.unicode.org/reports/tr35/tr35-31/tr35-dates.html#Date_Format_Patterns
  243. // | Year | y | yy | yyy | yyyy | yyyyy |
  244. // |----------|-------|----|-------|-------|-------|
  245. // | AD 1 | 1 | 01 | 001 | 0001 | 00001 |
  246. // | AD 12 | 12 | 12 | 012 | 0012 | 00012 |
  247. // | AD 123 | 123 | 23 | 123 | 0123 | 00123 |
  248. // | AD 1234 | 1234 | 34 | 1234 | 1234 | 01234 |
  249. // | AD 12345 | 12345 | 45 | 12345 | 12345 | 12345 |
  250. priority: 130,
  251. parse: function (string, token, match, _options) {
  252. var valueCallback = function (year) {
  253. return {
  254. year: year,
  255. isTwoDigitYear: token === 'yy'
  256. };
  257. };
  258. switch (token) {
  259. case 'y':
  260. return parseNDigits(4, string, valueCallback);
  261. case 'yo':
  262. return match.ordinalNumber(string, {
  263. unit: 'year',
  264. valueCallback: valueCallback
  265. });
  266. default:
  267. return parseNDigits(token.length, string, valueCallback);
  268. }
  269. },
  270. validate: function (_date, value, _options) {
  271. return value.isTwoDigitYear || value.year > 0;
  272. },
  273. set: function (date, flags, value, _options) {
  274. var currentYear = date.getUTCFullYear();
  275. if (value.isTwoDigitYear) {
  276. var normalizedTwoDigitYear = normalizeTwoDigitYear(value.year, currentYear);
  277. date.setUTCFullYear(normalizedTwoDigitYear, 0, 1);
  278. date.setUTCHours(0, 0, 0, 0);
  279. return date;
  280. }
  281. var year = !('era' in flags) || flags.era === 1 ? value.year : 1 - value.year;
  282. date.setUTCFullYear(year, 0, 1);
  283. date.setUTCHours(0, 0, 0, 0);
  284. return date;
  285. },
  286. incompatibleTokens: ['Y', 'R', 'u', 'w', 'I', 'i', 'e', 'c', 't', 'T']
  287. },
  288. // Local week-numbering year
  289. Y: {
  290. priority: 130,
  291. parse: function (string, token, match, _options) {
  292. var valueCallback = function (year) {
  293. return {
  294. year: year,
  295. isTwoDigitYear: token === 'YY'
  296. };
  297. };
  298. switch (token) {
  299. case 'Y':
  300. return parseNDigits(4, string, valueCallback);
  301. case 'Yo':
  302. return match.ordinalNumber(string, {
  303. unit: 'year',
  304. valueCallback: valueCallback
  305. });
  306. default:
  307. return parseNDigits(token.length, string, valueCallback);
  308. }
  309. },
  310. validate: function (_date, value, _options) {
  311. return value.isTwoDigitYear || value.year > 0;
  312. },
  313. set: function (date, flags, value, options) {
  314. var currentYear = getUTCWeekYear(date, options);
  315. if (value.isTwoDigitYear) {
  316. var normalizedTwoDigitYear = normalizeTwoDigitYear(value.year, currentYear);
  317. date.setUTCFullYear(normalizedTwoDigitYear, 0, options.firstWeekContainsDate);
  318. date.setUTCHours(0, 0, 0, 0);
  319. return startOfUTCWeek(date, options);
  320. }
  321. var year = !('era' in flags) || flags.era === 1 ? value.year : 1 - value.year;
  322. date.setUTCFullYear(year, 0, options.firstWeekContainsDate);
  323. date.setUTCHours(0, 0, 0, 0);
  324. return startOfUTCWeek(date, options);
  325. },
  326. incompatibleTokens: ['y', 'R', 'u', 'Q', 'q', 'M', 'L', 'I', 'd', 'D', 'i', 't', 'T']
  327. },
  328. // ISO week-numbering year
  329. R: {
  330. priority: 130,
  331. parse: function (string, token, _match, _options) {
  332. if (token === 'R') {
  333. return parseNDigitsSigned(4, string);
  334. }
  335. return parseNDigitsSigned(token.length, string);
  336. },
  337. set: function (_date, _flags, value, _options) {
  338. var firstWeekOfYear = new Date(0);
  339. firstWeekOfYear.setUTCFullYear(value, 0, 4);
  340. firstWeekOfYear.setUTCHours(0, 0, 0, 0);
  341. return startOfUTCISOWeek(firstWeekOfYear);
  342. },
  343. incompatibleTokens: ['G', 'y', 'Y', 'u', 'Q', 'q', 'M', 'L', 'w', 'd', 'D', 'e', 'c', 't', 'T']
  344. },
  345. // Extended year
  346. u: {
  347. priority: 130,
  348. parse: function (string, token, _match, _options) {
  349. if (token === 'u') {
  350. return parseNDigitsSigned(4, string);
  351. }
  352. return parseNDigitsSigned(token.length, string);
  353. },
  354. set: function (date, _flags, value, _options) {
  355. date.setUTCFullYear(value, 0, 1);
  356. date.setUTCHours(0, 0, 0, 0);
  357. return date;
  358. },
  359. incompatibleTokens: ['G', 'y', 'Y', 'R', 'w', 'I', 'i', 'e', 'c', 't', 'T']
  360. },
  361. // Quarter
  362. Q: {
  363. priority: 120,
  364. parse: function (string, token, match, _options) {
  365. switch (token) {
  366. // 1, 2, 3, 4
  367. case 'Q':
  368. case 'QQ':
  369. // 01, 02, 03, 04
  370. return parseNDigits(token.length, string);
  371. // 1st, 2nd, 3rd, 4th
  372. case 'Qo':
  373. return match.ordinalNumber(string, {
  374. unit: 'quarter'
  375. });
  376. // Q1, Q2, Q3, Q4
  377. case 'QQQ':
  378. return match.quarter(string, {
  379. width: 'abbreviated',
  380. context: 'formatting'
  381. }) || match.quarter(string, {
  382. width: 'narrow',
  383. context: 'formatting'
  384. });
  385. // 1, 2, 3, 4 (narrow quarter; could be not numerical)
  386. case 'QQQQQ':
  387. return match.quarter(string, {
  388. width: 'narrow',
  389. context: 'formatting'
  390. });
  391. // 1st quarter, 2nd quarter, ...
  392. case 'QQQQ':
  393. default:
  394. return match.quarter(string, {
  395. width: 'wide',
  396. context: 'formatting'
  397. }) || match.quarter(string, {
  398. width: 'abbreviated',
  399. context: 'formatting'
  400. }) || match.quarter(string, {
  401. width: 'narrow',
  402. context: 'formatting'
  403. });
  404. }
  405. },
  406. validate: function (_date, value, _options) {
  407. return value >= 1 && value <= 4;
  408. },
  409. set: function (date, _flags, value, _options) {
  410. date.setUTCMonth((value - 1) * 3, 1);
  411. date.setUTCHours(0, 0, 0, 0);
  412. return date;
  413. },
  414. incompatibleTokens: ['Y', 'R', 'q', 'M', 'L', 'w', 'I', 'd', 'D', 'i', 'e', 'c', 't', 'T']
  415. },
  416. // Stand-alone quarter
  417. q: {
  418. priority: 120,
  419. parse: function (string, token, match, _options) {
  420. switch (token) {
  421. // 1, 2, 3, 4
  422. case 'q':
  423. case 'qq':
  424. // 01, 02, 03, 04
  425. return parseNDigits(token.length, string);
  426. // 1st, 2nd, 3rd, 4th
  427. case 'qo':
  428. return match.ordinalNumber(string, {
  429. unit: 'quarter'
  430. });
  431. // Q1, Q2, Q3, Q4
  432. case 'qqq':
  433. return match.quarter(string, {
  434. width: 'abbreviated',
  435. context: 'standalone'
  436. }) || match.quarter(string, {
  437. width: 'narrow',
  438. context: 'standalone'
  439. });
  440. // 1, 2, 3, 4 (narrow quarter; could be not numerical)
  441. case 'qqqqq':
  442. return match.quarter(string, {
  443. width: 'narrow',
  444. context: 'standalone'
  445. });
  446. // 1st quarter, 2nd quarter, ...
  447. case 'qqqq':
  448. default:
  449. return match.quarter(string, {
  450. width: 'wide',
  451. context: 'standalone'
  452. }) || match.quarter(string, {
  453. width: 'abbreviated',
  454. context: 'standalone'
  455. }) || match.quarter(string, {
  456. width: 'narrow',
  457. context: 'standalone'
  458. });
  459. }
  460. },
  461. validate: function (_date, value, _options) {
  462. return value >= 1 && value <= 4;
  463. },
  464. set: function (date, _flags, value, _options) {
  465. date.setUTCMonth((value - 1) * 3, 1);
  466. date.setUTCHours(0, 0, 0, 0);
  467. return date;
  468. },
  469. incompatibleTokens: ['Y', 'R', 'Q', 'M', 'L', 'w', 'I', 'd', 'D', 'i', 'e', 'c', 't', 'T']
  470. },
  471. // Month
  472. M: {
  473. priority: 110,
  474. parse: function (string, token, match, _options) {
  475. var valueCallback = function (value) {
  476. return value - 1;
  477. };
  478. switch (token) {
  479. // 1, 2, ..., 12
  480. case 'M':
  481. return parseNumericPattern(numericPatterns.month, string, valueCallback);
  482. // 01, 02, ..., 12
  483. case 'MM':
  484. return parseNDigits(2, string, valueCallback);
  485. // 1st, 2nd, ..., 12th
  486. case 'Mo':
  487. return match.ordinalNumber(string, {
  488. unit: 'month',
  489. valueCallback: valueCallback
  490. });
  491. // Jan, Feb, ..., Dec
  492. case 'MMM':
  493. return match.month(string, {
  494. width: 'abbreviated',
  495. context: 'formatting'
  496. }) || match.month(string, {
  497. width: 'narrow',
  498. context: 'formatting'
  499. });
  500. // J, F, ..., D
  501. case 'MMMMM':
  502. return match.month(string, {
  503. width: 'narrow',
  504. context: 'formatting'
  505. });
  506. // January, February, ..., December
  507. case 'MMMM':
  508. default:
  509. return match.month(string, {
  510. width: 'wide',
  511. context: 'formatting'
  512. }) || match.month(string, {
  513. width: 'abbreviated',
  514. context: 'formatting'
  515. }) || match.month(string, {
  516. width: 'narrow',
  517. context: 'formatting'
  518. });
  519. }
  520. },
  521. validate: function (_date, value, _options) {
  522. return value >= 0 && value <= 11;
  523. },
  524. set: function (date, _flags, value, _options) {
  525. date.setUTCMonth(value, 1);
  526. date.setUTCHours(0, 0, 0, 0);
  527. return date;
  528. },
  529. incompatibleTokens: ['Y', 'R', 'q', 'Q', 'L', 'w', 'I', 'D', 'i', 'e', 'c', 't', 'T']
  530. },
  531. // Stand-alone month
  532. L: {
  533. priority: 110,
  534. parse: function (string, token, match, _options) {
  535. var valueCallback = function (value) {
  536. return value - 1;
  537. };
  538. switch (token) {
  539. // 1, 2, ..., 12
  540. case 'L':
  541. return parseNumericPattern(numericPatterns.month, string, valueCallback);
  542. // 01, 02, ..., 12
  543. case 'LL':
  544. return parseNDigits(2, string, valueCallback);
  545. // 1st, 2nd, ..., 12th
  546. case 'Lo':
  547. return match.ordinalNumber(string, {
  548. unit: 'month',
  549. valueCallback: valueCallback
  550. });
  551. // Jan, Feb, ..., Dec
  552. case 'LLL':
  553. return match.month(string, {
  554. width: 'abbreviated',
  555. context: 'standalone'
  556. }) || match.month(string, {
  557. width: 'narrow',
  558. context: 'standalone'
  559. });
  560. // J, F, ..., D
  561. case 'LLLLL':
  562. return match.month(string, {
  563. width: 'narrow',
  564. context: 'standalone'
  565. });
  566. // January, February, ..., December
  567. case 'LLLL':
  568. default:
  569. return match.month(string, {
  570. width: 'wide',
  571. context: 'standalone'
  572. }) || match.month(string, {
  573. width: 'abbreviated',
  574. context: 'standalone'
  575. }) || match.month(string, {
  576. width: 'narrow',
  577. context: 'standalone'
  578. });
  579. }
  580. },
  581. validate: function (_date, value, _options) {
  582. return value >= 0 && value <= 11;
  583. },
  584. set: function (date, _flags, value, _options) {
  585. date.setUTCMonth(value, 1);
  586. date.setUTCHours(0, 0, 0, 0);
  587. return date;
  588. },
  589. incompatibleTokens: ['Y', 'R', 'q', 'Q', 'M', 'w', 'I', 'D', 'i', 'e', 'c', 't', 'T']
  590. },
  591. // Local week of year
  592. w: {
  593. priority: 100,
  594. parse: function (string, token, match, _options) {
  595. switch (token) {
  596. case 'w':
  597. return parseNumericPattern(numericPatterns.week, string);
  598. case 'wo':
  599. return match.ordinalNumber(string, {
  600. unit: 'week'
  601. });
  602. default:
  603. return parseNDigits(token.length, string);
  604. }
  605. },
  606. validate: function (_date, value, _options) {
  607. return value >= 1 && value <= 53;
  608. },
  609. set: function (date, _flags, value, options) {
  610. return startOfUTCWeek(setUTCWeek(date, value, options), options);
  611. },
  612. incompatibleTokens: ['y', 'R', 'u', 'q', 'Q', 'M', 'L', 'I', 'd', 'D', 'i', 't', 'T']
  613. },
  614. // ISO week of year
  615. I: {
  616. priority: 100,
  617. parse: function (string, token, match, _options) {
  618. switch (token) {
  619. case 'I':
  620. return parseNumericPattern(numericPatterns.week, string);
  621. case 'Io':
  622. return match.ordinalNumber(string, {
  623. unit: 'week'
  624. });
  625. default:
  626. return parseNDigits(token.length, string);
  627. }
  628. },
  629. validate: function (_date, value, _options) {
  630. return value >= 1 && value <= 53;
  631. },
  632. set: function (date, _flags, value, options) {
  633. return startOfUTCISOWeek(setUTCISOWeek(date, value, options), options);
  634. },
  635. incompatibleTokens: ['y', 'Y', 'u', 'q', 'Q', 'M', 'L', 'w', 'd', 'D', 'e', 'c', 't', 'T']
  636. },
  637. // Day of the month
  638. d: {
  639. priority: 90,
  640. subPriority: 1,
  641. parse: function (string, token, match, _options) {
  642. switch (token) {
  643. case 'd':
  644. return parseNumericPattern(numericPatterns.date, string);
  645. case 'do':
  646. return match.ordinalNumber(string, {
  647. unit: 'date'
  648. });
  649. default:
  650. return parseNDigits(token.length, string);
  651. }
  652. },
  653. validate: function (date, value, _options) {
  654. var year = date.getUTCFullYear();
  655. var isLeapYear = isLeapYearIndex(year);
  656. var month = date.getUTCMonth();
  657. if (isLeapYear) {
  658. return value >= 1 && value <= DAYS_IN_MONTH_LEAP_YEAR[month];
  659. } else {
  660. return value >= 1 && value <= DAYS_IN_MONTH[month];
  661. }
  662. },
  663. set: function (date, _flags, value, _options) {
  664. date.setUTCDate(value);
  665. date.setUTCHours(0, 0, 0, 0);
  666. return date;
  667. },
  668. incompatibleTokens: ['Y', 'R', 'q', 'Q', 'w', 'I', 'D', 'i', 'e', 'c', 't', 'T']
  669. },
  670. // Day of year
  671. D: {
  672. priority: 90,
  673. subPriority: 1,
  674. parse: function (string, token, match, _options) {
  675. switch (token) {
  676. case 'D':
  677. case 'DD':
  678. return parseNumericPattern(numericPatterns.dayOfYear, string);
  679. case 'Do':
  680. return match.ordinalNumber(string, {
  681. unit: 'date'
  682. });
  683. default:
  684. return parseNDigits(token.length, string);
  685. }
  686. },
  687. validate: function (date, value, _options) {
  688. var year = date.getUTCFullYear();
  689. var isLeapYear = isLeapYearIndex(year);
  690. if (isLeapYear) {
  691. return value >= 1 && value <= 366;
  692. } else {
  693. return value >= 1 && value <= 365;
  694. }
  695. },
  696. set: function (date, _flags, value, _options) {
  697. date.setUTCMonth(0, value);
  698. date.setUTCHours(0, 0, 0, 0);
  699. return date;
  700. },
  701. incompatibleTokens: ['Y', 'R', 'q', 'Q', 'M', 'L', 'w', 'I', 'd', 'E', 'i', 'e', 'c', 't', 'T']
  702. },
  703. // Day of week
  704. E: {
  705. priority: 90,
  706. parse: function (string, token, match, _options) {
  707. switch (token) {
  708. // Tue
  709. case 'E':
  710. case 'EE':
  711. case 'EEE':
  712. return match.day(string, {
  713. width: 'abbreviated',
  714. context: 'formatting'
  715. }) || match.day(string, {
  716. width: 'short',
  717. context: 'formatting'
  718. }) || match.day(string, {
  719. width: 'narrow',
  720. context: 'formatting'
  721. });
  722. // T
  723. case 'EEEEE':
  724. return match.day(string, {
  725. width: 'narrow',
  726. context: 'formatting'
  727. });
  728. // Tu
  729. case 'EEEEEE':
  730. return match.day(string, {
  731. width: 'short',
  732. context: 'formatting'
  733. }) || match.day(string, {
  734. width: 'narrow',
  735. context: 'formatting'
  736. });
  737. // Tuesday
  738. case 'EEEE':
  739. default:
  740. return match.day(string, {
  741. width: 'wide',
  742. context: 'formatting'
  743. }) || match.day(string, {
  744. width: 'abbreviated',
  745. context: 'formatting'
  746. }) || match.day(string, {
  747. width: 'short',
  748. context: 'formatting'
  749. }) || match.day(string, {
  750. width: 'narrow',
  751. context: 'formatting'
  752. });
  753. }
  754. },
  755. validate: function (_date, value, _options) {
  756. return value >= 0 && value <= 6;
  757. },
  758. set: function (date, _flags, value, options) {
  759. date = setUTCDay(date, value, options);
  760. date.setUTCHours(0, 0, 0, 0);
  761. return date;
  762. },
  763. incompatibleTokens: ['D', 'i', 'e', 'c', 't', 'T']
  764. },
  765. // Local day of week
  766. e: {
  767. priority: 90,
  768. parse: function (string, token, match, options) {
  769. var valueCallback = function (value) {
  770. var wholeWeekDays = Math.floor((value - 1) / 7) * 7;
  771. return (value + options.weekStartsOn + 6) % 7 + wholeWeekDays;
  772. };
  773. switch (token) {
  774. // 3
  775. case 'e':
  776. case 'ee':
  777. // 03
  778. return parseNDigits(token.length, string, valueCallback);
  779. // 3rd
  780. case 'eo':
  781. return match.ordinalNumber(string, {
  782. unit: 'day',
  783. valueCallback: valueCallback
  784. });
  785. // Tue
  786. case 'eee':
  787. return match.day(string, {
  788. width: 'abbreviated',
  789. context: 'formatting'
  790. }) || match.day(string, {
  791. width: 'short',
  792. context: 'formatting'
  793. }) || match.day(string, {
  794. width: 'narrow',
  795. context: 'formatting'
  796. });
  797. // T
  798. case 'eeeee':
  799. return match.day(string, {
  800. width: 'narrow',
  801. context: 'formatting'
  802. });
  803. // Tu
  804. case 'eeeeee':
  805. return match.day(string, {
  806. width: 'short',
  807. context: 'formatting'
  808. }) || match.day(string, {
  809. width: 'narrow',
  810. context: 'formatting'
  811. });
  812. // Tuesday
  813. case 'eeee':
  814. default:
  815. return match.day(string, {
  816. width: 'wide',
  817. context: 'formatting'
  818. }) || match.day(string, {
  819. width: 'abbreviated',
  820. context: 'formatting'
  821. }) || match.day(string, {
  822. width: 'short',
  823. context: 'formatting'
  824. }) || match.day(string, {
  825. width: 'narrow',
  826. context: 'formatting'
  827. });
  828. }
  829. },
  830. validate: function (_date, value, _options) {
  831. return value >= 0 && value <= 6;
  832. },
  833. set: function (date, _flags, value, options) {
  834. date = setUTCDay(date, value, options);
  835. date.setUTCHours(0, 0, 0, 0);
  836. return date;
  837. },
  838. incompatibleTokens: ['y', 'R', 'u', 'q', 'Q', 'M', 'L', 'I', 'd', 'D', 'E', 'i', 'c', 't', 'T']
  839. },
  840. // Stand-alone local day of week
  841. c: {
  842. priority: 90,
  843. parse: function (string, token, match, options) {
  844. var valueCallback = function (value) {
  845. var wholeWeekDays = Math.floor((value - 1) / 7) * 7;
  846. return (value + options.weekStartsOn + 6) % 7 + wholeWeekDays;
  847. };
  848. switch (token) {
  849. // 3
  850. case 'c':
  851. case 'cc':
  852. // 03
  853. return parseNDigits(token.length, string, valueCallback);
  854. // 3rd
  855. case 'co':
  856. return match.ordinalNumber(string, {
  857. unit: 'day',
  858. valueCallback: valueCallback
  859. });
  860. // Tue
  861. case 'ccc':
  862. return match.day(string, {
  863. width: 'abbreviated',
  864. context: 'standalone'
  865. }) || match.day(string, {
  866. width: 'short',
  867. context: 'standalone'
  868. }) || match.day(string, {
  869. width: 'narrow',
  870. context: 'standalone'
  871. });
  872. // T
  873. case 'ccccc':
  874. return match.day(string, {
  875. width: 'narrow',
  876. context: 'standalone'
  877. });
  878. // Tu
  879. case 'cccccc':
  880. return match.day(string, {
  881. width: 'short',
  882. context: 'standalone'
  883. }) || match.day(string, {
  884. width: 'narrow',
  885. context: 'standalone'
  886. });
  887. // Tuesday
  888. case 'cccc':
  889. default:
  890. return match.day(string, {
  891. width: 'wide',
  892. context: 'standalone'
  893. }) || match.day(string, {
  894. width: 'abbreviated',
  895. context: 'standalone'
  896. }) || match.day(string, {
  897. width: 'short',
  898. context: 'standalone'
  899. }) || match.day(string, {
  900. width: 'narrow',
  901. context: 'standalone'
  902. });
  903. }
  904. },
  905. validate: function (_date, value, _options) {
  906. return value >= 0 && value <= 6;
  907. },
  908. set: function (date, _flags, value, options) {
  909. date = setUTCDay(date, value, options);
  910. date.setUTCHours(0, 0, 0, 0);
  911. return date;
  912. },
  913. incompatibleTokens: ['y', 'R', 'u', 'q', 'Q', 'M', 'L', 'I', 'd', 'D', 'E', 'i', 'e', 't', 'T']
  914. },
  915. // ISO day of week
  916. i: {
  917. priority: 90,
  918. parse: function (string, token, match, _options) {
  919. var valueCallback = function (value) {
  920. if (value === 0) {
  921. return 7;
  922. }
  923. return value;
  924. };
  925. switch (token) {
  926. // 2
  927. case 'i':
  928. case 'ii':
  929. // 02
  930. return parseNDigits(token.length, string);
  931. // 2nd
  932. case 'io':
  933. return match.ordinalNumber(string, {
  934. unit: 'day'
  935. });
  936. // Tue
  937. case 'iii':
  938. return match.day(string, {
  939. width: 'abbreviated',
  940. context: 'formatting',
  941. valueCallback: valueCallback
  942. }) || match.day(string, {
  943. width: 'short',
  944. context: 'formatting',
  945. valueCallback: valueCallback
  946. }) || match.day(string, {
  947. width: 'narrow',
  948. context: 'formatting',
  949. valueCallback: valueCallback
  950. });
  951. // T
  952. case 'iiiii':
  953. return match.day(string, {
  954. width: 'narrow',
  955. context: 'formatting',
  956. valueCallback: valueCallback
  957. });
  958. // Tu
  959. case 'iiiiii':
  960. return match.day(string, {
  961. width: 'short',
  962. context: 'formatting',
  963. valueCallback: valueCallback
  964. }) || match.day(string, {
  965. width: 'narrow',
  966. context: 'formatting',
  967. valueCallback: valueCallback
  968. });
  969. // Tuesday
  970. case 'iiii':
  971. default:
  972. return match.day(string, {
  973. width: 'wide',
  974. context: 'formatting',
  975. valueCallback: valueCallback
  976. }) || match.day(string, {
  977. width: 'abbreviated',
  978. context: 'formatting',
  979. valueCallback: valueCallback
  980. }) || match.day(string, {
  981. width: 'short',
  982. context: 'formatting',
  983. valueCallback: valueCallback
  984. }) || match.day(string, {
  985. width: 'narrow',
  986. context: 'formatting',
  987. valueCallback: valueCallback
  988. });
  989. }
  990. },
  991. validate: function (_date, value, _options) {
  992. return value >= 1 && value <= 7;
  993. },
  994. set: function (date, _flags, value, options) {
  995. date = setUTCISODay(date, value, options);
  996. date.setUTCHours(0, 0, 0, 0);
  997. return date;
  998. },
  999. incompatibleTokens: ['y', 'Y', 'u', 'q', 'Q', 'M', 'L', 'w', 'd', 'D', 'E', 'e', 'c', 't', 'T']
  1000. },
  1001. // AM or PM
  1002. a: {
  1003. priority: 80,
  1004. parse: function (string, token, match, _options) {
  1005. switch (token) {
  1006. case 'a':
  1007. case 'aa':
  1008. case 'aaa':
  1009. return match.dayPeriod(string, {
  1010. width: 'abbreviated',
  1011. context: 'formatting'
  1012. }) || match.dayPeriod(string, {
  1013. width: 'narrow',
  1014. context: 'formatting'
  1015. });
  1016. case 'aaaaa':
  1017. return match.dayPeriod(string, {
  1018. width: 'narrow',
  1019. context: 'formatting'
  1020. });
  1021. case 'aaaa':
  1022. default:
  1023. return match.dayPeriod(string, {
  1024. width: 'wide',
  1025. context: 'formatting'
  1026. }) || match.dayPeriod(string, {
  1027. width: 'abbreviated',
  1028. context: 'formatting'
  1029. }) || match.dayPeriod(string, {
  1030. width: 'narrow',
  1031. context: 'formatting'
  1032. });
  1033. }
  1034. },
  1035. set: function (date, _flags, value, _options) {
  1036. date.setUTCHours(dayPeriodEnumToHours(value), 0, 0, 0);
  1037. return date;
  1038. },
  1039. incompatibleTokens: ['b', 'B', 'H', 'K', 'k', 't', 'T']
  1040. },
  1041. // AM, PM, midnight
  1042. b: {
  1043. priority: 80,
  1044. parse: function (string, token, match, _options) {
  1045. switch (token) {
  1046. case 'b':
  1047. case 'bb':
  1048. case 'bbb':
  1049. return match.dayPeriod(string, {
  1050. width: 'abbreviated',
  1051. context: 'formatting'
  1052. }) || match.dayPeriod(string, {
  1053. width: 'narrow',
  1054. context: 'formatting'
  1055. });
  1056. case 'bbbbb':
  1057. return match.dayPeriod(string, {
  1058. width: 'narrow',
  1059. context: 'formatting'
  1060. });
  1061. case 'bbbb':
  1062. default:
  1063. return match.dayPeriod(string, {
  1064. width: 'wide',
  1065. context: 'formatting'
  1066. }) || match.dayPeriod(string, {
  1067. width: 'abbreviated',
  1068. context: 'formatting'
  1069. }) || match.dayPeriod(string, {
  1070. width: 'narrow',
  1071. context: 'formatting'
  1072. });
  1073. }
  1074. },
  1075. set: function (date, _flags, value, _options) {
  1076. date.setUTCHours(dayPeriodEnumToHours(value), 0, 0, 0);
  1077. return date;
  1078. },
  1079. incompatibleTokens: ['a', 'B', 'H', 'K', 'k', 't', 'T']
  1080. },
  1081. // in the morning, in the afternoon, in the evening, at night
  1082. B: {
  1083. priority: 80,
  1084. parse: function (string, token, match, _options) {
  1085. switch (token) {
  1086. case 'B':
  1087. case 'BB':
  1088. case 'BBB':
  1089. return match.dayPeriod(string, {
  1090. width: 'abbreviated',
  1091. context: 'formatting'
  1092. }) || match.dayPeriod(string, {
  1093. width: 'narrow',
  1094. context: 'formatting'
  1095. });
  1096. case 'BBBBB':
  1097. return match.dayPeriod(string, {
  1098. width: 'narrow',
  1099. context: 'formatting'
  1100. });
  1101. case 'BBBB':
  1102. default:
  1103. return match.dayPeriod(string, {
  1104. width: 'wide',
  1105. context: 'formatting'
  1106. }) || match.dayPeriod(string, {
  1107. width: 'abbreviated',
  1108. context: 'formatting'
  1109. }) || match.dayPeriod(string, {
  1110. width: 'narrow',
  1111. context: 'formatting'
  1112. });
  1113. }
  1114. },
  1115. set: function (date, _flags, value, _options) {
  1116. date.setUTCHours(dayPeriodEnumToHours(value), 0, 0, 0);
  1117. return date;
  1118. },
  1119. incompatibleTokens: ['a', 'b', 't', 'T']
  1120. },
  1121. // Hour [1-12]
  1122. h: {
  1123. priority: 70,
  1124. parse: function (string, token, match, _options) {
  1125. switch (token) {
  1126. case 'h':
  1127. return parseNumericPattern(numericPatterns.hour12h, string);
  1128. case 'ho':
  1129. return match.ordinalNumber(string, {
  1130. unit: 'hour'
  1131. });
  1132. default:
  1133. return parseNDigits(token.length, string);
  1134. }
  1135. },
  1136. validate: function (_date, value, _options) {
  1137. return value >= 1 && value <= 12;
  1138. },
  1139. set: function (date, _flags, value, _options) {
  1140. var isPM = date.getUTCHours() >= 12;
  1141. if (isPM && value < 12) {
  1142. date.setUTCHours(value + 12, 0, 0, 0);
  1143. } else if (!isPM && value === 12) {
  1144. date.setUTCHours(0, 0, 0, 0);
  1145. } else {
  1146. date.setUTCHours(value, 0, 0, 0);
  1147. }
  1148. return date;
  1149. },
  1150. incompatibleTokens: ['H', 'K', 'k', 't', 'T']
  1151. },
  1152. // Hour [0-23]
  1153. H: {
  1154. priority: 70,
  1155. parse: function (string, token, match, _options) {
  1156. switch (token) {
  1157. case 'H':
  1158. return parseNumericPattern(numericPatterns.hour23h, string);
  1159. case 'Ho':
  1160. return match.ordinalNumber(string, {
  1161. unit: 'hour'
  1162. });
  1163. default:
  1164. return parseNDigits(token.length, string);
  1165. }
  1166. },
  1167. validate: function (_date, value, _options) {
  1168. return value >= 0 && value <= 23;
  1169. },
  1170. set: function (date, _flags, value, _options) {
  1171. date.setUTCHours(value, 0, 0, 0);
  1172. return date;
  1173. },
  1174. incompatibleTokens: ['a', 'b', 'h', 'K', 'k', 't', 'T']
  1175. },
  1176. // Hour [0-11]
  1177. K: {
  1178. priority: 70,
  1179. parse: function (string, token, match, _options) {
  1180. switch (token) {
  1181. case 'K':
  1182. return parseNumericPattern(numericPatterns.hour11h, string);
  1183. case 'Ko':
  1184. return match.ordinalNumber(string, {
  1185. unit: 'hour'
  1186. });
  1187. default:
  1188. return parseNDigits(token.length, string);
  1189. }
  1190. },
  1191. validate: function (_date, value, _options) {
  1192. return value >= 0 && value <= 11;
  1193. },
  1194. set: function (date, _flags, value, _options) {
  1195. var isPM = date.getUTCHours() >= 12;
  1196. if (isPM && value < 12) {
  1197. date.setUTCHours(value + 12, 0, 0, 0);
  1198. } else {
  1199. date.setUTCHours(value, 0, 0, 0);
  1200. }
  1201. return date;
  1202. },
  1203. incompatibleTokens: ['a', 'b', 'h', 'H', 'k', 't', 'T']
  1204. },
  1205. // Hour [1-24]
  1206. k: {
  1207. priority: 70,
  1208. parse: function (string, token, match, _options) {
  1209. switch (token) {
  1210. case 'k':
  1211. return parseNumericPattern(numericPatterns.hour24h, string);
  1212. case 'ko':
  1213. return match.ordinalNumber(string, {
  1214. unit: 'hour'
  1215. });
  1216. default:
  1217. return parseNDigits(token.length, string);
  1218. }
  1219. },
  1220. validate: function (_date, value, _options) {
  1221. return value >= 1 && value <= 24;
  1222. },
  1223. set: function (date, _flags, value, _options) {
  1224. var hours = value <= 24 ? value % 24 : value;
  1225. date.setUTCHours(hours, 0, 0, 0);
  1226. return date;
  1227. },
  1228. incompatibleTokens: ['a', 'b', 'h', 'H', 'K', 't', 'T']
  1229. },
  1230. // Minute
  1231. m: {
  1232. priority: 60,
  1233. parse: function (string, token, match, _options) {
  1234. switch (token) {
  1235. case 'm':
  1236. return parseNumericPattern(numericPatterns.minute, string);
  1237. case 'mo':
  1238. return match.ordinalNumber(string, {
  1239. unit: 'minute'
  1240. });
  1241. default:
  1242. return parseNDigits(token.length, string);
  1243. }
  1244. },
  1245. validate: function (_date, value, _options) {
  1246. return value >= 0 && value <= 59;
  1247. },
  1248. set: function (date, _flags, value, _options) {
  1249. date.setUTCMinutes(value, 0, 0);
  1250. return date;
  1251. },
  1252. incompatibleTokens: ['t', 'T']
  1253. },
  1254. // Second
  1255. s: {
  1256. priority: 50,
  1257. parse: function (string, token, match, _options) {
  1258. switch (token) {
  1259. case 's':
  1260. return parseNumericPattern(numericPatterns.second, string);
  1261. case 'so':
  1262. return match.ordinalNumber(string, {
  1263. unit: 'second'
  1264. });
  1265. default:
  1266. return parseNDigits(token.length, string);
  1267. }
  1268. },
  1269. validate: function (_date, value, _options) {
  1270. return value >= 0 && value <= 59;
  1271. },
  1272. set: function (date, _flags, value, _options) {
  1273. date.setUTCSeconds(value, 0);
  1274. return date;
  1275. },
  1276. incompatibleTokens: ['t', 'T']
  1277. },
  1278. // Fraction of second
  1279. S: {
  1280. priority: 30,
  1281. parse: function (string, token, _match, _options) {
  1282. var valueCallback = function (value) {
  1283. return Math.floor(value * Math.pow(10, -token.length + 3));
  1284. };
  1285. return parseNDigits(token.length, string, valueCallback);
  1286. },
  1287. set: function (date, _flags, value, _options) {
  1288. date.setUTCMilliseconds(value);
  1289. return date;
  1290. },
  1291. incompatibleTokens: ['t', 'T']
  1292. },
  1293. // Timezone (ISO-8601. +00:00 is `'Z'`)
  1294. X: {
  1295. priority: 10,
  1296. parse: function (string, token, _match, _options) {
  1297. switch (token) {
  1298. case 'X':
  1299. return parseTimezonePattern(timezonePatterns.basicOptionalMinutes, string);
  1300. case 'XX':
  1301. return parseTimezonePattern(timezonePatterns.basic, string);
  1302. case 'XXXX':
  1303. return parseTimezonePattern(timezonePatterns.basicOptionalSeconds, string);
  1304. case 'XXXXX':
  1305. return parseTimezonePattern(timezonePatterns.extendedOptionalSeconds, string);
  1306. case 'XXX':
  1307. default:
  1308. return parseTimezonePattern(timezonePatterns.extended, string);
  1309. }
  1310. },
  1311. set: function (date, flags, value, _options) {
  1312. if (flags.timestampIsSet) {
  1313. return date;
  1314. }
  1315. return new Date(date.getTime() - value);
  1316. },
  1317. incompatibleTokens: ['t', 'T', 'x']
  1318. },
  1319. // Timezone (ISO-8601)
  1320. x: {
  1321. priority: 10,
  1322. parse: function (string, token, _match, _options) {
  1323. switch (token) {
  1324. case 'x':
  1325. return parseTimezonePattern(timezonePatterns.basicOptionalMinutes, string);
  1326. case 'xx':
  1327. return parseTimezonePattern(timezonePatterns.basic, string);
  1328. case 'xxxx':
  1329. return parseTimezonePattern(timezonePatterns.basicOptionalSeconds, string);
  1330. case 'xxxxx':
  1331. return parseTimezonePattern(timezonePatterns.extendedOptionalSeconds, string);
  1332. case 'xxx':
  1333. default:
  1334. return parseTimezonePattern(timezonePatterns.extended, string);
  1335. }
  1336. },
  1337. set: function (date, flags, value, _options) {
  1338. if (flags.timestampIsSet) {
  1339. return date;
  1340. }
  1341. return new Date(date.getTime() - value);
  1342. },
  1343. incompatibleTokens: ['t', 'T', 'X']
  1344. },
  1345. // Seconds timestamp
  1346. t: {
  1347. priority: 40,
  1348. parse: function (string, _token, _match, _options) {
  1349. return parseAnyDigitsSigned(string);
  1350. },
  1351. set: function (_date, _flags, value, _options) {
  1352. return [new Date(value * 1000), {
  1353. timestampIsSet: true
  1354. }];
  1355. },
  1356. incompatibleTokens: '*'
  1357. },
  1358. // Milliseconds timestamp
  1359. T: {
  1360. priority: 20,
  1361. parse: function (string, _token, _match, _options) {
  1362. return parseAnyDigitsSigned(string);
  1363. },
  1364. set: function (_date, _flags, value, _options) {
  1365. return [new Date(value), {
  1366. timestampIsSet: true
  1367. }];
  1368. },
  1369. incompatibleTokens: '*'
  1370. }
  1371. };
  1372. export default parsers;