[FIX] hopefully, properly uses the user's timezone when performing a readgroup (in orm.py)

bzr revid: ged@openerp.com-20140129084721-6m4cfg087vhqb51d
This commit is contained in:
Gery Debongnie 2014-01-29 09:47:21 +01:00
parent 2fe3861353
commit cffcc5ea18
1 changed files with 22 additions and 5 deletions

View File

@ -47,6 +47,7 @@ import itertools
import logging
import operator
import pickle
import pytz
import re
import simplejson
import time
@ -62,7 +63,7 @@ import fields
import openerp
import openerp.tools as tools
from openerp.tools.config import config
from openerp.tools.misc import CountingStream
from openerp.tools.misc import CountingStream, DEFAULT_SERVER_DATETIME_FORMAT, DEFAULT_SERVER_DATE_FORMAT
from openerp.tools.safe_eval import safe_eval as eval
from openerp.tools.translate import _
from openerp import SUPERUSER_ID
@ -2687,8 +2688,13 @@ class BaseModel(object):
elif interval == 'year':
display_format = 'YYYY'
timezone = context.get('tz', 'UTC')
qualified_groupby_field = "date_trunc('%s',timezone('%s', %s))" % (interval, timezone, qualified_groupby_field)
if groupby_type == 'datetime' and context.get('tz') in pytz.all_timezones:
# Convert groupby result to user TZ to avoid confusion!
# PostgreSQL is compatible with all pytz timezone names, so we can use them
# directly for conversion, starting with timestamps stored in UTC.
timezone = context.get('tz', 'UTC')
qualified_groupby_field = "timezone('%s', timezone('UTC',%s))" % (timezone, qualified_groupby_field)
qualified_groupby_field = "date_trunc('%s', %s)" % (interval, qualified_groupby_field)
flist = "%s as %s " % (qualified_groupby_field, groupby)
elif groupby_type == 'boolean':
qualified_groupby_field = "coalesce(%s,false)" % qualified_groupby_field
@ -2750,11 +2756,15 @@ class BaseModel(object):
if groupby or not context.get('group_by_no_leaf', False):
d['__context'] = {'group_by': groupby_list[1:]}
if groupby and groupby in fget:
if d[groupby] and fget[groupby]['type'] in ('date', 'datetime'):
groupby_type = fget[groupby]['type']
if d[groupby] and groupby_type in ('date', 'datetime'):
groupby_datetime = alldata[d['id']][groupby]
if isinstance(groupby_datetime, basestring):
_default = datetime.datetime(1970, 1, 1) # force starts of month
groupby_datetime = dateutil.parser.parse(groupby_datetime, default=_default)
tz_convert = groupby_type == 'datetime' and context.get('tz') in pytz.all_timezones
if tz_convert:
groupby_datetime = pytz.timezone(context['tz']).localize(groupby_datetime)
d[groupby] = babel.dates.format_date(
groupby_datetime, format=display_format, locale=context.get('lang', 'en_US'))
domain_dt_begin = groupby_datetime
@ -2768,7 +2778,14 @@ class BaseModel(object):
domain_dt_end = groupby_datetime + datetime.timedelta(days=1)
else:
domain_dt_end = groupby_datetime + dateutil.relativedelta.relativedelta(years=1)
d['__domain'] = [(groupby, '>=', domain_dt_begin.strftime('%Y-%m-%d')), (groupby, '<', domain_dt_end.strftime('%Y-%m-%d'))] + domain
if tz_convert:
# the time boundaries were all computed in the apparent TZ of the user,
# so we need to convert them to UTC to have proper server-side values.
domain_dt_begin = domain_dt_begin.astimezone(pytz.utc)
domain_dt_end = domain_dt_end.astimezone(pytz.utc)
dt_format = DEFAULT_SERVER_DATETIME_FORMAT if groupby_type == 'datetime' else DEFAULT_SERVER_DATE_FORMAT
d['__domain'] = [(groupby, '>=', domain_dt_begin.strftime(dt_format)),
(groupby, '<', domain_dt_end.strftime(dt_format))] + domain
del alldata[d['id']][groupby]
d.update(alldata[d['id']])
del d['id']