| angular.module('ui.bootstrap.dateparser', []) |
| |
| .service('uibDateParser', ['$log', '$locale', 'orderByFilter', function($log, $locale, orderByFilter) { |
| // Pulled from https://github.com/mbostock/d3/blob/master/src/format/requote.js |
| var SPECIAL_CHARACTERS_REGEXP = /[\\\^\$\*\+\?\|\[\]\(\)\.\{\}]/g; |
| |
| var localeId; |
| var formatCodeToRegex; |
| |
| this.init = function() { |
| localeId = $locale.id; |
| |
| this.parsers = {}; |
| |
| formatCodeToRegex = { |
| 'yyyy': { |
| regex: '\\d{4}', |
| apply: function(value) { this.year = +value; } |
| }, |
| 'yy': { |
| regex: '\\d{2}', |
| apply: function(value) { this.year = +value + 2000; } |
| }, |
| 'y': { |
| regex: '\\d{1,4}', |
| apply: function(value) { this.year = +value; } |
| }, |
| 'MMMM': { |
| regex: $locale.DATETIME_FORMATS.MONTH.join('|'), |
| apply: function(value) { this.month = $locale.DATETIME_FORMATS.MONTH.indexOf(value); } |
| }, |
| 'MMM': { |
| regex: $locale.DATETIME_FORMATS.SHORTMONTH.join('|'), |
| apply: function(value) { this.month = $locale.DATETIME_FORMATS.SHORTMONTH.indexOf(value); } |
| }, |
| 'MM': { |
| regex: '0[1-9]|1[0-2]', |
| apply: function(value) { this.month = value - 1; } |
| }, |
| 'M': { |
| regex: '[1-9]|1[0-2]', |
| apply: function(value) { this.month = value - 1; } |
| }, |
| 'dd': { |
| regex: '[0-2][0-9]{1}|3[0-1]{1}', |
| apply: function(value) { this.date = +value; } |
| }, |
| 'd': { |
| regex: '[1-2]?[0-9]{1}|3[0-1]{1}', |
| apply: function(value) { this.date = +value; } |
| }, |
| 'EEEE': { |
| regex: $locale.DATETIME_FORMATS.DAY.join('|') |
| }, |
| 'EEE': { |
| regex: $locale.DATETIME_FORMATS.SHORTDAY.join('|') |
| }, |
| 'HH': { |
| regex: '(?:0|1)[0-9]|2[0-3]', |
| apply: function(value) { this.hours = +value; } |
| }, |
| 'hh': { |
| regex: '0[0-9]|1[0-2]', |
| apply: function(value) { this.hours = +value; } |
| }, |
| 'H': { |
| regex: '1?[0-9]|2[0-3]', |
| apply: function(value) { this.hours = +value; } |
| }, |
| 'h': { |
| regex: '[0-9]|1[0-2]', |
| apply: function(value) { this.hours = +value; } |
| }, |
| 'mm': { |
| regex: '[0-5][0-9]', |
| apply: function(value) { this.minutes = +value; } |
| }, |
| 'm': { |
| regex: '[0-9]|[1-5][0-9]', |
| apply: function(value) { this.minutes = +value; } |
| }, |
| 'sss': { |
| regex: '[0-9][0-9][0-9]', |
| apply: function(value) { this.milliseconds = +value; } |
| }, |
| 'ss': { |
| regex: '[0-5][0-9]', |
| apply: function(value) { this.seconds = +value; } |
| }, |
| 's': { |
| regex: '[0-9]|[1-5][0-9]', |
| apply: function(value) { this.seconds = +value; } |
| }, |
| 'a': { |
| regex: $locale.DATETIME_FORMATS.AMPMS.join('|'), |
| apply: function(value) { |
| if (this.hours === 12) { |
| this.hours = 0; |
| } |
| |
| if (value === 'PM') { |
| this.hours += 12; |
| } |
| } |
| } |
| }; |
| }; |
| |
| this.init(); |
| |
| function createParser(format) { |
| var map = [], regex = format.split(''); |
| |
| angular.forEach(formatCodeToRegex, function(data, code) { |
| var index = format.indexOf(code); |
| |
| if (index > -1) { |
| format = format.split(''); |
| |
| regex[index] = '(' + data.regex + ')'; |
| format[index] = '$'; // Custom symbol to define consumed part of format |
| for (var i = index + 1, n = index + code.length; i < n; i++) { |
| regex[i] = ''; |
| format[i] = '$'; |
| } |
| format = format.join(''); |
| |
| map.push({ index: index, apply: data.apply }); |
| } |
| }); |
| |
| return { |
| regex: new RegExp('^' + regex.join('') + '$'), |
| map: orderByFilter(map, 'index') |
| }; |
| } |
| |
| this.parse = function(input, format, baseDate) { |
| if (!angular.isString(input) || !format) { |
| return input; |
| } |
| |
| format = $locale.DATETIME_FORMATS[format] || format; |
| format = format.replace(SPECIAL_CHARACTERS_REGEXP, '\\$&'); |
| |
| if ($locale.id !== localeId) { |
| this.init(); |
| } |
| |
| if (!this.parsers[format]) { |
| this.parsers[format] = createParser(format); |
| } |
| |
| var parser = this.parsers[format], |
| regex = parser.regex, |
| map = parser.map, |
| results = input.match(regex); |
| |
| if (results && results.length) { |
| var fields, dt; |
| if (angular.isDate(baseDate) && !isNaN(baseDate.getTime())) { |
| fields = { |
| year: baseDate.getFullYear(), |
| month: baseDate.getMonth(), |
| date: baseDate.getDate(), |
| hours: baseDate.getHours(), |
| minutes: baseDate.getMinutes(), |
| seconds: baseDate.getSeconds(), |
| milliseconds: baseDate.getMilliseconds() |
| }; |
| } else { |
| if (baseDate) { |
| $log.warn('dateparser:', 'baseDate is not a valid date'); |
| } |
| fields = { year: 1900, month: 0, date: 1, hours: 0, minutes: 0, seconds: 0, milliseconds: 0 }; |
| } |
| |
| for (var i = 1, n = results.length; i < n; i++) { |
| var mapper = map[i-1]; |
| if (mapper.apply) { |
| mapper.apply.call(fields, results[i]); |
| } |
| } |
| |
| if (isValid(fields.year, fields.month, fields.date)) { |
| if (angular.isDate(baseDate) && !isNaN(baseDate.getTime())) { |
| dt = new Date(baseDate); |
| dt.setFullYear(fields.year, fields.month, fields.date, |
| fields.hours, fields.minutes, fields.seconds, |
| fields.milliseconds || 0); |
| } else { |
| dt = new Date(fields.year, fields.month, fields.date, |
| fields.hours, fields.minutes, fields.seconds, |
| fields.milliseconds || 0); |
| } |
| } |
| |
| return dt; |
| } |
| }; |
| |
| // Check if date is valid for specific month (and year for February). |
| // Month: 0 = Jan, 1 = Feb, etc |
| function isValid(year, month, date) { |
| if (date < 1) { |
| return false; |
| } |
| |
| if (month === 1 && date > 28) { |
| return date === 29 && ((year % 4 === 0 && year % 100 !== 0) || year % 400 === 0); |
| } |
| |
| if (month === 3 || month === 5 || month === 8 || month === 10) { |
| return date < 31; |
| } |
| |
| return true; |
| } |
| }]); |
| |
| /* Deprecated dateparser below */ |
| |
| angular.module('ui.bootstrap.dateparser') |
| |
| .value('$dateParserSuppressWarning', false) |
| |
| .service('dateParser', ['$log', '$dateParserSuppressWarning', 'uibDateParser', function($log, $dateParserSuppressWarning, uibDateParser) { |
| if (!$dateParserSuppressWarning) { |
| $log.warn('dateParser is now deprecated. Use uibDateParser instead.'); |
| } |
| |
| angular.extend(this, uibDateParser); |
| }]); |