summaryrefslogtreecommitdiff
path: root/addons/web/static/src/js
diff options
context:
space:
mode:
authorMartin Trigaux <mat@openerp.com>2014-01-28 14:37:06 +0100
committerMartin Trigaux <mat@openerp.com>2014-01-28 14:37:06 +0100
commit802d64ca92a31661154e1179b89db78e99ad3645 (patch)
tree15de309d6c916aed5edd97b4dc74e1753bed5bb8 /addons/web/static/src/js
parent3ce5e01eca85cdefe284ee3eb9314291833a7fb5 (diff)
parent5b7ade9db180b8a038c2a9944aba85d1ffd220ea (diff)
[MERGE] [ADD] ways to correctly handle local datetimes in e.g. domains
* Alter datetime.now(), generate a local datetime (add utcnow() which generates a UTC datetime) * Implement datetime.replace() to manipulate local datetimes * Implement date.today(), generates a local date * Implement datetime.toJSON(), returns a javascript Date (assumes datetime attributes are local) * Add conversion hook in JSON and JSONP handlers, automatically converts a Date object to a UTC datetime formatted according to server formats Should allow the generation of correctly working (from the end-user's POV) [Today] filters, amongst other things. Eg: a local expression in a domain for 'Today 00:00:00' would now be expressed as 'datetime.datetime.now().replace(hour=0, minute=0, second=0)' (no .strftime) and will be converted to UTC when sent to the server bzr revid: mat@openerp.com-20140128133706-4yp610pp5w06tcia
Diffstat (limited to 'addons/web/static/src/js')
-rw-r--r--addons/web/static/src/js/openerpframework.js24
-rw-r--r--addons/web/static/src/js/pyeval.js49
2 files changed, 67 insertions, 6 deletions
diff --git a/addons/web/static/src/js/openerpframework.js b/addons/web/static/src/js/openerpframework.js
index 22ca70ebbf7..71f45899f5f 100644
--- a/addons/web/static/src/js/openerpframework.js
+++ b/addons/web/static/src/js/openerpframework.js
@@ -823,13 +823,33 @@ var genericJsonRpc = function(fct_name, params, fct) {
});
};
+/**
+ * Replacer function for JSON.stringify, serializes Date objects to UTC
+ * datetime in the OpenERP Server format.
+ *
+ * However, if a serialized value has a toJSON method that method is called
+ * *before* the replacer is invoked. Date#toJSON exists, and thus the value
+ * passed to the replacer is a string, the original Date has to be fetched
+ * on the parent object (which is provided as the replacer's context).
+ *
+ * @param {String} k
+ * @param {Object} v
+ * @returns {Object}
+ */
+function date_to_utc(k, v) {
+ var value = this[k];
+ if (!(value instanceof Date)) { return v; }
+
+ return openerp.datetime_to_str(value);
+}
+
openerp.jsonRpc = function(url, fct_name, params, settings) {
return genericJsonRpc(fct_name, params, function(data) {
return $.ajax(url, _.extend({}, settings, {
url: url,
dataType: 'json',
type: 'POST',
- data: JSON.stringify(data),
+ data: JSON.stringify(data, date_to_utc),
contentType: 'application/json'
}));
});
@@ -838,7 +858,7 @@ openerp.jsonRpc = function(url, fct_name, params, settings) {
openerp.jsonpRpc = function(url, fct_name, params, settings) {
settings = settings || {};
return genericJsonRpc(fct_name, params, function(data) {
- var payload_str = JSON.stringify(data);
+ var payload_str = JSON.stringify(data, date_to_utc);
var payload_url = $.param({r:payload_str});
var force2step = settings.force2step || false;
delete settings.force2step;
diff --git a/addons/web/static/src/js/pyeval.js b/addons/web/static/src/js/pyeval.js
index b10c175c683..d5499a028b7 100644
--- a/addons/web/static/src/js/pyeval.js
+++ b/addons/web/static/src/js/pyeval.js
@@ -382,13 +382,28 @@
this[key] = asJS(args[key]);
}
},
+ replace: function () {
+ var args = py.PY_parseArgs(arguments, [
+ ['year', py.None], ['month', py.None], ['day', py.None],
+ ['hour', py.None], ['minute', py.None], ['second', py.None],
+ ['microsecond', py.None] // FIXME: tzinfo, can't use None as valid input
+ ]);
+ var params = {};
+ for(var key in args) {
+ if (!args.hasOwnProperty(key)) { continue; }
+
+ var arg = args[key];
+ params[key] = (arg === py.None ? this[key] : asJS(arg));
+ }
+ return py.PY_call(datetime.datetime, params);
+ },
strftime: function () {
var self = this;
var args = py.PY_parseArgs(arguments, 'format');
return py.str.fromJSON(args.format.toJSON()
.replace(/%([A-Za-z])/g, function (m, c) {
switch (c) {
- case 'Y': return self.year;
+ case 'Y': return _.str.sprintf('%04d', self.year);
case 'm': return _.str.sprintf('%02d', self.month);
case 'd': return _.str.sprintf('%02d', self.day);
case 'H': return _.str.sprintf('%02d', self.hour);
@@ -399,6 +414,17 @@
}));
},
now: py.classmethod.fromJSON(function () {
+ var d = new Date;
+ return py.PY_call(datetime.datetime, [
+ d.getFullYear(), d.getMonth() + 1, d.getDate(),
+ d.getHours(), d.getMinutes(), d.getSeconds(),
+ d.getMilliseconds() * 1000]);
+ }),
+ today: py.classmethod.fromJSON(function () {
+ var dt_class = py.PY_getAttr(datetime, 'datetime');
+ return py.PY_call(py.PY_getAttr(dt_class, 'now'));
+ }),
+ utcnow: py.classmethod.fromJSON(function () {
var d = new Date();
return py.PY_call(datetime.datetime,
[d.getUTCFullYear(), d.getUTCMonth() + 1, d.getUTCDate(),
@@ -415,7 +441,17 @@
py.PY_getAttr(args.time, 'minute'),
py.PY_getAttr(args.time, 'second')
]);
- })
+ }),
+ toJSON: function () {
+ return new Date(
+ this.year,
+ this.month - 1,
+ this.day,
+ this.hour,
+ this.minute,
+ this.second,
+ this.microsecond / 1000);
+ },
});
datetime.date = py.type('date', null, {
__init__: function () {
@@ -470,7 +506,12 @@
},
fromJSON: function (year, month, day) {
return py.PY_call(datetime.date, [year, month, day]);
- }
+ },
+ today: py.classmethod.fromJSON(function () {
+ var d = new Date;
+ return py.PY_call(datetime.date, [
+ d.getFullYear(), d.getMonth() + 1, d.getDate()]);
+ }),
});
/**
Returns the current local date, which means the date on the client (which can be different
@@ -501,7 +542,7 @@
time.strftime = py.PY_def.fromJSON(function () {
var args = py.PY_parseArgs(arguments, 'format');
var dt_class = py.PY_getAttr(datetime, 'datetime');
- var d = py.PY_call(py.PY_getAttr(dt_class, 'now'));
+ var d = py.PY_call(py.PY_getAttr(dt_class, 'utcnow'));
return py.PY_call(py.PY_getAttr(d, 'strftime'), [args.format]);
});