diff options
| author | Francois Volral <fvo@odoo.com> | 2018-07-09 14:46:45 +0200 |
|---|---|---|
| committer | Francois Volral <fvo@odoo.com> | 2018-08-10 17:21:17 +0200 |
| commit | 4a40db209706a5adae879a2b4349f873b336ccb9 (patch) | |
| tree | 0e39964f2d37412b78eeee8dd56da3b790dc2ed1 /odoo/tools/date_utils.py | |
| parent | 32e232149f5622ac9e14734b92db2eb23330bbd8 (diff) | |
[IMP] orm: add support to fill temporal holes (read_group)
This commit add an extra parameter 'fill_temporal' to read_group which allows
the orm to add missing groups for date intervals. This is useful for charts.
Suppose that we are in a use case where data are grouped by a date fields
(typically months but it could be another interval) and displayed in a Bar Chart
or a Line Char.
Let's says a request has to group records by month for August, September
and ...December. If we don't changed anything, we would get a Bar Chart
looking like this :
___
___ | |
| | | |
| | ___ | |
| || || |
|___||___||___|
Aug Sep D
December follows directly after September, it can be unintuitive for the
user, so we change that. We add some fake records for each missing months
between the earliest and the lastest date of the result
___
___ | |
| | | |
| | ___ | |
| || | | |
|___||___| ___ ___ |___|
Aug Sep Oct Nov Dec
This commit is part of task #1835644
Diffstat (limited to 'odoo/tools/date_utils.py')
| -rw-r--r-- | odoo/tools/date_utils.py | 43 |
1 files changed, 41 insertions, 2 deletions
diff --git a/odoo/tools/date_utils.py b/odoo/tools/date_utils.py index e7d1aa24ffd..55220ced033 100644 --- a/odoo/tools/date_utils.py +++ b/odoo/tools/date_utils.py @@ -1,9 +1,8 @@ # -*- coding: utf-8 -*- - import math import calendar from datetime import date, datetime, time - +import pytz from dateutil.relativedelta import relativedelta from . import ustr @@ -178,3 +177,43 @@ def json_default(obj): return fields.Datetime.to_string(obj) return fields.Date.to_string(obj) return ustr(obj) + +def date_range(start, end, step=relativedelta(months=1)): + """Date range generator with a step interval. + + :param start datetime: begining date of the range. + :param end datetime: ending date of the range. + :param step relativedelta: interval of the range. + :return: a range of datetime from start to end. + :rtype: Iterator[datetime] + """ + + are_naive = start.tzinfo is None and end.tzinfo is None + are_utc = start.tzinfo == pytz.utc and end.tzinfo == pytz.utc + + # Cases with miscellenous timezone are more complexe because of DST. + are_others = start.tzinfo and end.tzinfo and not are_utc + + if are_others: + if start.tzinfo.zone != end.tzinfo.zone: + raise ValueError("Timezones of start argument and end argument seem inconsistent") + + if not are_naive and not are_utc and not are_others: + raise ValueError("Timezones of start argument and end argument mismatch") + + if start > end: + raise ValueError("start > end, start date must be before end") + + if start == start + step: + raise ValueError("Looks like step is null") + + if start.tzinfo: + localize = start.tzinfo.localize + else: + localize = lambda dt: dt + + dt = start.replace(tzinfo=None) + end = end.replace(tzinfo=None) + while dt <= end: + yield localize(dt) + dt = dt + step |
