date.parser.js 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283
  1. /**
  2. * DevExtreme (localization/ldml/date.parser.js)
  3. * Version: 19.1.16
  4. * Build date: Tue Oct 18 2022
  5. *
  6. * Copyright (c) 2012 - 2022 Developer Express Inc. ALL RIGHTS RESERVED
  7. * Read about DevExtreme licensing here: https://js.devexpress.com/Licensing/
  8. */
  9. "use strict";
  10. var escapeRegExp = require("../../core/utils/common").escapeRegExp;
  11. var FORMAT_TYPES = {
  12. 3: "abbreviated",
  13. 4: "wide",
  14. 5: "narrow"
  15. };
  16. var monthRegExpGenerator = function(count, dateParts) {
  17. if (count > 2) {
  18. return Object.keys(FORMAT_TYPES).map(function(count) {
  19. return ["format", "standalone"].map(function(type) {
  20. return dateParts.getMonthNames(FORMAT_TYPES[count], type).join("|")
  21. }).join("|")
  22. }).join("|")
  23. }
  24. return "0?[1-9]|1[012]"
  25. };
  26. var PATTERN_REGEXPS = {
  27. y: function(count) {
  28. return "[0-9]+"
  29. },
  30. M: monthRegExpGenerator,
  31. L: monthRegExpGenerator,
  32. Q: function(count, dateParts) {
  33. if (count > 2) {
  34. return dateParts.getQuarterNames(FORMAT_TYPES[count], "format").join("|")
  35. }
  36. return "0?[1-4]"
  37. },
  38. E: function(count, dateParts) {
  39. return "\\D*"
  40. },
  41. a: function(count, dateParts) {
  42. return dateParts.getPeriodNames(FORMAT_TYPES[count < 3 ? 3 : count], "format").join("|")
  43. },
  44. d: function(count) {
  45. return "0?[1-9]|[12][0-9]|3[01]"
  46. },
  47. H: function(count) {
  48. return "0?[0-9]|1[0-9]|2[0-3]"
  49. },
  50. h: function(count) {
  51. return "0?[1-9]|1[012]"
  52. },
  53. m: function(count) {
  54. return "0?[0-9]|[1-5][0-9]"
  55. },
  56. s: function(count) {
  57. return "0?[0-9]|[1-5][0-9]"
  58. },
  59. S: function(count) {
  60. return "[0-9]{1," + count + "}"
  61. }
  62. };
  63. var parseNumber = Number;
  64. var caseInsensitiveIndexOf = function(array, value) {
  65. return array.map(function(item) {
  66. return item.toLowerCase()
  67. }).indexOf(value.toLowerCase())
  68. };
  69. var monthPatternParser = function(text, count, dateParts) {
  70. if (count > 2) {
  71. return ["format", "standalone"].map(function(type) {
  72. return Object.keys(FORMAT_TYPES).map(function(count) {
  73. var monthNames = dateParts.getMonthNames(FORMAT_TYPES[count], type);
  74. return caseInsensitiveIndexOf(monthNames, text)
  75. })
  76. }).reduce(function(a, b) {
  77. return a.concat(b)
  78. }).filter(function(index) {
  79. return index >= 0
  80. })[0]
  81. }
  82. return parseNumber(text) - 1
  83. };
  84. var PATTERN_PARSERS = {
  85. y: function(text, count) {
  86. var year = parseNumber(text);
  87. if (2 === count) {
  88. return year < 30 ? 2e3 + year : 1900 + year
  89. }
  90. return year
  91. },
  92. M: monthPatternParser,
  93. L: monthPatternParser,
  94. Q: function(text, count, dateParts) {
  95. if (count > 2) {
  96. return dateParts.getQuarterNames(FORMAT_TYPES[count], "format").indexOf(text)
  97. }
  98. return parseNumber(text) - 1
  99. },
  100. E: function(text, count, dateParts) {
  101. var dayNames = dateParts.getDayNames(FORMAT_TYPES[count < 3 ? 3 : count], "format");
  102. return caseInsensitiveIndexOf(dayNames, text)
  103. },
  104. a: function(text, count, dateParts) {
  105. var periodNames = dateParts.getPeriodNames(FORMAT_TYPES[count < 3 ? 3 : count], "format");
  106. return caseInsensitiveIndexOf(periodNames, text)
  107. },
  108. d: parseNumber,
  109. H: parseNumber,
  110. h: parseNumber,
  111. m: parseNumber,
  112. s: parseNumber,
  113. S: function(text, count) {
  114. count = Math.max(count, 3);
  115. text = text.slice(0, 3);
  116. while (count < 3) {
  117. text += "0";
  118. count++
  119. }
  120. return parseNumber(text)
  121. }
  122. };
  123. var ORDERED_PATTERNS = ["y", "M", "d", "h", "m", "s", "S"];
  124. var PATTERN_SETTERS = {
  125. y: "setFullYear",
  126. M: "setMonth",
  127. L: "setMonth",
  128. a: function(date, value, datePartValues) {
  129. var hours = date.getHours();
  130. var hourPartValue = datePartValues.h;
  131. if (void 0 !== hourPartValue && hourPartValue !== hours) {
  132. hours--
  133. }
  134. if (!value && 12 === hours) {
  135. hours = 0
  136. } else {
  137. if (value && 12 !== hours) {
  138. hours += 12
  139. }
  140. }
  141. date.setHours(hours)
  142. },
  143. d: "setDate",
  144. H: "setHours",
  145. h: "setHours",
  146. m: "setMinutes",
  147. s: "setSeconds",
  148. S: "setMilliseconds"
  149. };
  150. var getSameCharCount = function(text, index) {
  151. var char = text[index];
  152. var count = 0;
  153. do {
  154. index++;
  155. count++
  156. } while (text[index] === char);
  157. return count
  158. };
  159. var createPattern = function(char, count) {
  160. var result = "";
  161. for (var i = 0; i < count; i++) {
  162. result += char
  163. }
  164. return result
  165. };
  166. var getRegExpInfo = function(format, dateParts) {
  167. var regexpText = "";
  168. var stubText = "";
  169. var isEscaping;
  170. var patterns = [];
  171. var addPreviousStub = function() {
  172. if (stubText) {
  173. patterns.push("'" + stubText + "'");
  174. regexpText += escapeRegExp(stubText) + ")";
  175. stubText = ""
  176. }
  177. };
  178. for (var i = 0; i < format.length; i++) {
  179. var char = format[i];
  180. var isEscapeChar = "'" === char;
  181. var regexpPart = PATTERN_REGEXPS[char];
  182. if (isEscapeChar) {
  183. isEscaping = !isEscaping;
  184. if ("'" !== format[i - 1]) {
  185. continue
  186. }
  187. }
  188. if (regexpPart && !isEscaping) {
  189. var count = getSameCharCount(format, i);
  190. var pattern = createPattern(char, count);
  191. addPreviousStub();
  192. patterns.push(pattern);
  193. regexpText += "(" + regexpPart(count, dateParts) + ")";
  194. i += count - 1
  195. } else {
  196. if (!stubText) {
  197. regexpText += "("
  198. }
  199. stubText += char
  200. }
  201. }
  202. addPreviousStub();
  203. return {
  204. patterns: patterns,
  205. regexp: new RegExp("^" + regexpText + "$", "i")
  206. }
  207. };
  208. var getPatternSetters = function() {
  209. return PATTERN_SETTERS
  210. };
  211. var setPatternPart = function(date, pattern, text, dateParts, datePartValues) {
  212. var patternChar = pattern[0];
  213. var partSetter = PATTERN_SETTERS[patternChar];
  214. var partParser = PATTERN_PARSERS[patternChar];
  215. if (partSetter && partParser) {
  216. var value = partParser(text, pattern.length, dateParts);
  217. datePartValues[pattern] = value;
  218. if (date[partSetter]) {
  219. date[partSetter](value)
  220. } else {
  221. partSetter(date, value, datePartValues)
  222. }
  223. }
  224. };
  225. var setPatternPartFromNow = function(date, pattern, now) {
  226. var setterName = PATTERN_SETTERS[pattern];
  227. var getterName = "g" + setterName.substr(1);
  228. var value = now[getterName]();
  229. date[setterName](value)
  230. };
  231. var getShortPatterns = function(fullPatterns) {
  232. return fullPatterns.map(function(pattern) {
  233. if ("'" === pattern[0]) {
  234. return ""
  235. } else {
  236. return "H" === pattern[0] ? "h" : pattern[0]
  237. }
  238. })
  239. };
  240. var getMaxOrderedPatternIndex = function(patterns) {
  241. var indexes = patterns.map(function(pattern) {
  242. return ORDERED_PATTERNS.indexOf(pattern)
  243. });
  244. return Math.max.apply(Math, indexes)
  245. };
  246. var getOrderedFormatPatterns = function(formatPatterns) {
  247. var otherPatterns = formatPatterns.filter(function(pattern) {
  248. return ORDERED_PATTERNS.indexOf(pattern) < 0
  249. });
  250. return ORDERED_PATTERNS.concat(otherPatterns)
  251. };
  252. var getParser = function(format, dateParts) {
  253. var regExpInfo = getRegExpInfo(format, dateParts);
  254. return function(text) {
  255. var regExpResult = regExpInfo.regexp.exec(text);
  256. if (regExpResult) {
  257. var now = new Date;
  258. var date = new Date(now.getFullYear(), 0, 1);
  259. var formatPatterns = getShortPatterns(regExpInfo.patterns);
  260. var maxPatternIndex = getMaxOrderedPatternIndex(formatPatterns);
  261. var orderedFormatPatterns = getOrderedFormatPatterns(formatPatterns);
  262. var datePartValues = {};
  263. orderedFormatPatterns.forEach(function(pattern, index) {
  264. if (!pattern || index < ORDERED_PATTERNS.length && index > maxPatternIndex) {
  265. return
  266. }
  267. var patternIndex = formatPatterns.indexOf(pattern);
  268. if (patternIndex >= 0) {
  269. var regExpPattern = regExpInfo.patterns[patternIndex];
  270. var regExpText = regExpResult[patternIndex + 1];
  271. setPatternPart(date, regExpPattern, regExpText, dateParts, datePartValues)
  272. } else {
  273. setPatternPartFromNow(date, pattern, now)
  274. }
  275. });
  276. return date
  277. }
  278. return null
  279. }
  280. };
  281. exports.getParser = getParser;
  282. exports.getRegExpInfo = getRegExpInfo;
  283. exports.getPatternSetters = getPatternSetters;