[ADD] ways to correctly handle local datetimes in e.g. domains
* change datetime.now() to generate user-local naive datetimes * add datetime.utcnow() behaving as the old now() * add date.today() generating a user-local date (for the current day) * add datetime.replace() to replace any specific attribute of the datetime object (except tzinfo, for now) * datetime.toJSON() now returns the equivalent javascript Date object (warning: uses the datetime attributes directly, since datetimes are naive if they were created with utcnow() the Date result is going to be complete nonsense). With the previous commit datetime.now() generates a user-local now() which is converted to the correct UTC datetime when sent to the server. This means it becomes possible to generate datetime bounds for the user's local today with either datetime.datetime.now().replace(hour=0, minute=0, second=0) or datetime.datetime.combine( datetime.date.today(), datetime.time()) and once send over JSON-RPC the server will get the local datetime in UTC to the server's format. nb: user-local means "in the timezone of the user's browser" in this context. bzr revid: xmo@openerp.com-20140122151911-akn1nr6e739eg92s
This commit is contained in:
parent
36eedfab43
commit
5b7ade9db1
|
@ -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]);
|
||||
});
|
||||
|
||||
|
|
|
@ -265,6 +265,41 @@ openerp.testing.section('eval.types', {
|
|||
instance.web.pyeval.context()),
|
||||
"2012-02-14 23:59:59");
|
||||
});
|
||||
test('datetime.tojson', function (instance) {
|
||||
var result = py.eval(
|
||||
'datetime.datetime(2012, 2, 15, 1, 7, 31)',
|
||||
instance.web.pyeval.context());
|
||||
ok(result instanceof Date);
|
||||
equal(result.getFullYear(), 2012);
|
||||
equal(result.getMonth(), 1);
|
||||
equal(result.getDate(), 15);
|
||||
equal(result.getHours(), 1);
|
||||
equal(result.getMinutes(), 7);
|
||||
equal(result.getSeconds(), 31);
|
||||
});
|
||||
test('datetime.combine', function (instance) {
|
||||
var result = py.eval(
|
||||
'datetime.datetime.combine(datetime.date(2012, 2, 15),' +
|
||||
' datetime.time(1, 7, 13))' +
|
||||
' .strftime("%Y-%m-%d %H:%M:%S")',
|
||||
instance.web.pyeval.context());
|
||||
equal(result, "2012-02-15 01:07:13");
|
||||
|
||||
result = py.eval(
|
||||
'datetime.datetime.combine(datetime.date(2012, 2, 15),' +
|
||||
' datetime.time())' +
|
||||
' .strftime("%Y-%m-%d %H:%M:%S")',
|
||||
instance.web.pyeval.context());
|
||||
equal(result, '2012-02-15 00:00:00');
|
||||
});
|
||||
test('datetime.replace', function (instance) {
|
||||
var result = py.eval(
|
||||
'datetime.datetime(2012, 2, 15, 1, 7, 13)' +
|
||||
' .replace(hour=0, minute=0, second=0)' +
|
||||
' .strftime("%Y-%m-%d %H:%M:%S")',
|
||||
instance.web.pyeval.context());
|
||||
equal(result, "2012-02-15 00:00:00");
|
||||
});
|
||||
});
|
||||
openerp.testing.section('eval.edc', {
|
||||
dependencies: ['web.data'],
|
||||
|
|
Loading…
Reference in New Issue