Deal with languages helpfully adding timezones into timestamps

Fixes random (12, 6, 7) hours sometimes added to dates
This commit is contained in:
Nathan Gray 2014-08-18 16:47:27 +00:00
parent 161734f941
commit 5b91e871de
2 changed files with 32 additions and 11 deletions

View File

@ -66,6 +66,12 @@ class etemplate_widget_date extends etemplate_widget_transformer
$value = self::get_array($content, $form_name); $value = self::get_array($content, $form_name);
$valid =& self::get_array($validated, $form_name, true); $valid =& self::get_array($validated, $form_name, true);
// Client / etemplate always deals in 'user time', which has no timezone
// The change to server time is handled elsewhere
// Change to UTC to avoid PHP doing automatic timezone math
$default_tz = date_default_timezone_get();
date_default_timezone_set('UTC');
if ((string)$value === '' && $this->attrs['needed']) if ((string)$value === '' && $this->attrs['needed'])
{ {
self::set_validation_error($form_name,lang('Field must not be empty !!!')); self::set_validation_error($form_name,lang('Field must not be empty !!!'));
@ -92,6 +98,8 @@ class etemplate_widget_date extends etemplate_widget_transformer
// this is not really a user error, but one of the clientside engine // this is not really a user error, but one of the clientside engine
self::set_validation_error($form_name,lang("'%1' is not a valid date !!!", $value).' '.$this->dataformat); self::set_validation_error($form_name,lang("'%1' is not a valid date !!!", $value).' '.$this->dataformat);
} }
date_default_timezone_set($default_tz);
} }
} }
} }

View File

@ -23,6 +23,11 @@
/** /**
* Class which implements the "date" XET-Tag * Class which implements the "date" XET-Tag
* *
* Care must be taken anytime a date from the user is parsed. eTemplate client
* side dates are all in 'user time', which is dealt with on the server and has
* no timezone. Javascript uses the browser's timezone, which affects parsing
* and calculations.
*
* @augments et2_inputWidget * @augments et2_inputWidget
*/ */
var et2_date = et2_inputWidget.extend( var et2_date = et2_inputWidget.extend(
@ -146,7 +151,8 @@ var et2_date = et2_inputWidget.extend(
return; return;
} }
this.set_validation_error(false); this.set_validation_error(false);
this.date.setHours(parsed.hour); // Avoid javascript timezone offset, hour is in 'user time'
this.date.setUTCHours(parsed.hour);
this.date.setMinutes(parsed.minute); this.date.setMinutes(parsed.minute);
this.input_date.val(_value); this.input_date.val(_value);
if(old_value !== this.getValue()) if(old_value !== this.getValue())
@ -173,7 +179,6 @@ var et2_date = et2_inputWidget.extend(
var DTformat = this.options.data_format.split(' '); var DTformat = this.options.data_format.split(' ');
var parsed = jQuery.datepicker.parseDateTime(this.egw().dateTimeFormat(DTformat[0]),this.egw().dateTimeFormat(DTformat[1]), _value); var parsed = jQuery.datepicker.parseDateTime(this.egw().dateTimeFormat(DTformat[0]),this.egw().dateTimeFormat(DTformat[1]), _value);
} }
this.date = new Date(parsed);
} }
else // Parse other date widgets date with timepicker date/time format to date onject else // Parse other date widgets date with timepicker date/time format to date onject
{ {
@ -184,9 +189,12 @@ var et2_date = et2_inputWidget.extend(
this.set_validation_error(this.egw().lang("%1' han an invalid format !!!",_value)); this.set_validation_error(this.egw().lang("%1' han an invalid format !!!",_value));
return; return;
} }
this.date = new Date(parsed);
} }
// Update local variable, but remove the timezone offset that javascript adds
if(parsed)
{
this.date = new Date(parsed.valueOf() - (parsed.getTimezoneOffset()*60*1000));
}
this.set_validation_error(false); this.set_validation_error(false);
} }
@ -204,7 +212,10 @@ var et2_date = et2_inputWidget.extend(
_value = ''; _value = '';
if(this._type != 'date-timeonly') if(this._type != 'date-timeonly')
{ {
_value = jQuery.datepicker.formatDate(this.input_date.datepicker("option","dateFormat"),this.date); _value = jQuery.datepicker.formatDate(this.input_date.datepicker("option","dateFormat"),
// Add timezone offset for datepicker format, or it will lose that many hours
new Date(this.date.valueOf() + (this.date.getTimezoneOffset()*60*1000))
);
} }
if(this._type != 'date') if(this._type != 'date')
{ {
@ -238,12 +249,7 @@ var et2_date = et2_inputWidget.extend(
this.date.setMonth(0); this.date.setMonth(0);
this.date.setFullYear(1970); this.date.setFullYear(1970);
} }
// this is a hack, to work around birthdays changing one day for each time they are stored
// ToDo: either find and fix the reason, or send date as YYYY-mm-dd string to server
else if (this._type == 'date')
{
this.date.setHours(12);
}
// Convert to timestamp - no seconds // Convert to timestamp - no seconds
this.date.setSeconds(0,0); this.date.setSeconds(0,0);
return Math.round(this.date.valueOf() / 1000); return Math.round(this.date.valueOf() / 1000);
@ -645,6 +651,13 @@ var et2_date_ro = et2_valueWidget.extend([et2_IDetachedDOM],
jQuery.datepicker.parseDateTime(this.egw().preference('dateformat'),this.egw().preference('timeformat') == '24' ? 'H:i' : 'g:i a', _value); jQuery.datepicker.parseDateTime(this.egw().preference('dateformat'),this.egw().preference('timeformat') == '24' ? 'H:i' : 'g:i a', _value);
var text = new Date(parsed); var text = new Date(parsed);
// Update local variable, but remove the timezone offset that javascript adds
if(parsed)
{
this.date = new Date(text.valueOf() - (text.getTimezoneOffset()*60*1000));
}
// JS dates use milliseconds // JS dates use milliseconds
this.date.setTime(text.valueOf()); this.date.setTime(text.valueOf());
} }