Merge lp:~openerp-dev/openerp-web/trunk-local-today-xmo into lp:openerp-web

Proposed by Xavier (Open ERP)
Status: Merged
Merged at revision: 3919
Proposed branch: lp:~openerp-dev/openerp-web/trunk-local-today-xmo
Merge into: lp:openerp-web
Diff against target: 187 lines (+102/-6)
3 files modified
addons/web/static/src/js/openerpframework.js (+22/-2)
addons/web/static/src/js/pyeval.js (+45/-4)
addons/web/static/test/evals.js (+35/-0)
To merge this branch: bzr merge lp:~openerp-dev/openerp-web/trunk-local-today-xmo
Reviewer Review Type Date Requested Status
Martin Trigaux (OpenERP) Approve
Anaƫl Closson (openerp) Pending
OpenERP R&D Web Team Pending
Review via email: mp+202692@code.launchpad.net

Description of the change

* 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.

(although that may not be absolutely trivial as timedelta and relativedelta currently work only with date objects)

To post a comment you must log in.
Revision history for this message
Martin Trigaux (OpenERP) (mat-openerp) wrote :

Thanks for the patch, merged in trunk

revno: 3919 [merge]
revision-id: <email address hidden>

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'addons/web/static/src/js/openerpframework.js'
2--- addons/web/static/src/js/openerpframework.js 2013-12-18 16:50:33 +0000
3+++ addons/web/static/src/js/openerpframework.js 2014-01-22 15:36:54 +0000
4@@ -823,13 +823,33 @@
5 });
6 };
7
8+/**
9+ * Replacer function for JSON.stringify, serializes Date objects to UTC
10+ * datetime in the OpenERP Server format.
11+ *
12+ * However, if a serialized value has a toJSON method that method is called
13+ * *before* the replacer is invoked. Date#toJSON exists, and thus the value
14+ * passed to the replacer is a string, the original Date has to be fetched
15+ * on the parent object (which is provided as the replacer's context).
16+ *
17+ * @param {String} k
18+ * @param {Object} v
19+ * @returns {Object}
20+ */
21+function date_to_utc(k, v) {
22+ var value = this[k];
23+ if (!(value instanceof Date)) { return v; }
24+
25+ return openerp.datetime_to_str(value);
26+}
27+
28 openerp.jsonRpc = function(url, fct_name, params, settings) {
29 return genericJsonRpc(fct_name, params, function(data) {
30 return $.ajax(url, _.extend({}, settings, {
31 url: url,
32 dataType: 'json',
33 type: 'POST',
34- data: JSON.stringify(data),
35+ data: JSON.stringify(data, date_to_utc),
36 contentType: 'application/json'
37 }));
38 });
39@@ -838,7 +858,7 @@
40 openerp.jsonpRpc = function(url, fct_name, params, settings) {
41 settings = settings || {};
42 return genericJsonRpc(fct_name, params, function(data) {
43- var payload_str = JSON.stringify(data);
44+ var payload_str = JSON.stringify(data, date_to_utc);
45 var payload_url = $.param({r:payload_str});
46 var force2step = settings.force2step || false;
47 delete settings.force2step;
48
49=== modified file 'addons/web/static/src/js/pyeval.js'
50--- addons/web/static/src/js/pyeval.js 2013-08-06 12:50:22 +0000
51+++ addons/web/static/src/js/pyeval.js 2014-01-22 15:36:54 +0000
52@@ -382,13 +382,28 @@
53 this[key] = asJS(args[key]);
54 }
55 },
56+ replace: function () {
57+ var args = py.PY_parseArgs(arguments, [
58+ ['year', py.None], ['month', py.None], ['day', py.None],
59+ ['hour', py.None], ['minute', py.None], ['second', py.None],
60+ ['microsecond', py.None] // FIXME: tzinfo, can't use None as valid input
61+ ]);
62+ var params = {};
63+ for(var key in args) {
64+ if (!args.hasOwnProperty(key)) { continue; }
65+
66+ var arg = args[key];
67+ params[key] = (arg === py.None ? this[key] : asJS(arg));
68+ }
69+ return py.PY_call(datetime.datetime, params);
70+ },
71 strftime: function () {
72 var self = this;
73 var args = py.PY_parseArgs(arguments, 'format');
74 return py.str.fromJSON(args.format.toJSON()
75 .replace(/%([A-Za-z])/g, function (m, c) {
76 switch (c) {
77- case 'Y': return self.year;
78+ case 'Y': return _.str.sprintf('%04d', self.year);
79 case 'm': return _.str.sprintf('%02d', self.month);
80 case 'd': return _.str.sprintf('%02d', self.day);
81 case 'H': return _.str.sprintf('%02d', self.hour);
82@@ -399,6 +414,17 @@
83 }));
84 },
85 now: py.classmethod.fromJSON(function () {
86+ var d = new Date;
87+ return py.PY_call(datetime.datetime, [
88+ d.getFullYear(), d.getMonth() + 1, d.getDate(),
89+ d.getHours(), d.getMinutes(), d.getSeconds(),
90+ d.getMilliseconds() * 1000]);
91+ }),
92+ today: py.classmethod.fromJSON(function () {
93+ var dt_class = py.PY_getAttr(datetime, 'datetime');
94+ return py.PY_call(py.PY_getAttr(dt_class, 'now'));
95+ }),
96+ utcnow: py.classmethod.fromJSON(function () {
97 var d = new Date();
98 return py.PY_call(datetime.datetime,
99 [d.getUTCFullYear(), d.getUTCMonth() + 1, d.getUTCDate(),
100@@ -415,7 +441,17 @@
101 py.PY_getAttr(args.time, 'minute'),
102 py.PY_getAttr(args.time, 'second')
103 ]);
104- })
105+ }),
106+ toJSON: function () {
107+ return new Date(
108+ this.year,
109+ this.month - 1,
110+ this.day,
111+ this.hour,
112+ this.minute,
113+ this.second,
114+ this.microsecond / 1000);
115+ },
116 });
117 datetime.date = py.type('date', null, {
118 __init__: function () {
119@@ -470,7 +506,12 @@
120 },
121 fromJSON: function (year, month, day) {
122 return py.PY_call(datetime.date, [year, month, day]);
123- }
124+ },
125+ today: py.classmethod.fromJSON(function () {
126+ var d = new Date;
127+ return py.PY_call(datetime.date, [
128+ d.getFullYear(), d.getMonth() + 1, d.getDate()]);
129+ }),
130 });
131 /**
132 Returns the current local date, which means the date on the client (which can be different
133@@ -501,7 +542,7 @@
134 time.strftime = py.PY_def.fromJSON(function () {
135 var args = py.PY_parseArgs(arguments, 'format');
136 var dt_class = py.PY_getAttr(datetime, 'datetime');
137- var d = py.PY_call(py.PY_getAttr(dt_class, 'now'));
138+ var d = py.PY_call(py.PY_getAttr(dt_class, 'utcnow'));
139 return py.PY_call(py.PY_getAttr(d, 'strftime'), [args.format]);
140 });
141
142
143=== modified file 'addons/web/static/test/evals.js'
144--- addons/web/static/test/evals.js 2013-08-06 12:26:23 +0000
145+++ addons/web/static/test/evals.js 2014-01-22 15:36:54 +0000
146@@ -265,6 +265,41 @@
147 instance.web.pyeval.context()),
148 "2012-02-14 23:59:59");
149 });
150+ test('datetime.tojson', function (instance) {
151+ var result = py.eval(
152+ 'datetime.datetime(2012, 2, 15, 1, 7, 31)',
153+ instance.web.pyeval.context());
154+ ok(result instanceof Date);
155+ equal(result.getFullYear(), 2012);
156+ equal(result.getMonth(), 1);
157+ equal(result.getDate(), 15);
158+ equal(result.getHours(), 1);
159+ equal(result.getMinutes(), 7);
160+ equal(result.getSeconds(), 31);
161+ });
162+ test('datetime.combine', function (instance) {
163+ var result = py.eval(
164+ 'datetime.datetime.combine(datetime.date(2012, 2, 15),' +
165+ ' datetime.time(1, 7, 13))' +
166+ ' .strftime("%Y-%m-%d %H:%M:%S")',
167+ instance.web.pyeval.context());
168+ equal(result, "2012-02-15 01:07:13");
169+
170+ result = py.eval(
171+ 'datetime.datetime.combine(datetime.date(2012, 2, 15),' +
172+ ' datetime.time())' +
173+ ' .strftime("%Y-%m-%d %H:%M:%S")',
174+ instance.web.pyeval.context());
175+ equal(result, '2012-02-15 00:00:00');
176+ });
177+ test('datetime.replace', function (instance) {
178+ var result = py.eval(
179+ 'datetime.datetime(2012, 2, 15, 1, 7, 13)' +
180+ ' .replace(hour=0, minute=0, second=0)' +
181+ ' .strftime("%Y-%m-%d %H:%M:%S")',
182+ instance.web.pyeval.context());
183+ equal(result, "2012-02-15 00:00:00");
184+ });
185 });
186 openerp.testing.section('eval.edc', {
187 dependencies: ['web.data'],