: str_replace(): Passing null to parameter #2 ($replace) of type array|string is deprecated in
tp_inst._defaults.showTimepicker = false;
tp_inst._updateDateTime(inst);
$.datepicker._enableTimepickerDatepicker = function (target) {
var inst = this._getInst(target);
var tp_inst = this._get(inst, 'timepicker');
$(target).datepicker('getDate'); // Init selected[Year|Month|Day]
inst.settings.showTimepicker = true;
tp_inst._defaults.showTimepicker = true;
tp_inst._addTimePicker(inst); // Could be disabled on page load
tp_inst._updateDateTime(inst);
* Create our own set time function
$.datepicker._setTime = function (inst, date) {
var tp_inst = this._get(inst, 'timepicker');
var defaults = tp_inst._defaults;
// calling _setTime with no date sets time to defaults
tp_inst.hour = date ? date.getHours() : defaults.hour;
tp_inst.minute = date ? date.getMinutes() : defaults.minute;
tp_inst.second = date ? date.getSeconds() : defaults.second;
tp_inst.millisec = date ? date.getMilliseconds() : defaults.millisec;
tp_inst.microsec = date ? date.getMicroseconds() : defaults.microsec;
//check if within min/max times..
tp_inst._limitMinMaxDateTime(inst, true);
tp_inst._updateDateTime(inst);
* Create new public method to set only time, callable as $().datepicker('setTime', date)
$.datepicker._setTimeDatepicker = function (target, date, withDate) {
var inst = this._getInst(target);
var tp_inst = this._get(inst, 'timepicker');
this._setDateFromField(inst);
if (typeof date === "string") {
tp_inst._parseTime(date, withDate);
tp_date.setHours(tp_inst.hour, tp_inst.minute, tp_inst.second, tp_inst.millisec);
tp_date.setMicroseconds(tp_inst.microsec);
tp_date = new Date(date.getTime());
tp_date.setMicroseconds(date.getMicroseconds());
if (tp_date.toString() === 'Invalid Date') {
this._setTime(inst, tp_date);
* override setDate() to allow setting time too within Date object
$.datepicker._base_setDateDatepicker = $.datepicker._setDateDatepicker;
$.datepicker._setDateDatepicker = function (target, date) {
var inst = this._getInst(target);
if (typeof(date) === 'string') {
$.timepicker.log("Error creating Date object from string.");
var tp_inst = this._get(inst, 'timepicker');
if (date instanceof Date) {
tp_date = new Date(date.getTime());
tp_date.setMicroseconds(date.getMicroseconds());
// This is important if you are using the timezone option, javascript's Date
// object will only return the timezone offset for the current locale, so we
// adjust it accordingly. If not using timezone option this won't matter..
// If a timezone is different in tp, keep the timezone as is
if (tp_inst && tp_date) {
// look out for DST if tz wasn't specified
if (!tp_inst.support.timezone && tp_inst._defaults.timezone === null) {
tp_inst.timezone = tp_date.getTimezoneOffset() * -1;
date = $.timepicker.timezoneAdjust(date, tp_inst.timezone);
tp_date = $.timepicker.timezoneAdjust(tp_date, tp_inst.timezone);
this._updateDatepicker(inst);
this._base_setDateDatepicker.apply(this, arguments);
this._setTimeDatepicker(target, tp_date, true);
* override getDate() to allow getting time too within Date object
$.datepicker._base_getDateDatepicker = $.datepicker._getDateDatepicker;
$.datepicker._getDateDatepicker = function (target, noDefault) {
var inst = this._getInst(target);
var tp_inst = this._get(inst, 'timepicker');
// if it hasn't yet been defined, grab from field
if (inst.lastVal === undefined) {
this._setDateFromField(inst, noDefault);
var date = this._getDate(inst);
if (date && tp_inst._parseTime($(target).val(), tp_inst.timeOnly)) {
date.setHours(tp_inst.hour, tp_inst.minute, tp_inst.second, tp_inst.millisec);
date.setMicroseconds(tp_inst.microsec);
// This is important if you are using the timezone option, javascript's Date
// object will only return the timezone offset for the current locale, so we
// adjust it accordingly. If not using timezone option this won't matter..
if (tp_inst.timezone != null) {
// look out for DST if tz wasn't specified
if (!tp_inst.support.timezone && tp_inst._defaults.timezone === null) {
tp_inst.timezone = date.getTimezoneOffset() * -1;
date = $.timepicker.timezoneAdjust(date, tp_inst.timezone);
return this._base_getDateDatepicker(target, noDefault);
* override parseDate() because UI 1.8.14 throws an error about "Extra characters"
* An option in datapicker to ignore extra format characters would be nicer.
$.datepicker._base_parseDate = $.datepicker.parseDate;
$.datepicker.parseDate = function (format, value, settings) {
date = this._base_parseDate(format, value, settings);
// Hack! The error message ends with a colon, a space, and
// the "extra" characters. We rely on that instead of
// attempting to perfectly reproduce the parsing algorithm.
if (err.indexOf(":") >= 0) {
date = this._base_parseDate(format, value.substring(0, value.length - (err.length - err.indexOf(':') - 2)), settings);
$.timepicker.log("Error parsing the date string: " + err + "\ndate string = " + value + "\ndate format = " + format);
* override formatDate to set date with time to the input
$.datepicker._base_formatDate = $.datepicker._formatDate;
$.datepicker._formatDate = function (inst, day, month, year) {
var tp_inst = this._get(inst, 'timepicker');
tp_inst._updateDateTime(inst);
return tp_inst.$input.val();
return this._base_formatDate(inst);
* override options setter to add time to maxDate(Time) and minDate(Time). MaxDate
$.datepicker._base_optionDatepicker = $.datepicker._optionDatepicker;
$.datepicker._optionDatepicker = function (target, name, value) {
var inst = this._getInst(target),
var tp_inst = this._get(inst, 'timepicker');
overrides = tp_inst._defaults.evnts,
if (typeof name === 'string') { // if min/max was set with the string
if (name === 'minDate' || name === 'minDateTime') {
} else if (name === 'maxDate' || name === 'maxDateTime') {
} else if (name === 'onSelect') {
} else if (overrides.hasOwnProperty(name)) {
if (typeof (value) === 'undefined') {
name_clone = {}; //empty results in exiting function after overrides updated
} else if (typeof name === 'object') { //if min/max was set with the JSON
} else if (name.minDateTime) {
} else if (name.maxDate) {
} else if (name.maxDateTime) {
for (prop in overrides) {
if (overrides.hasOwnProperty(prop) && name[prop]) {
if (fns.hasOwnProperty(prop)) {
overrides[prop] = fns[prop];
if (!name_clone) { name_clone = $.extend({}, name); }
if (name_clone && isEmptyObject(name_clone)) { return; }
if (min) { //if min was set
tp_inst._defaults.minDate = min;
tp_inst._defaults.minDateTime = min;
} else if (max) { //if max was set
tp_inst._defaults.maxDate = max;
tp_inst._defaults.maxDateTime = max;
tp_inst._defaults.onSelect = onselect;
if (value === undefined) {
return this._base_optionDatepicker.call($.datepicker, target, name);
return this._base_optionDatepicker.call($.datepicker, target, name_clone || name, value);
* jQuery isEmptyObject does not check hasOwnProperty - if someone has added to the object prototype,
* it will return false for all objects
var isEmptyObject = function (obj) {
if (obj.hasOwnProperty(prop)) {
* jQuery extend now ignores nulls!
var extendRemove = function (target, props) {
for (var name in props) {
if (props[name] === null || props[name] === undefined) {
target[name] = props[name];
* Determine by the time format which units are supported
* Returns an object of booleans for each unit
var detectSupport = function (timeFormat) {
var tf = timeFormat.replace(/'.*?'/g, '').toLowerCase(), // removes literals
isIn = function (f, t) { // does the format contain the token?
return f.indexOf(t) !== -1 ? true : false;
ampm: isIn(tf, 't') && isIn(timeFormat, 'h'),
iso8601: isIn(timeFormat, 'Z')
* Converts 24 hour format into 12 hour
* Returns 12 hour without leading 0
var convert24to12 = function (hour) {
var computeEffectiveSetting = function (settings, property) {
return settings && settings[property] ? settings[property] : $.timepicker._defaults[property];
* Splits datetime string into date and time substrings.
* Throws exception when date can't be parsed
* Returns {dateString: dateString, timeString: timeString}
var splitDateTime = function (dateTimeString, timeSettings) {
// The idea is to get the number separator occurrences in datetime and the time format requested (since time has
// fewer unknowns, mostly numbers and am/pm). We will use the time pattern to split.
var separator = computeEffectiveSetting(timeSettings, 'separator'),
format = computeEffectiveSetting(timeSettings, 'timeFormat'),
timeParts = format.split(separator), // how many occurrences of separator may be in our format?
timePartsLen = timeParts.length,
allParts = dateTimeString.split(separator),
allPartsLen = allParts.length;
dateString: allParts.splice(0, allPartsLen - timePartsLen).join(separator),
timeString: allParts.splice(0, timePartsLen).join(separator)
dateString: dateTimeString,
* Internal function to parse datetime interval
* Returns: {date: Date, timeObj: Object}, where
* date - parsed date without time (type Date)
* timeObj = {hour: , minute: , second: , millisec: , microsec: } - parsed time. Optional
var parseDateTimeInternal = function (dateFormat, timeFormat, dateTimeString, dateSettings, timeSettings) {
parts = splitDateTime(dateTimeString, timeSettings);
date = $.datepicker._base_parseDate(dateFormat, parts.dateString, dateSettings);
if (parts.timeString === '') {
parsedTime = $.datepicker.parseTime(timeFormat, parts.timeString, timeSettings);
throw 'Wrong time format';
* Internal function to set timezone_select to the local timezone
var selectLocalTimezone = function (tp_inst, date) {
if (tp_inst && tp_inst.timezone_select) {
var now = date || new Date();
tp_inst.timezone_select.val(-now.getTimezoneOffset());
* Create a Singleton Instance
$.timepicker = new Timepicker();
* Get the timezone offset as string from a date object (eg '+0530' for UTC+5.5)
* @param {number} tzMinutes if not a number, less than -720 (-1200), or greater than 840 (+1400) this value is returned
* @param {boolean} iso8601 if true formats in accordance to iso8601 "+12:45"
$.timepicker.timezoneOffsetString = function (tzMinutes, iso8601) {
if (isNaN(tzMinutes) || tzMinutes > 840 || tzMinutes < -720) {
hours = (off - minutes) / 60,
iso = iso8601 ? ':' : '',
tz = (off >= 0 ? '+' : '-') + ('0' + Math.abs(hours)).slice(-2) + iso + ('0' + Math.abs(minutes)).slice(-2);
* Get the number in minutes that represents a timezone string
* @param {string} tzString formatted like "+0500", "-1245", "Z"
* @return {number} the offset minutes or the original string if it doesn't match expectations
$.timepicker.timezoneOffsetNumber = function (tzString) {
var normalized = tzString.toString().replace(':', ''); // excuse any iso8601, end up with "+1245"
if (normalized.toUpperCase() === 'Z') { // if iso8601 with Z, its 0 minute offset
if (!/^(\-|\+)\d{4}$/.test(normalized)) { // possibly a user defined tz, so just give it back
return ((normalized.substr(0, 1) === '-' ? -1 : 1) * // plus or minus
((parseInt(normalized.substr(1, 2), 10) * 60) + // hours (converted to minutes)
parseInt(normalized.substr(3, 2), 10))); // minutes
* No way to set timezone in js Date, so we must adjust the minutes to compensate. (think setDate, getDate)
* @param {string} toTimezone formatted like "+0500", "-1245"
$.timepicker.timezoneAdjust = function (date, toTimezone) {
var toTz = $.timepicker.timezoneOffsetNumber(toTimezone);
date.setMinutes(date.getMinutes() + -date.getTimezoneOffset() - toTz);
* Calls `timepicker()` on the `startTime` and `endTime` elements, and configures them to
* enforce date range limits.
* n.b. The input value must be correctly formatted (reformatting is not supported)
* @param {Element} startTime
* @param {Element} endTime
* @param {Object} options Options for the timepicker() call
$.timepicker.timeRange = function (startTime, endTime, options) {
return $.timepicker.handleRange('timepicker', startTime, endTime, options);
* Calls `datetimepicker` on the `startTime` and `endTime` elements, and configures them to
* enforce date range limits.
* @param {Element} startTime
* @param {Element} endTime
* @param {Object} options Options for the `timepicker()` call. Also supports `reformat`,
* a boolean value that can be used to reformat the input values to the `dateFormat`.
* @param {string} method Can be used to specify the type of picker to be added