commit | author | age
|
1759c2
|
1 |
/** |
RM |
2 |
* angular-strap |
|
3 |
* @version v2.0.3 - 2014-05-30 |
|
4 |
* @link http://mgcrea.github.io/angular-strap |
|
5 |
* @author Olivier Louvignes (olivier@mg-crea.com) |
|
6 |
* @license MIT License, http://www.opensource.org/licenses/MIT |
|
7 |
*/ |
|
8 |
'use strict'; |
|
9 |
angular.module('mgcrea.ngStrap.helpers.dateParser', []).provider('$dateParser', [ |
|
10 |
'$localeProvider', |
|
11 |
function ($localeProvider) { |
|
12 |
var proto = Date.prototype; |
|
13 |
function isNumeric(n) { |
|
14 |
return !isNaN(parseFloat(n)) && isFinite(n); |
|
15 |
} |
|
16 |
var defaults = this.defaults = { |
|
17 |
format: 'shortDate', |
|
18 |
strict: false |
|
19 |
}; |
|
20 |
this.$get = [ |
|
21 |
'$locale', |
|
22 |
function ($locale) { |
|
23 |
var DateParserFactory = function (config) { |
|
24 |
var options = angular.extend({}, defaults, config); |
|
25 |
var $dateParser = {}; |
|
26 |
var regExpMap = { |
|
27 |
'sss': '[0-9]{3}', |
|
28 |
'ss': '[0-5][0-9]', |
|
29 |
's': options.strict ? '[1-5]?[0-9]' : '[0-9]|[0-5][0-9]', |
|
30 |
'mm': '[0-5][0-9]', |
|
31 |
'm': options.strict ? '[1-5]?[0-9]' : '[0-9]|[0-5][0-9]', |
|
32 |
'HH': '[01][0-9]|2[0-3]', |
|
33 |
'H': options.strict ? '1?[0-9]|2[0-3]' : '[01]?[0-9]|2[0-3]', |
|
34 |
'hh': '[0][1-9]|[1][012]', |
|
35 |
'h': options.strict ? '[1-9]|1[012]' : '0?[1-9]|1[012]', |
|
36 |
'a': 'AM|PM', |
|
37 |
'EEEE': $locale.DATETIME_FORMATS.DAY.join('|'), |
|
38 |
'EEE': $locale.DATETIME_FORMATS.SHORTDAY.join('|'), |
|
39 |
'dd': '0[1-9]|[12][0-9]|3[01]', |
|
40 |
'd': options.strict ? '[1-9]|[1-2][0-9]|3[01]' : '0?[1-9]|[1-2][0-9]|3[01]', |
|
41 |
'MMMM': $locale.DATETIME_FORMATS.MONTH.join('|'), |
|
42 |
'MMM': $locale.DATETIME_FORMATS.SHORTMONTH.join('|'), |
|
43 |
'MM': '0[1-9]|1[012]', |
|
44 |
'M': options.strict ? '[1-9]|1[012]' : '0?[1-9]|1[012]', |
|
45 |
'yyyy': '[1]{1}[0-9]{3}|[2]{1}[0-9]{3}', |
|
46 |
'yy': '[0-9]{2}', |
|
47 |
'y': options.strict ? '-?(0|[1-9][0-9]{0,3})' : '-?0*[0-9]{1,4}' |
|
48 |
}; |
|
49 |
var setFnMap = { |
|
50 |
'sss': proto.setMilliseconds, |
|
51 |
'ss': proto.setSeconds, |
|
52 |
's': proto.setSeconds, |
|
53 |
'mm': proto.setMinutes, |
|
54 |
'm': proto.setMinutes, |
|
55 |
'HH': proto.setHours, |
|
56 |
'H': proto.setHours, |
|
57 |
'hh': proto.setHours, |
|
58 |
'h': proto.setHours, |
|
59 |
'dd': proto.setDate, |
|
60 |
'd': proto.setDate, |
|
61 |
'a': function (value) { |
|
62 |
var hours = this.getHours(); |
|
63 |
return this.setHours(value.match(/pm/i) ? hours + 12 : hours); |
|
64 |
}, |
|
65 |
'MMMM': function (value) { |
|
66 |
return this.setMonth($locale.DATETIME_FORMATS.MONTH.indexOf(value)); |
|
67 |
}, |
|
68 |
'MMM': function (value) { |
|
69 |
return this.setMonth($locale.DATETIME_FORMATS.SHORTMONTH.indexOf(value)); |
|
70 |
}, |
|
71 |
'MM': function (value) { |
|
72 |
return this.setMonth(1 * value - 1); |
|
73 |
}, |
|
74 |
'M': function (value) { |
|
75 |
return this.setMonth(1 * value - 1); |
|
76 |
}, |
|
77 |
'yyyy': proto.setFullYear, |
|
78 |
'yy': function (value) { |
|
79 |
return this.setFullYear(2000 + 1 * value); |
|
80 |
}, |
|
81 |
'y': proto.setFullYear |
|
82 |
}; |
|
83 |
var regex, setMap; |
|
84 |
$dateParser.init = function () { |
|
85 |
$dateParser.$format = $locale.DATETIME_FORMATS[options.format] || options.format; |
|
86 |
regex = regExpForFormat($dateParser.$format); |
|
87 |
setMap = setMapForFormat($dateParser.$format); |
|
88 |
}; |
|
89 |
$dateParser.isValid = function (date) { |
|
90 |
if (angular.isDate(date)) |
|
91 |
return !isNaN(date.getTime()); |
|
92 |
return regex.test(date); |
|
93 |
}; |
|
94 |
$dateParser.parse = function (value, baseDate, format) { |
|
95 |
var formatRegex = format ? regExpForFormat(format) : regex; |
|
96 |
var formatSetMap = format ? setMapForFormat(format) : setMap; |
|
97 |
if (angular.isDate(value)) |
|
98 |
return value; |
|
99 |
var matches = formatRegex.exec(value); |
|
100 |
if (!matches) |
|
101 |
return false; |
|
102 |
var date = baseDate || new Date(0, 0, 1); |
|
103 |
for (var i = 0; i < matches.length - 1; i++) { |
|
104 |
formatSetMap[i] && formatSetMap[i].call(date, matches[i + 1]); |
|
105 |
} |
|
106 |
return date; |
|
107 |
}; |
|
108 |
// Private functions |
|
109 |
function setMapForFormat(format) { |
|
110 |
var keys = Object.keys(setFnMap), i; |
|
111 |
var map = [], sortedMap = []; |
|
112 |
// Map to setFn |
|
113 |
var clonedFormat = format; |
|
114 |
for (i = 0; i < keys.length; i++) { |
|
115 |
if (format.split(keys[i]).length > 1) { |
|
116 |
var index = clonedFormat.search(keys[i]); |
|
117 |
format = format.split(keys[i]).join(''); |
|
118 |
if (setFnMap[keys[i]]) |
|
119 |
map[index] = setFnMap[keys[i]]; |
|
120 |
} |
|
121 |
} |
|
122 |
// Sort result map |
|
123 |
angular.forEach(map, function (v) { |
|
124 |
sortedMap.push(v); |
|
125 |
}); |
|
126 |
return sortedMap; |
|
127 |
} |
|
128 |
function escapeReservedSymbols(text) { |
|
129 |
return text.replace(/\//g, '[\\/]').replace('/-/g', '[-]').replace(/\./g, '[.]').replace(/\\s/g, '[\\s]'); |
|
130 |
} |
|
131 |
function regExpForFormat(format) { |
|
132 |
var keys = Object.keys(regExpMap), i; |
|
133 |
var re = format; |
|
134 |
// Abstract replaces to avoid collisions |
|
135 |
for (i = 0; i < keys.length; i++) { |
|
136 |
re = re.split(keys[i]).join('${' + i + '}'); |
|
137 |
} |
|
138 |
// Replace abstracted values |
|
139 |
for (i = 0; i < keys.length; i++) { |
|
140 |
re = re.split('${' + i + '}').join('(' + regExpMap[keys[i]] + ')'); |
|
141 |
} |
|
142 |
format = escapeReservedSymbols(format); |
|
143 |
return new RegExp('^' + re + '$', ['i']); |
|
144 |
} |
|
145 |
$dateParser.init(); |
|
146 |
return $dateParser; |
|
147 |
}; |
|
148 |
return DateParserFactory; |
|
149 |
} |
|
150 |
]; |
|
151 |
} |
|
152 |
]); |