mirror of https://github.com/OCA/web.git
Merge pull request #15 from hbrunn/7.0-web_relativedelta_squashed
[ADD] web_relativedeltapull/53/head
commit
c1f1221612
|
@ -0,0 +1,20 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
##############################################################################
|
||||||
|
#
|
||||||
|
# OpenERP, Open Source Management Solution
|
||||||
|
# This module copyright (C) 2014 Therp BV (<http://therp.nl>).
|
||||||
|
#
|
||||||
|
# This program is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU Affero General Public License as
|
||||||
|
# published by the Free Software Foundation, either version 3 of the
|
||||||
|
# License, or (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU Affero General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU Affero General Public License
|
||||||
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
#
|
||||||
|
##############################################################################
|
|
@ -0,0 +1,78 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
##############################################################################
|
||||||
|
#
|
||||||
|
# OpenERP, Open Source Management Solution
|
||||||
|
# This module copyright (C) 2014 Therp BV (<http://therp.nl>).
|
||||||
|
#
|
||||||
|
# This program is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU Affero General Public License as
|
||||||
|
# published by the Free Software Foundation, either version 3 of the
|
||||||
|
# License, or (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU Affero General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU Affero General Public License
|
||||||
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
#
|
||||||
|
##############################################################################
|
||||||
|
{
|
||||||
|
"name": "More pythonic relativedelta",
|
||||||
|
"version": "1.0",
|
||||||
|
"author": "Therp BV",
|
||||||
|
"license": "AGPL-3",
|
||||||
|
"complexity": "normal",
|
||||||
|
"description": """
|
||||||
|
Introduction
|
||||||
|
============
|
||||||
|
|
||||||
|
This addon provides a reimplementation of OpenERP's pyjs relativedelta class
|
||||||
|
using Moment.js (http://momentjs.com).
|
||||||
|
|
||||||
|
On top of what you can do with the original, you can use
|
||||||
|
|
||||||
|
- datetime objects
|
||||||
|
- relativedelta(hour=0-23, hours=0-23)
|
||||||
|
- relativedelta(minute=0-59, minutes=0-59)
|
||||||
|
- relativedelta(seconds=0-59, seconds=0-59)
|
||||||
|
- relativedelta(weekday=0) [MO] ... weekday=6 [SU]
|
||||||
|
|
||||||
|
- there's no MO(+n) syntax, but that can be simulated by
|
||||||
|
relativedelta(weeks=+(n-1), days=1, weekday=0), this week's monday would
|
||||||
|
be relativedelta(weeks=-1, days=1, weekday=0) etc.
|
||||||
|
|
||||||
|
- all of them together in a predictable manner as detailed in
|
||||||
|
https://labix.org/python-dateutil#head-72c4689ec5608067d118b9143cef6bdffb6dad4e
|
||||||
|
|
||||||
|
Usage
|
||||||
|
=====
|
||||||
|
|
||||||
|
Simply depend on web_relativedelta and enjoy most of python's relativedelta
|
||||||
|
functionality
|
||||||
|
""",
|
||||||
|
"category": "Dependency",
|
||||||
|
"depends": [
|
||||||
|
'web',
|
||||||
|
],
|
||||||
|
"data": [
|
||||||
|
],
|
||||||
|
"js": [
|
||||||
|
'static/lib/moment.js',
|
||||||
|
'static/src/js/web_relativedelta.js'
|
||||||
|
],
|
||||||
|
"css": [
|
||||||
|
],
|
||||||
|
"qweb": [
|
||||||
|
],
|
||||||
|
"test": [
|
||||||
|
'static/test/web_relativedelta.js',
|
||||||
|
],
|
||||||
|
"auto_install": False,
|
||||||
|
"installable": True,
|
||||||
|
"application": False,
|
||||||
|
"external_dependencies": {
|
||||||
|
'python': [],
|
||||||
|
},
|
||||||
|
}
|
File diff suppressed because it is too large
Load Diff
Binary file not shown.
After Width: | Height: | Size: 7.8 KiB |
|
@ -0,0 +1,179 @@
|
||||||
|
//-*- coding: utf-8 -*-
|
||||||
|
//############################################################################
|
||||||
|
//
|
||||||
|
// OpenERP, Open Source Management Solution
|
||||||
|
// This module copyright (C) 2014 Therp BV (<http://therp.nl>).
|
||||||
|
//
|
||||||
|
// This program is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU Affero General Public License as
|
||||||
|
// published by the Free Software Foundation, either version 3 of the
|
||||||
|
// License, or (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU Affero General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU Affero General Public License
|
||||||
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
//
|
||||||
|
//############################################################################
|
||||||
|
|
||||||
|
openerp.web_relativedelta = function(openerp)
|
||||||
|
{
|
||||||
|
var relativedelta = py.type('relativedelta', null,
|
||||||
|
{
|
||||||
|
__init__: function()
|
||||||
|
{
|
||||||
|
this.ops = py.PY_parseArgs(
|
||||||
|
arguments,
|
||||||
|
[
|
||||||
|
['year', null],
|
||||||
|
['years', null],
|
||||||
|
['month', null],
|
||||||
|
['months', null],
|
||||||
|
['day', null],
|
||||||
|
['days', null],
|
||||||
|
['hour', null],
|
||||||
|
['hours', null],
|
||||||
|
['minute', null],
|
||||||
|
['minutes', null],
|
||||||
|
['second', null],
|
||||||
|
['seconds', null],
|
||||||
|
['weeks', null],
|
||||||
|
['weekday', null],
|
||||||
|
]);
|
||||||
|
},
|
||||||
|
__add__: function(other)
|
||||||
|
{
|
||||||
|
if(other.__name__ != 'date' && other.__name__ != 'datetime')
|
||||||
|
{
|
||||||
|
return py.NotImplemented;
|
||||||
|
}
|
||||||
|
|
||||||
|
var result = moment({
|
||||||
|
year: other.year,
|
||||||
|
//january==0 in moment.js
|
||||||
|
month: other.month - 1,
|
||||||
|
day: other.day,
|
||||||
|
hour: other.hour,
|
||||||
|
minute: other.minute,
|
||||||
|
second: other.second});
|
||||||
|
|
||||||
|
if(this.ops.year)
|
||||||
|
{
|
||||||
|
result.year(Math.abs(this.ops.year._value));
|
||||||
|
}
|
||||||
|
if(this.ops.years)
|
||||||
|
{
|
||||||
|
result.add('years', this.ops.years._value);
|
||||||
|
}
|
||||||
|
if(this.ops.month)
|
||||||
|
{
|
||||||
|
//january==0 in moment.js
|
||||||
|
result.month(Math.abs(this.ops.month._value % 13) - 1);
|
||||||
|
}
|
||||||
|
if(this.ops.months)
|
||||||
|
{
|
||||||
|
result.add('months', this.ops.months._value);
|
||||||
|
}
|
||||||
|
if(this.ops.day)
|
||||||
|
{
|
||||||
|
result = result.clone()
|
||||||
|
.endOf('month')
|
||||||
|
.hours(result.hours())
|
||||||
|
.minutes(result.minutes())
|
||||||
|
.seconds(result.seconds())
|
||||||
|
.max(result.clone()
|
||||||
|
.date(Math.abs(this.ops.day._value)));
|
||||||
|
}
|
||||||
|
if(this.ops.days)
|
||||||
|
{
|
||||||
|
result.add('days', this.ops.days._value)
|
||||||
|
}
|
||||||
|
if(this.ops.weeks)
|
||||||
|
{
|
||||||
|
result.add('days', this.ops.weeks._value * 7);
|
||||||
|
}
|
||||||
|
if(this.ops.hour)
|
||||||
|
{
|
||||||
|
result.hour(Math.abs(this.ops.hour._value % 24));
|
||||||
|
}
|
||||||
|
if(this.ops.hours)
|
||||||
|
{
|
||||||
|
result.add('hours', this.ops.hours._value);
|
||||||
|
}
|
||||||
|
if(this.ops.minute)
|
||||||
|
{
|
||||||
|
result.minute(Math.abs(this.ops.minute._value % 60));
|
||||||
|
}
|
||||||
|
if(this.ops.minutes)
|
||||||
|
{
|
||||||
|
result.add('minutes', this.ops.minutes._value);
|
||||||
|
}
|
||||||
|
if(this.ops.second)
|
||||||
|
{
|
||||||
|
result.second(Math.abs(this.ops.second._value % 60));
|
||||||
|
}
|
||||||
|
if(this.ops.seconds)
|
||||||
|
{
|
||||||
|
result.add('seconds', this.ops.seconds._value);
|
||||||
|
}
|
||||||
|
if(this.ops.weekday)
|
||||||
|
{
|
||||||
|
//in relativedelta, 0=MO, but in iso, 1=MO
|
||||||
|
var isoWeekday = Math.abs(this.ops.weekday._value || 1) /
|
||||||
|
(this.ops.weekday._value || 1) *
|
||||||
|
(Math.abs(this.ops.weekday._value) + 1),
|
||||||
|
originalIsoWeekday = result.isoWeekday();
|
||||||
|
result.isoWeekday(isoWeekday).add(
|
||||||
|
'weeks', isoWeekday < originalIsoWeekday ? 1 : 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
var args = [
|
||||||
|
result.year(),
|
||||||
|
//january==0 in moment.js
|
||||||
|
result.month() + 1,
|
||||||
|
result.date(),
|
||||||
|
];
|
||||||
|
if(other.__name__ == 'datetime')
|
||||||
|
{
|
||||||
|
args.push(result.hour());
|
||||||
|
args.push(result.minute());
|
||||||
|
args.push(result.second());
|
||||||
|
}
|
||||||
|
|
||||||
|
return py.PY_call(Object.getPrototypeOf(other), args);
|
||||||
|
},
|
||||||
|
__radd__: function(other)
|
||||||
|
{
|
||||||
|
return this.__add__(other);
|
||||||
|
},
|
||||||
|
__sub__: function(other)
|
||||||
|
{
|
||||||
|
_.each(this.ops, function(op, name)
|
||||||
|
{
|
||||||
|
if(!op || name == 'weekday')
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
op._value = -op._value;
|
||||||
|
});
|
||||||
|
return this.__add__(other);
|
||||||
|
},
|
||||||
|
__rsub__: function(other)
|
||||||
|
{
|
||||||
|
return this.__sub__(other);
|
||||||
|
},
|
||||||
|
});
|
||||||
|
var original_pyeval_context = openerp.web.pyeval.context;
|
||||||
|
openerp.web.pyeval.context = function ()
|
||||||
|
{
|
||||||
|
var ctx = original_pyeval_context();
|
||||||
|
return _.extend(
|
||||||
|
ctx,
|
||||||
|
{
|
||||||
|
relativedelta: relativedelta,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,76 @@
|
||||||
|
//-*- coding: utf-8 -*-
|
||||||
|
//############################################################################
|
||||||
|
//
|
||||||
|
// OpenERP, Open Source Management Solution
|
||||||
|
// This module copyright (C) 2014 Therp BV (<http://therp.nl>).
|
||||||
|
//
|
||||||
|
// This program is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU Affero General Public License as
|
||||||
|
// published by the Free Software Foundation, either version 3 of the
|
||||||
|
// License, or (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU Affero General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU Affero General Public License
|
||||||
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
//
|
||||||
|
//############################################################################
|
||||||
|
|
||||||
|
openerp.testing.section(
|
||||||
|
'python_compatibility',
|
||||||
|
{dependencies: ['web.coresetup', 'web.pyeval']},
|
||||||
|
function(test)
|
||||||
|
{
|
||||||
|
test('basic deltas', function(instance)
|
||||||
|
{
|
||||||
|
openerp.web_relativedelta(instance);
|
||||||
|
var eval = function(expression)
|
||||||
|
{
|
||||||
|
var result_domain = instance.web.pyeval.eval(
|
||||||
|
'domain', "[['a', '=', " + expression + "]]", {}, {});
|
||||||
|
return result_domain[0][2];
|
||||||
|
}
|
||||||
|
|
||||||
|
var result;
|
||||||
|
|
||||||
|
result = eval(
|
||||||
|
"(datetime.date(2012, 12, 25) + relativedelta(days=7)).strftime('%Y-%m-%d')");
|
||||||
|
ok(result == '2013-01-01', "cross year");
|
||||||
|
|
||||||
|
result = eval(
|
||||||
|
//2012 is a leap year
|
||||||
|
"(datetime.date(2012, 01, 01) + relativedelta(days=366)).strftime('%Y-%m-%d')");
|
||||||
|
ok(result == '2013-01-01', "cross leap year");
|
||||||
|
|
||||||
|
result = eval(
|
||||||
|
"(datetime.date(2012, 02, 01) + relativedelta(day=366)).strftime('%Y-%m-%d')");
|
||||||
|
ok(result == '2012-02-29', "absolute day");
|
||||||
|
|
||||||
|
result = eval(
|
||||||
|
"(datetime.date(2012, 02, 01) + relativedelta(hours=-1)).strftime('%Y-%m-%d')");
|
||||||
|
ok(result == '2012-01-31', "negative hour");
|
||||||
|
|
||||||
|
result = eval(
|
||||||
|
"(datetime.date(2012, 01, 30) + relativedelta(weekday=0)).strftime('%Y-%m-%d')");
|
||||||
|
ok(result == '2012-01-30', "weekday=MO (on monday)");
|
||||||
|
|
||||||
|
result = eval(
|
||||||
|
"(datetime.date(2012, 01, 31) + relativedelta(weekday=0)).strftime('%Y-%m-%d')");
|
||||||
|
ok(result == '2012-02-06', "weekday=MO (on tuesday)");
|
||||||
|
|
||||||
|
result = eval(
|
||||||
|
"(datetime.date(2012, 01, 30) + relativedelta(weeks=-1, days=1, weekday=0)).strftime('%Y-%m-%d')");
|
||||||
|
ok(result == '2012-01-30', "last monday (on monday)");
|
||||||
|
|
||||||
|
result = eval(
|
||||||
|
"(datetime.date(2012, 01, 31) + relativedelta(weeks=-1, days=1, weekday=0)).strftime('%Y-%m-%d')");
|
||||||
|
ok(result == '2012-01-30', "last monday (on tuesday)");
|
||||||
|
|
||||||
|
result = eval(
|
||||||
|
"(datetime.date(2012, 02, 01) + relativedelta(weeks=-1, days=1, weekday=0)).strftime('%Y-%m-%d')");
|
||||||
|
ok(result == '2012-01-30', "last monday (on wednesday)");
|
||||||
|
});
|
||||||
|
});
|
Loading…
Reference in New Issue