diff --git a/addons/web/static/src/js/fields/basic_fields.js b/addons/web/static/src/js/fields/basic_fields.js index 9f37240e0cc..85cd0382ac2 100644 --- a/addons/web/static/src/js/fields/basic_fields.js +++ b/addons/web/static/src/js/fields/basic_fields.js @@ -282,6 +282,14 @@ var FieldDate = InputField.extend({ // Private //-------------------------------------------------------------------------- + /** + * @override + * @private + */ + _doDebouncedAction: function () { + this.datewidget.change_datetime(); + }, + /** * return the datepicker value * @@ -311,6 +319,16 @@ var FieldDate = InputField.extend({ this.$input = this.datewidget.$input; }, + /** + * FieldDateTime overrides _formatValue to use the session timezone + * + * @override + * @private + * @param {Moment} value + */ + _formatValue: function (value) { + return field_utils.format.date(value, {timezone: true}); + }, }); var FieldDateTime = FieldDate.extend({ diff --git a/addons/web/static/src/js/fields/field_utils.js b/addons/web/static/src/js/fields/field_utils.js index d6677291d47..b00fca0048a 100644 --- a/addons/web/static/src/js/fields/field_utils.js +++ b/addons/web/static/src/js/fields/field_utils.js @@ -60,12 +60,20 @@ function formatChar(value) { * an empty string. Note that this is dependant on the localization settings * * @param {Moment|false} + * @param {Object} [field] + * a description of the field (note: this parameter is ignored) + * @param {Object} [options] additional options + * @param {boolean} [options.timezone=true] use the user timezone when formating the + * date * @returns {string} */ -function formatDate(value) { +function formatDate(value, field, options) { if (!value) { return ""; } + if (!options || !('timezone' in options) || options.timezone) { + value = value.clone().add(session.tzOffset < 0 ? -1 : 0, 'days'); + } var l10n = core._t.database.parameters; var date_format = time.strftime_to_moment_format(l10n.date_format); return value.format(date_format); @@ -77,9 +85,14 @@ function formatDate(value) { * settings * * @params {Moment|false} + * @param {Object} [field] + * a description of the field (note: this parameter is ignored) + * @param {Object} [options] additional options + * @param {boolean} [options.timezone=true] use the user timezone when formating the + * date * @returns {string} */ -function formatDateTime(value, options) { +function formatDateTime(value, field, options) { if (!value) { return ""; } @@ -264,23 +277,32 @@ function formatSelection(value, field) { //////////////////////////////////////////////////////////////////////////////// /** - * create an Date object + * Create an Date object * The method toJSON return the formated value to send value server side * - * @params {string} + * @param {string} + * @param {Object} [field] + * a description of the field (note: this parameter is ignored) + * @param {Object} [options] additional options + * @param {boolean} [options.isUTC] the formatted date is utc + * @param {boolean} [options.timezone=false] format the date after apply the timezone + * offset * @returns {Moment|false} Moment date object */ function parseDate(value, field, options) { if (!value) { return false; } - var date_pattern = time.strftime_to_moment_format(core._t.database.parameters.date_format); - var date_pattern_wo_zero = date_pattern.replace('MM','M').replace('DD','D'); + var datePattern = time.strftime_to_moment_format(core._t.database.parameters.date_format); + var datePatternWoZero = datePattern.replace('MM','M').replace('DD','D'); var date; if (options && options.isUTC) { date = moment.utc(value); } else { - date = moment.utc(value, [date_pattern, date_pattern_wo_zero, moment.ISO_8601], true); + date = moment.utc(value, [datePattern, datePatternWoZero, moment.ISO_8601], true); + if (options && options.timezone) { + date.add(session.tzOffset > 0 ? -1 : 0, 'days'); + } } if (date.isValid() && date.year() >= 1900) { if (date.year() === 0) { @@ -297,22 +319,28 @@ function parseDate(value, field, options) { } /** - * create an Date object + * Create an Date object * The method toJSON return the formated value to send value server side * - * @params {string} + * @param {string} + * @param {Object} [field] + * a description of the field (note: this parameter is ignored) + * @param {Object} [options] additional options + * @param {boolean} [options.isUTC] the formatted date is utc + * @param {boolean} [options.timezone=false] format the date after apply the timezone + * offset * @returns {Moment|false} Moment date object */ function parseDateTime(value, field, options) { if (!value) { return false; } - var date_pattern = time.strftime_to_moment_format(core._t.database.parameters.date_format), - time_pattern = time.strftime_to_moment_format(core._t.database.parameters.time_format); - var date_pattern_wo_zero = date_pattern.replace('MM','M').replace('DD','D'), - time_pattern_wo_zero = time_pattern.replace('HH','H').replace('mm','m').replace('ss','s'); - var pattern1 = date_pattern + ' ' + time_pattern; - var pattern2 = date_pattern_wo_zero + ' ' + time_pattern_wo_zero; + var datePattern = time.strftime_to_moment_format(core._t.database.parameters.date_format), + timePattern = time.strftime_to_moment_format(core._t.database.parameters.time_format); + var datePatternWoZero = datePattern.replace('MM','M').replace('DD','D'), + timePatternWoZero = timePattern.replace('HH','H').replace('mm','m').replace('ss','s'); + var pattern1 = datePattern + ' ' + timePattern; + var pattern2 = datePatternWoZero + ' ' + timePatternWoZero; var datetime; if (options && options.isUTC) { // phatomjs crash if we don't use this format diff --git a/addons/web/static/src/js/widgets/date_picker.js b/addons/web/static/src/js/widgets/date_picker.js index 1641f13f634..1aaf05ee11e 100644 --- a/addons/web/static/src/js/widgets/date_picker.js +++ b/addons/web/static/src/js/widgets/date_picker.js @@ -60,7 +60,8 @@ var DateWidget = Widget.extend({ } }, get_value: function() { - return this.get('value') && this.get('value').clone(); + var value = this.get('value'); + return value && value.clone(); }, set_value_from_ui: function() { var value = this.$input.val() || false; @@ -84,10 +85,10 @@ var DateWidget = Widget.extend({ } }, parse_client: function(v) { - return field_utils.parse[this.type_of_date](v, {timezone: false}); + return field_utils.parse[this.type_of_date](v, null, {timezone: false}); }, format_client: function(v) { - return field_utils.format[this.type_of_date](v, {timezone: false}); + return field_utils.format[this.type_of_date](v, null, {timezone: false}); }, set_datetime_default: function() { //when opening datetimepicker the date and time by default should be the one from diff --git a/addons/web/static/tests/fields/basic_fields_tests.js b/addons/web/static/tests/fields/basic_fields_tests.js index 7d7aabb5617..1dd84ce3dd4 100644 --- a/addons/web/static/tests/fields/basic_fields_tests.js +++ b/addons/web/static/tests/fields/basic_fields_tests.js @@ -1041,7 +1041,10 @@ QUnit.module('basic_fields', { '', translateParameters: { // Avoid issues due to localization formats date_format: '%m/%d/%Y', - } + }, + session: { + tzOffset: 0 + }, }); var $cell = list.$('tr.o_data_row td:not(.o_list_record_selector)').first(); diff --git a/addons/web/static/tests/views/calendar_tests.js b/addons/web/static/tests/views/calendar_tests.js index 7813320af1d..a2347ad801b 100644 --- a/addons/web/static/tests/views/calendar_tests.js +++ b/addons/web/static/tests/views/calendar_tests.js @@ -33,8 +33,10 @@ QUnit.module('Views', { user_id: {string: "user", type: "many2one", relation: 'user'}, parnter_id: {string: "user", type: "many2one", relation: 'partner', related: 'user_id.parnter_id'}, name: {string: "name", type: "char"}, - start: {string: "start", type: "datetime"}, - stop: {string: "stop", type: "datetime"}, + start_date: {string: "start date", type: "date"}, + stop_date: {string: "stop date", type: "date"}, + start: {string: "start datetime", type: "datetime"}, + stop: {string: "stop datetime", type: "datetime"}, allday: {string: "allday", type: "boolean"}, partner_ids: {string: "attendees", type: "one2many", relation: 'partner'}, type: {string: "type", type: "integer"}, @@ -95,32 +97,19 @@ QUnit.module('Views', { QUnit.module('CalendarView'); var archs = { - "event,false,form": { - attrs: {}, - children: [ - { - attrs: {name: "name"}, - children: [], - tag: 'field' - }, - { - attrs: {name: "allday"}, - children: [], - tag: 'field' - }, - { - attrs: {name: "start"}, - children: [], - tag: 'field' - }, - { - attrs: {name: "stop"}, - children: [], - tag: 'field' - } - ], - tag: "form" - }, + "event,false,form": + '
', "event,1,form": { attrs: {}, children: [ @@ -337,10 +326,92 @@ QUnit.module('Views', { }); QUnit.test('create event with timezone in week mode', function (assert) { - assert.expect(8); + assert.expect(4); this.data.event.records = []; + var calendar = createView({ + View: CalendarView, + model: 'event', + data: this.data, + arch: + '