[ADD] tools.misc: added method to compute client timestamp according to timezone, for example for inclusion in strings where it will not be formatted by the client (do NOT use it when returning date[time] field values to the client!) + refactored timezone_get service method to make it accessible in tools.

bzr revid: odo@openerp.com-20100727152211-mupv9tdhbpv48nvu
This commit is contained in:
Olivier Dony 2010-07-27 17:22:11 +02:00
parent a7aebd3489
commit a736c6e17f
2 changed files with 60 additions and 7 deletions

View File

@ -438,11 +438,7 @@ GNU Public Licence.
return info
def exp_timezone_get(self, db, login, password):
#timezone detection is safe in multithread, so lazy init is ok here
if (not tools.config['timezone']):
tools.config['timezone'] = tools.misc.detect_server_timezone()
return tools.config['timezone']
return tools.misc.get_server_timezone()
def exp_get_available_updates(self, contract_id, contract_password):
import tools.maintenance as tm

View File

@ -26,6 +26,7 @@ Miscelleanous tools used by OpenERP.
import os, time, sys
import inspect
from datetime import datetime
from config import config
@ -48,7 +49,6 @@ from email.Utils import formatdate, COMMASPACE
from email import Encoders
import netsvc
if sys.version_info[:2] < (2, 4):
from threadinglocal import local
else:
@ -1250,7 +1250,7 @@ def get_win32_timezone():
res = str(_winreg.QueryValueEx(current_tz_key,"StandardName")[0]) # [0] is value, [1] is type code
_winreg.CloseKey(current_tz_key)
_winreg.CloseKey(hklm)
except:
except Exception:
pass
return res
@ -1309,6 +1309,63 @@ def detect_server_timezone():
"No valid timezone could be detected, using default UTC timezone. You can specify it explicitly with option 'timezone' in the server configuration.")
return 'UTC'
def get_server_timezone():
# timezone detection is safe in multithread, so lazy init is ok here
if (not config['timezone']):
config['timezone'] = detect_server_timezone()
return config['timezone']
DEFAULT_SERVER_DATE_FORMAT = "%Y-%m-%d"
DEFAULT_SERVER_DATETIME_FORMAT = DEFAULT_SERVER_DATE_FORMAT + " %H:%M:%S"
def server_to_local_timestamp(src_tstamp_str, src_format, dst_format, dst_tz_name,
tz_offset=True, ignore_unparsable_time=True):
"""
Convert a source timestamp string into a destination timestamp string, attempting to apply the
correct offset if both the server and local timezone are recognized, or no
offset at all if they aren't or if tz_offset is false (i.e. assuming they are both in the same TZ).
WARNING: This method is here to allow formatting dates correctly for inclusion in strings where
the client would not be able to format/offset it correctly. DO NOT use it for returning
date fields directly, these are supposed to be handled by the client!!
@param src_tstamp_str: the str value containing the timestamp in the server timezone.
@param src_format: the format to use when parsing the server timestamp.
@param dst_format: the format to use when formatting the resulting timestamp for the local/client timezone.
@param dst_tz_name: name of the destination timezone (such as the 'tz' value of the client context)
@param ignore_unparsable_time: if True, return False if src_tstamp_str cannot be parsed
using src_format or formatted using dst_format.
@return: local/client formatted timestamp, expressed in the local/client timezone if possible
and if tz_offset is true, or src_tstamp_str if timezone offset could not be determined.
"""
if not src_tstamp_str:
return False
res = src_tstamp_str
if src_format and dst_format:
# find out server timezone
server_tz = get_server_timezone()
try:
# dt_value needs to be a datetime.datetime object (so no time.struct_time or mx.DateTime.DateTime here!)
dt_value = datetime.strptime(src_tstamp_str, src_format)
if tz_offset and dst_tz_name:
try:
import pytz
src_tz = pytz.timezone(server_tz)
dst_tz = pytz.timezone(dst_tz_name)
src_dt = src_tz.localize(dt_value, is_dst=True)
dt_value = src_dt.astimezone(dst_tz)
except Exception:
pass
res = dt_value.strftime(dst_format)
except Exception:
# Normal ways to end up here are if strptime or strftime failed
if not ignore_unparsable_time:
return False
return res
def split_every(n, iterable, piece_maker=tuple):
"""Splits an iterable into length-n pieces. The last piece will be shorter