|
22 | 22 |
|
23 | 23 | $.extend($.ui, { timepicker: { version: "1.0.0" } });
|
24 | 24 |
|
| 25 | +//####################################################################################### |
| 26 | +// Return regexp to parse possible am/pm time postfixes. |
| 27 | +// amNames, pmNames - arrays of strings |
| 28 | +//####################################################################################### |
| 29 | +var getPatternAmpm = function(amNames, pmNames) { |
| 30 | + var markers = []; |
| 31 | + if (amNames) |
| 32 | + $.merge(markers, amNames); |
| 33 | + if (pmNames) |
| 34 | + $.merge(markers, pmNames); |
| 35 | + markers = $.map(markers, function(val) { return val.replace(/[.*+?|()\[\]{}\\]/g, '\\$&'); }); |
| 36 | + return '(' + markers.join('|') + ')?'; |
| 37 | +} |
| 38 | + |
| 39 | +var getFormatPositions = function( timeFormat ) { |
| 40 | + var finds = timeFormat.toLowerCase().match(/(h{1,2}|m{1,2}|s{1,2}|l{1}|t{1,2}|z)/g), |
| 41 | + orders = { h: -1, m: -1, s: -1, l: -1, t: -1, z: -1 }; |
| 42 | + |
| 43 | + if (finds) |
| 44 | + for (var i = 0; i < finds.length; i++) |
| 45 | + if (orders[finds[i].toString().charAt(0)] == -1) |
| 46 | + orders[finds[i].toString().charAt(0)] = i + 1; |
| 47 | + |
| 48 | + return orders; |
| 49 | +} |
| 50 | + |
| 51 | +//####################################################################################### |
| 52 | +// Splits datetime string into date ans time substrings. |
| 53 | +// Throws exception when date can't be parsed |
| 54 | +// If only date is present, time substring eill be '' |
| 55 | +//####################################################################################### |
| 56 | +var splitDateTime = function(dateFormat, dateTimeString, dateSettings) |
| 57 | +{ |
| 58 | + try { |
| 59 | + var date = $.datepicker._base_parseDate(dateFormat, dateTimeString, dateSettings); |
| 60 | + } catch (err) { |
| 61 | + if (err.indexOf(":") >= 0) { |
| 62 | + // Hack! The error message ends with a colon, a space, and |
| 63 | + // the "extra" characters. We rely on that instead of |
| 64 | + // attempting to perfectly reproduce the parsing algorithm. |
| 65 | + var dateStringLength = dateTimeString.length-(err.length-err.indexOf(':')-2); |
| 66 | + var timeString = dateTimeString.substring(dateStringLength); |
| 67 | + |
| 68 | + return [dateTimeString.substring(0, dateStringLength), dateTimeString.substring(dateStringLength)] |
| 69 | + |
| 70 | + } else { |
| 71 | + throw err; |
| 72 | + } |
| 73 | + } |
| 74 | + return [dateTimeString, '']; |
| 75 | +} |
| 76 | + |
| 77 | +//####################################################################################### |
| 78 | +// Internal function to parse datetime interval |
| 79 | +// Returns: {date: Date, timeObj: Object}, where |
| 80 | +// date is parsed date withowt time (type Date) |
| 81 | +// timeObj = {hour: , minute: , second: , millisec: } - parsed time. Can be missed |
| 82 | +//####################################################################################### |
| 83 | +var parseDateTimeInternal = function(dateFormat, timeFormat, dateTimeString, dateSettings, timeSettings) |
| 84 | +{ |
| 85 | + var date; |
| 86 | + var splitRes = splitDateTime(dateFormat, dateTimeString, dateSettings); |
| 87 | + date = $.datepicker._base_parseDate(dateFormat, splitRes[0], dateSettings); |
| 88 | + if (splitRes[1] != '') |
| 89 | + { |
| 90 | + var timeString = splitRes[1]; |
| 91 | + var separator = timeSettings && timeSettings.separator ? timeSettings.separator : $.timepicker._defaults.separator; |
| 92 | + if ( timeString.indexOf(separator) != 0) |
| 93 | + throw 'Missing time separator'; |
| 94 | + timeString = timeString.substring(separator.length); |
| 95 | + var parsedTime = $.datepicker.parseTime(timeFormat, timeString, timeSettings); |
| 96 | + if (parsedTime === null) |
| 97 | + throw 'Wrong time format'; |
| 98 | + return {date: date, timeObj: parsedTime}; |
| 99 | + } |
| 100 | + else |
| 101 | + return {date: date}; |
| 102 | +} |
25 | 103 | /* Time picker manager.
|
26 | 104 | Use the singleton instance of this class, $.timepicker, to interact with the time picker.
|
27 | 105 | Settings for (groups of) time pickers are maintained in an instance object,
|
@@ -227,110 +305,40 @@ $.extend(Timepicker.prototype, {
|
227 | 305 | // parse the time string from input value or _setTime
|
228 | 306 | //########################################################################
|
229 | 307 | _parseTime: function(timeString, withDate) {
|
230 |
| - var regstr = this._defaults.timeFormat.toString() |
231 |
| - .replace(/h{1,2}/ig, '(\\d?\\d)') |
232 |
| - .replace(/m{1,2}/ig, '(\\d?\\d)') |
233 |
| - .replace(/s{1,2}/ig, '(\\d?\\d)') |
234 |
| - .replace(/l{1}/ig, '(\\d?\\d?\\d)') |
235 |
| - .replace(/t{1,2}/ig, this._getPatternAmpm()) |
236 |
| - .replace(/z{1}/ig, '(z|[-+]\\d\\d:?\\d\\d)?') |
237 |
| - .replace(/\s/g, '\\s?') + this._defaults.timeSuffix + '$', |
238 |
| - order = this._getFormatPositions(), |
239 |
| - ampm = '', |
240 |
| - treg; |
241 |
| - |
242 |
| - if (!this.inst) this.inst = $.datepicker._getInst(this.$input[0]); |
243 |
| - |
244 |
| - if (withDate || !this._defaults.timeOnly) { |
245 |
| - // the time should come after x number of characters and a space. |
246 |
| - // x = at least the length of text specified by the date format |
| 308 | + if (withDate || !this._defaults.timeOnly) |
| 309 | + { |
| 310 | + if (!this.inst) this.inst = $.datepicker._getInst(this.$input[0]); |
247 | 311 | var dp_dateFormat = $.datepicker._get(this.inst, 'dateFormat');
|
248 |
| - // escape special regex characters in the seperator |
249 |
| - var specials = new RegExp("[.*+?|()\\[\\]{}\\\\]", "g"); |
250 |
| - regstr = '^.{' + dp_dateFormat.length + ',}?' + this._defaults.separator.replace(specials, "\\$&") + regstr; |
251 |
| - } |
252 |
| - |
253 |
| - treg = timeString.match(new RegExp(regstr, 'i')); |
254 |
| - |
255 |
| - if (treg) { |
256 |
| - if (order.t !== -1) { |
257 |
| - if (treg[order.t] === undefined || treg[order.t].length === 0) { |
258 |
| - ampm = ''; |
259 |
| - this.ampm = ''; |
260 |
| - } else { |
261 |
| - ampm = $.inArray(treg[order.t].toUpperCase(), this.amNames) !== -1 ? 'AM' : 'PM'; |
262 |
| - this.ampm = this._defaults[ampm == 'AM' ? 'amNames' : 'pmNames'][0]; |
263 |
| - } |
264 |
| - } |
265 |
| - |
266 |
| - if (order.h !== -1) { |
267 |
| - if (ampm == 'AM' && treg[order.h] == '12') |
268 |
| - this.hour = 0; // 12am = 0 hour |
269 |
| - else if (ampm == 'PM' && treg[order.h] != '12') |
270 |
| - this.hour = (parseFloat(treg[order.h]) + 12).toFixed(0); // 12pm = 12 hour, any other pm = hour + 12 |
271 |
| - else this.hour = Number(treg[order.h]); |
272 |
| - } |
273 |
| - |
274 |
| - if (order.m !== -1) this.minute = Number(treg[order.m]); |
275 |
| - if (order.s !== -1) this.second = Number(treg[order.s]); |
276 |
| - if (order.l !== -1) this.millisec = Number(treg[order.l]); |
277 |
| - if (order.z !== -1 && treg[order.z] !== undefined) { |
278 |
| - var tz = treg[order.z].toUpperCase(); |
279 |
| - switch (tz.length) { |
280 |
| - case 1: // Z |
281 |
| - tz = this._defaults.timezoneIso8609 ? 'Z' : '+0000'; |
282 |
| - break; |
283 |
| - case 5: // +hhmm |
284 |
| - if (this._defaults.timezoneIso8609) |
285 |
| - tz = tz.substring(1) == '0000' |
286 |
| - ? 'Z' |
287 |
| - : tz.substring(0, 3) + ':' + tz.substring(3); |
288 |
| - break; |
289 |
| - case 6: // +hh:mm |
290 |
| - if (!this._defaults.timezoneIso8609) |
291 |
| - tz = tz == 'Z' || tz.substring(1) == '00:00' |
292 |
| - ? '+0000' |
293 |
| - : tz.replace(/:/, ''); |
294 |
| - else if (tz.substring(1) == '00:00') |
295 |
| - tz = 'Z'; |
296 |
| - break; |
297 |
| - } |
298 |
| - this.timezone = tz; |
299 |
| - } |
300 |
| - |
301 |
| - return true; |
302 |
| - |
303 |
| - } |
304 |
| - return false; |
| 312 | + try { |
| 313 | + var parseRes = parseDateTimeInternal(dp_dateFormat, this._defaults.timeFormat, timeString, $.datepicker._getFormatConfig(this.inst), this._defaults); |
| 314 | + if (!parseRes.timeObj) return false; |
| 315 | + $.extend(this, parseRes.timeObj); |
| 316 | + } catch (err) |
| 317 | + { |
| 318 | + return false; |
| 319 | + } |
| 320 | + return true; |
| 321 | + } |
| 322 | + else |
| 323 | + { |
| 324 | + var timeObj = $.datepicker.parseTime(this._defaults.timeFormat, timeString, this._defaults); |
| 325 | + $.extend(this, parseRes.timeObj); |
| 326 | + return true; |
| 327 | + } |
305 | 328 | },
|
306 | 329 |
|
307 | 330 | //########################################################################
|
308 | 331 | // pattern for standard and localized AM/PM markers
|
309 | 332 | //########################################################################
|
310 | 333 | _getPatternAmpm: function() {
|
311 |
| - var markers = []; |
312 |
| - o = this._defaults; |
313 |
| - if (o.amNames) |
314 |
| - $.merge(markers, o.amNames); |
315 |
| - if (o.pmNames) |
316 |
| - $.merge(markers, o.pmNames); |
317 |
| - markers = $.map(markers, function(val) { return val.replace(/[.*+?|()\[\]{}\\]/g, '\\$&'); }); |
318 |
| - return '(' + markers.join('|') + ')?'; |
| 334 | + return getPatternAmpm(this._defaults.amNames, this._defaults.pmNames); |
319 | 335 | },
|
320 | 336 |
|
321 | 337 | //########################################################################
|
322 | 338 | // figure out position of time elements.. cause js cant do named captures
|
323 | 339 | //########################################################################
|
324 | 340 | _getFormatPositions: function() {
|
325 |
| - var finds = this._defaults.timeFormat.toLowerCase().match(/(h{1,2}|m{1,2}|s{1,2}|l{1}|t{1,2}|z)/g), |
326 |
| - orders = { h: -1, m: -1, s: -1, l: -1, t: -1, z: -1 }; |
327 |
| - |
328 |
| - if (finds) |
329 |
| - for (var i = 0; i < finds.length; i++) |
330 |
| - if (orders[finds[i].toString().charAt(0)] == -1) |
331 |
| - orders[finds[i].toString().charAt(0)] = i + 1; |
332 |
| - |
333 |
| - return orders; |
| 341 | + return getFormatPositions(this._defaults.timeFormat); |
334 | 342 | },
|
335 | 343 |
|
336 | 344 | //########################################################################
|
@@ -928,6 +936,88 @@ $.fn.extend({
|
928 | 936 | }
|
929 | 937 | });
|
930 | 938 |
|
| 939 | +$.datepicker.parseDateTime = function(dateFormat, timeFormat, dateTimeString, dateSettings, timeSettings) { |
| 940 | + var parseRes = parseDateTimeInternal(dateFormat, timeFormat, dateTimeString, dateSettings, timeSettings); |
| 941 | + if (parseRes.timeObj) |
| 942 | + { |
| 943 | + var t = parseRes.timeObj; |
| 944 | + parseRes.date.setHours(t.hour, t.minute, t.second, t.millisec); |
| 945 | + } |
| 946 | + |
| 947 | + return parseRes.date; |
| 948 | +} |
| 949 | + |
| 950 | +$.datepicker.parseTime = function(timeFormat, timeString, options) { |
| 951 | + var o = extendRemove(extendRemove({}, $.timepicker._defaults), options || {}); |
| 952 | + |
| 953 | + var regstr = '^' + timeFormat.toString() |
| 954 | + .replace(/h{1,2}/ig, '(\\d?\\d)') |
| 955 | + .replace(/m{1,2}/ig, '(\\d?\\d)') |
| 956 | + .replace(/s{1,2}/ig, '(\\d?\\d)') |
| 957 | + .replace(/l{1}/ig, '(\\d?\\d?\\d)') |
| 958 | + .replace(/t{1,2}/ig, getPatternAmpm(o.amNames, o.pmNames)) |
| 959 | + .replace(/z{1}/ig, '(z|[-+]\\d\\d:?\\d\\d)?') |
| 960 | + .replace(/\s/g, '\\s?') + o.timeSuffix + '$', |
| 961 | + order = getFormatPositions(timeFormat), |
| 962 | + ampm = '', |
| 963 | + treg; |
| 964 | + |
| 965 | + treg = timeString.match(new RegExp(regstr, 'i')); |
| 966 | + |
| 967 | + var resTime = {hour: 0, minute: 0, second: 0, millisec: 0}; |
| 968 | + |
| 969 | + if (treg) { |
| 970 | + if (order.t !== -1) { |
| 971 | + if (treg[order.t] === undefined || treg[order.t].length === 0) { |
| 972 | + ampm = ''; |
| 973 | + resTime.ampm = ''; |
| 974 | + } else { |
| 975 | + ampm = $.inArray(treg[order.t], o.amNames) !== -1 ? 'AM' : 'PM'; |
| 976 | + resTime.ampm = o[ampm == 'AM' ? 'amNames' : 'pmNames'][0]; |
| 977 | + } |
| 978 | + } |
| 979 | + |
| 980 | + if (order.h !== -1) { |
| 981 | + if (ampm == 'AM' && treg[order.h] == '12') |
| 982 | + resTime.hour = 0; // 12am = 0 hour |
| 983 | + else if (ampm == 'PM' && treg[order.h] != '12') |
| 984 | + resTime.hour = Number(treg[order.h]) + 12; // 12pm = 12 hour, any other pm = hour + 12 |
| 985 | + else resTime.hour = Number(treg[order.h]); |
| 986 | + } |
| 987 | + |
| 988 | + if (order.m !== -1) resTime.minute = Number(treg[order.m]); |
| 989 | + if (order.s !== -1) resTime.second = Number(treg[order.s]); |
| 990 | + if (order.l !== -1) resTime.millisec = Number(treg[order.l]); |
| 991 | + if (order.z !== -1 && treg[order.z] !== undefined) { |
| 992 | + var tz = treg[order.z].toUpperCase(); |
| 993 | + switch (tz.length) { |
| 994 | + case 1: // Z |
| 995 | + tz = o.timezoneIso8609 ? 'Z' : '+0000'; |
| 996 | + break; |
| 997 | + case 5: // +hhmm |
| 998 | + if (o.timezoneIso8609) |
| 999 | + tz = tz.substring(1) == '0000' |
| 1000 | + ? 'Z' |
| 1001 | + : tz.substring(0, 3) + ':' + tz.substring(3); |
| 1002 | + break; |
| 1003 | + case 6: // +hh:mm |
| 1004 | + if (!o.timezoneIso8609) |
| 1005 | + tz = tz == 'Z' || tz.substring(1) == '00:00' |
| 1006 | + ? '+0000' |
| 1007 | + : tz.replace(/:/, ''); |
| 1008 | + else if (tz.substring(1) == '00:00') |
| 1009 | + tz = 'Z'; |
| 1010 | + break; |
| 1011 | + } |
| 1012 | + resTime.timezone = tz; |
| 1013 | + } |
| 1014 | + |
| 1015 | + return resTime; |
| 1016 | + |
| 1017 | + } |
| 1018 | + return null; |
| 1019 | +}, |
| 1020 | + |
931 | 1021 | //########################################################################
|
932 | 1022 | // format the time all pretty...
|
933 | 1023 | // format = string format of the time
|
@@ -1234,21 +1324,8 @@ $.datepicker._getDateDatepicker = function(target, noDefault) {
|
1234 | 1324 | //#######################################################################################
|
1235 | 1325 | $.datepicker._base_parseDate = $.datepicker.parseDate;
|
1236 | 1326 | $.datepicker.parseDate = function(format, value, settings) {
|
1237 |
| - var date; |
1238 |
| - try { |
1239 |
| - date = this._base_parseDate(format, value, settings); |
1240 |
| - } catch (err) { |
1241 |
| - if (err.indexOf(":") >= 0) { |
1242 |
| - // Hack! The error message ends with a colon, a space, and |
1243 |
| - // the "extra" characters. We rely on that instead of |
1244 |
| - // attempting to perfectly reproduce the parsing algorithm. |
1245 |
| - date = this._base_parseDate(format, value.substring(0,value.length-(err.length-err.indexOf(':')-2)), settings); |
1246 |
| - } else { |
1247 |
| - // The underlying error was not related to the time |
1248 |
| - throw err; |
1249 |
| - } |
1250 |
| - } |
1251 |
| - return date; |
| 1327 | + var splitRes = splitDateTime(dateFormat, dateTimeString, dateSettings); |
| 1328 | + return $.datepicker._base_parseDate(dateFormat, splitRes[0], dateSettings); |
1252 | 1329 | };
|
1253 | 1330 |
|
1254 | 1331 | //#######################################################################################
|
|
0 commit comments