Holger Brunn
11 years ago
6 changed files with 2842 additions and 0 deletions
-
20web_relativedelta/__init__.py
-
78web_relativedelta/__openerp__.py
-
2489web_relativedelta/static/lib/moment.js
-
BINweb_relativedelta/static/src/img/icon.png
-
179web_relativedelta/static/src/js/web_relativedelta.js
-
76web_relativedelta/static/test/web_relativedelta.js
@ -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': [], |
||||
|
}, |
||||
|
} |
2489
web_relativedelta/static/lib/moment.js
File diff suppressed because it is too large
View File
File diff suppressed because it is too large
View File
After Width: 80 | Height: 80 | 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)"); |
||||
|
}); |
||||
|
}); |
Write
Preview
Loading…
Cancel
Save
Reference in new issue