summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--addons/web/models/ir_http.py3
-rw-r--r--addons/web/static/src/js/core/session.js15
-rw-r--r--addons/web/static/src/js/fields/basic_fields.js6
-rw-r--r--addons/web/static/src/js/fields/field_utils.js6
-rw-r--r--addons/web/static/src/js/views/calendar/calendar_model.js12
-rw-r--r--addons/web/static/tests/fields/basic_fields_tests.js32
-rw-r--r--addons/web/static/tests/fields/field_utils_tests.js26
-rw-r--r--addons/web/static/tests/fields/relational_fields_tests.js4
-rw-r--r--addons/web/static/tests/helpers/test_utils.js7
-rw-r--r--addons/web/static/tests/views/calendar_tests.js16
-rw-r--r--addons/web/static/tests/views/form_tests.js4
-rw-r--r--addons/web/static/tests/views/list_tests.js4
12 files changed, 99 insertions, 36 deletions
diff --git a/addons/web/models/ir_http.py b/addons/web/models/ir_http.py
index 73a83664683..a1fa58ef81d 100644
--- a/addons/web/models/ir_http.py
+++ b/addons/web/models/ir_http.py
@@ -5,8 +5,6 @@ import json
from odoo import models
from odoo.http import request
-import pytz
-import datetime
import odoo
@@ -26,7 +24,6 @@ class Http(models.AbstractModel):
version_info = odoo.service.common.exp_version()
return {
"session_id": request.session.sid,
- "tzOffset": self._context.get('tz') and datetime.datetime.now(pytz.timezone(self._context['tz'])).utcoffset().total_seconds() / 60 or False,
"uid": request.session.uid,
"is_system": request.env.user._is_system(),
"is_superuser": request.env.user._is_superuser(),
diff --git a/addons/web/static/src/js/core/session.js b/addons/web/static/src/js/core/session.js
index c98ff7fbe9a..033d7995c9c 100644
--- a/addons/web/static/src/js/core/session.js
+++ b/addons/web/static/src/js/core/session.js
@@ -285,10 +285,6 @@ var Session = core.Class.extend(mixins.EventDispatcherMixin, {
var result = _.extend({}, window.odoo.session_info);
delete result.session_id;
_.extend(this, result);
- if (this.tzOffset === false) {
- // send by server to have the user timezone and not the browser timezone
- this.tzOffset = -new Date().getTimezoneOffset();
- }
return $.when();
},
check_session_id: function () {
@@ -410,6 +406,17 @@ var Session = core.Class.extend(mixins.EventDispatcherMixin, {
}) ? '' : this.prefix;
return prefix + path + qs;
},
+ /**
+ * Returns the time zone difference (in minutes) from the current locale
+ * (host system settings) to UTC, for a given date. The offset is positive
+ * if the local timezone is behind UTC, and negative if it is ahead.
+ *
+ * @param {string || moment} date a valid string date or moment instance
+ * @returns {integer}
+ */
+ getTZOffset: function (date) {
+ return -new Date(date).getTimezoneOffset();
+ },
});
return Session;
diff --git a/addons/web/static/src/js/fields/basic_fields.js b/addons/web/static/src/js/fields/basic_fields.js
index ec04f67e270..035d24dbdf2 100644
--- a/addons/web/static/src/js/fields/basic_fields.js
+++ b/addons/web/static/src/js/fields/basic_fields.js
@@ -450,7 +450,7 @@ var FieldDateTime = FieldDate.extend({
*/
_getValue: function () {
var value = this.datewidget.getValue();
- return value && value.add(-this.getSession().tzOffset, 'minutes');
+ return value && value.add(-this.getSession().getTZOffset(value), 'minutes');
},
/**
@@ -460,7 +460,7 @@ var FieldDateTime = FieldDate.extend({
* @private
*/
_makeDatePicker: function () {
- var value = this.value && this.value.clone().add(this.getSession().tzOffset, 'minutes');
+ var value = this.value && this.value.clone().add(this.getSession().getTZOffset(this.value), 'minutes');
return new datepicker.DateTimeWidget(this, {defaultDate: value});
},
@@ -471,7 +471,7 @@ var FieldDateTime = FieldDate.extend({
* @private
*/
_renderEdit: function () {
- var value = this.value && this.value.clone().add(this.getSession().tzOffset, 'minutes');
+ var value = this.value && this.value.clone().add(this.getSession().getTZOffset(this.value), 'minutes');
this.datewidget.setValue(value);
this.$input = this.datewidget.$input;
},
diff --git a/addons/web/static/src/js/fields/field_utils.js b/addons/web/static/src/js/fields/field_utils.js
index 787f66080dd..db5cd34d8b9 100644
--- a/addons/web/static/src/js/fields/field_utils.js
+++ b/addons/web/static/src/js/fields/field_utils.js
@@ -97,7 +97,7 @@ function formatDate(value, field, options) {
}
if (field && field.type === 'datetime') {
if (!options || !('timezone' in options) || options.timezone) {
- value = value.clone().add(session.tzOffset, 'minutes');
+ value = value.clone().add(session.getTZOffset(value), 'minutes');
}
}
var l10n = core._t.database.parameters;
@@ -123,7 +123,7 @@ function formatDateTime(value, field, options) {
return "";
}
if (!options || !('timezone' in options) || options.timezone) {
- value = value.clone().add(session.tzOffset, 'minutes');
+ value = value.clone().add(session.getTZOffset(value), 'minutes');
}
var l10n = core._t.database.parameters;
var date_format = time.strftime_to_moment_format(l10n.date_format);
@@ -404,7 +404,7 @@ function parseDateTime(value, field, options) {
} else {
datetime = moment.utc(value, [pattern1, pattern2, moment.ISO_8601], true);
if (options && options.timezone) {
- datetime.add(-session.tzOffset, 'minutes');
+ datetime.add(-session.getTZOffset(datetime), 'minutes');
}
}
if (datetime.isValid()) {
diff --git a/addons/web/static/src/js/views/calendar/calendar_model.js b/addons/web/static/src/js/views/calendar/calendar_model.js
index d2b0c02c524..ed02983d957 100644
--- a/addons/web/static/src/js/views/calendar/calendar_model.js
+++ b/addons/web/static/src/js/views/calendar/calendar_model.js
@@ -65,12 +65,12 @@ return AbstractModel.extend({
end.startOf('day').add(-1, 'days');
} else {
// default hours in the user's timezone
- start.hours(7).add(-this.getSession().tzOffset, 'minutes');
- end.hours(19).add(-this.getSession().tzOffset, 'minutes');
+ start.hours(7).add(-this.getSession().getTZOffset(start), 'minutes');
+ end.hours(19).add(-this.getSession().getTZOffset(end), 'minutes');
}
} else {
- start.add(-this.getSession().tzOffset, 'minutes');
- end.add(-this.getSession().tzOffset, 'minutes');
+ start.add(-this.getSession().getTZOffset(start), 'minutes');
+ end.add(-this.getSession().getTZOffset(end), 'minutes');
}
if (this.mapping.all_day) {
@@ -599,8 +599,8 @@ return AbstractModel.extend({
date_stop = date_start.clone().add(date_delay,'hours');
}
- date_start.add(this.getSession().tzOffset, 'minutes');
- date_stop.add(this.getSession().tzOffset, 'minutes');
+ date_start.add(this.getSession().getTZOffset(date_start), 'minutes');
+ date_stop.add(this.getSession().getTZOffset(date_stop), 'minutes');
if (this.mapping.all_day && evt[this.mapping.all_day]) {
date_stop.add(1, 'days');
diff --git a/addons/web/static/tests/fields/basic_fields_tests.js b/addons/web/static/tests/fields/basic_fields_tests.js
index a1aa5958009..35fa05a8eab 100644
--- a/addons/web/static/tests/fields/basic_fields_tests.js
+++ b/addons/web/static/tests/fields/basic_fields_tests.js
@@ -1589,7 +1589,9 @@ QUnit.module('basic_fields', {
date_format: '%m/%d/%Y',
},
session: {
- tzOffset: 120 // Should be ignored by date fields
+ getTZOffset: function () {
+ return 120; // Should be ignored by date fields
+ },
},
});
@@ -1634,7 +1636,9 @@ QUnit.module('basic_fields', {
date_format: '%m/%d/%Y',
},
session: {
- tzOffset: -120 // Should be ignored by date fields
+ getTZOffset: function () {
+ return -120; // Should be ignored by date fields
+ },
},
});
@@ -1663,7 +1667,9 @@ QUnit.module('basic_fields', {
date_format: '%m/%d/%Y',
},
session: {
- tzOffset: 0
+ getTZOffset: function () {
+ return 0;
+ },
},
});
@@ -1752,7 +1758,9 @@ QUnit.module('basic_fields', {
time_format: '%H:%M:%S',
},
session: {
- tzOffset: 120
+ getTZOffset: function () {
+ return 120;
+ },
},
});
@@ -1809,7 +1817,9 @@ QUnit.module('basic_fields', {
time_format: '%H:%M:%S',
},
session: {
- tzOffset: 120
+ getTZOffset: function () {
+ return 120;
+ },
},
});
@@ -1879,7 +1889,9 @@ QUnit.module('basic_fields', {
time_format: '%H:%M:%S',
},
session: {
- tzOffset: 120
+ getTZOffset: function () {
+ return 120;
+ },
},
});
@@ -1924,7 +1936,9 @@ QUnit.module('basic_fields', {
time_format: '%H:%M:%S',
},
session: {
- tzOffset: -240,
+ getTZOffset: function () {
+ return -240;
+ },
},
});
@@ -1966,7 +1980,9 @@ QUnit.module('basic_fields', {
time_format: '%H:%M:%S',
},
session: {
- tzOffset: -240,
+ getTZOffset: function () {
+ return -240;
+ },
},
});
diff --git a/addons/web/static/tests/fields/field_utils_tests.js b/addons/web/static/tests/fields/field_utils_tests.js
index 922c9f3a79c..a0284798553 100644
--- a/addons/web/static/tests/fields/field_utils_tests.js
+++ b/addons/web/static/tests/fields/field_utils_tests.js
@@ -4,6 +4,7 @@ odoo.define('web.field_utils_tests', function (require) {
var core = require('web.core');
var session = require('web.session');
var fieldUtils = require('web.field_utils');
+var testUtils = require('web.test_utils');
QUnit.module('fields', {}, function () {
@@ -63,6 +64,31 @@ QUnit.test("format_datetime", function (assert) {
assert.strictEqual(str, moment(date).format("MM/DD/YYYY HH:mm:ss"));
});
+QUnit.test("format_datetime (with different timezone offset)", function (assert) {
+ assert.expect(2);
+
+ // mock the date format to avoid issues due to localisation
+ var dateFormat = core._t.database.parameters.date_format;
+ core._t.database.parameters.date_format = '%m/%d/%Y';
+ session.getTZOffset = function (date) {
+ // simulate daylight saving time
+ var startDate = new Date(2017, 2, 26);
+ var endDate = new Date(2017, 9, 29);
+ if (startDate < date && date < endDate) {
+ return 120; // UTC+2
+ } else {
+ return 60; // UTC+1
+ }
+ };
+
+ var str = fieldUtils.format.datetime(moment.utc('2017-01-01T10:00:00Z'));
+ assert.strictEqual(str, '01/01/2017 11:00:00');
+ str = fieldUtils.format.datetime(moment.utc('2017-06-01T10:00:00Z'));
+ assert.strictEqual(str, '06/01/2017 12:00:00');
+
+ core._t.database.parameters.date_format = dateFormat;
+});
+
QUnit.test("format_many2one", function (assert) {
assert.expect(2);
diff --git a/addons/web/static/tests/fields/relational_fields_tests.js b/addons/web/static/tests/fields/relational_fields_tests.js
index fd872fe2ca7..3d6721a55df 100644
--- a/addons/web/static/tests/fields/relational_fields_tests.js
+++ b/addons/web/static/tests/fields/relational_fields_tests.js
@@ -1771,7 +1771,9 @@ QUnit.module('relational_fields', {
'</form>',
res_id: 1,
session: {
- tzOffset: 120
+ getTZOffset: function () {
+ return 120;
+ },
},
});
assert.strictEqual(form.$('td:eq(0)').text(), "01/25/2017",
diff --git a/addons/web/static/tests/helpers/test_utils.js b/addons/web/static/tests/helpers/test_utils.js
index 56070453e31..0115dfc9152 100644
--- a/addons/web/static/tests/helpers/test_utils.js
+++ b/addons/web/static/tests/helpers/test_utils.js
@@ -256,8 +256,11 @@ function addMockEnvironment(widget, params) {
var initialDebounce = DebouncedField.prototype.DEBOUNCE;
DebouncedField.prototype.DEBOUNCE = params.fieldDebounce || 0;
var initialSession, initialConfig, initialParameters;
+ initialSession = _.extend({}, session);
+ session.getTZOffset = function () {
+ return 0; // by default, but may be overriden in specific tests
+ };
if ('session' in params) {
- initialSession = _.extend({}, session);
_.extend(session, params.session);
}
if ('config' in params) {
@@ -282,8 +285,8 @@ function addMockEnvironment(widget, params) {
for (key in session) {
delete session[key];
}
- _.extend(session, initialSession);
}
+ _.extend(session, initialSession);
if ('config' in params) {
for (key in config) {
delete config[key];
diff --git a/addons/web/static/tests/views/calendar_tests.js b/addons/web/static/tests/views/calendar_tests.js
index 6832c71b170..29e76182bb4 100644
--- a/addons/web/static/tests/views/calendar_tests.js
+++ b/addons/web/static/tests/views/calendar_tests.js
@@ -440,7 +440,9 @@ QUnit.module('Views', {
initialDate: initialDate,
},
session: {
- tzOffset: 120
+ getTZOffset: function () {
+ return 120;
+ },
},
mockRPC: function (route, args) {
if (args.method === "create") {
@@ -541,7 +543,9 @@ QUnit.module('Views', {
initialDate: initialDate,
},
session: {
- tzOffset: 120
+ getTZOffset: function () {
+ return 120;
+ },
},
mockRPC: function (route, args) {
if (args.method === "create") {
@@ -664,7 +668,9 @@ QUnit.module('Views', {
initialDate: initialDate,
},
session: {
- tzOffset: 120
+ getTZOffset: function () {
+ return 120;
+ },
},
});
@@ -728,7 +734,9 @@ QUnit.module('Views', {
initialDate: initialDate,
},
session: {
- tzOffset: 120
+ getTZOffset: function () {
+ return 120;
+ },
},
});
diff --git a/addons/web/static/tests/views/form_tests.js b/addons/web/static/tests/views/form_tests.js
index 3a1976592d7..ada05e5ed28 100644
--- a/addons/web/static/tests/views/form_tests.js
+++ b/addons/web/static/tests/views/form_tests.js
@@ -2849,7 +2849,9 @@ QUnit.module('Views', {
'</form>',
res_id: 1,
session: {
- tzOffset: 120
+ getTZOffset: function () {
+ return 120;
+ },
},
});
diff --git a/addons/web/static/tests/views/list_tests.js b/addons/web/static/tests/views/list_tests.js
index 402b59194f8..083aa349516 100644
--- a/addons/web/static/tests/views/list_tests.js
+++ b/addons/web/static/tests/views/list_tests.js
@@ -1271,7 +1271,9 @@ QUnit.module('Views', {
data: this.data,
arch: '<tree><field name="date"/><field name="datetime"/></tree>',
session: {
- tzOffset: 120
+ getTZOffset: function () {
+ return 120;
+ },
},
});