Skip to content

Commit e7c7d40

Browse files
committed
Add $.datepicker.parseDateTime(), $.datepicker.parseTime() functions
1 parent 610129e commit e7c7d40

File tree

1 file changed

+183
-106
lines changed

1 file changed

+183
-106
lines changed

jquery-ui-timepicker-addon.js

Lines changed: 183 additions & 106 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,84 @@
2222

2323
$.extend($.ui, { timepicker: { version: "1.0.0" } });
2424

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+
}
25103
/* Time picker manager.
26104
Use the singleton instance of this class, $.timepicker, to interact with the time picker.
27105
Settings for (groups of) time pickers are maintained in an instance object,
@@ -227,110 +305,40 @@ $.extend(Timepicker.prototype, {
227305
// parse the time string from input value or _setTime
228306
//########################################################################
229307
_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]);
247311
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+
}
305328
},
306329

307330
//########################################################################
308331
// pattern for standard and localized AM/PM markers
309332
//########################################################################
310333
_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);
319335
},
320336

321337
//########################################################################
322338
// figure out position of time elements.. cause js cant do named captures
323339
//########################################################################
324340
_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);
334342
},
335343

336344
//########################################################################
@@ -928,6 +936,88 @@ $.fn.extend({
928936
}
929937
});
930938

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+
9311021
//########################################################################
9321022
// format the time all pretty...
9331023
// format = string format of the time
@@ -1234,21 +1324,8 @@ $.datepicker._getDateDatepicker = function(target, noDefault) {
12341324
//#######################################################################################
12351325
$.datepicker._base_parseDate = $.datepicker.parseDate;
12361326
$.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);
12521329
};
12531330

12541331
//#######################################################################################

0 commit comments

Comments
 (0)