[ADD] formats support to date and datetime converters
bzr revid: xmo@openerp.com-20131202073313-tu79esduu5bvyaai
This commit is contained in:
parent
c457c2197a
commit
228938ccba
|
@ -627,14 +627,21 @@ class DateConverter(osv.AbstractModel):
|
|||
def value_to_html(self, cr, uid, value, column, options=None, context=None):
|
||||
if not value: return ''
|
||||
lang = self.user_lang(cr, uid, context=context)
|
||||
|
||||
out_format = lang.date_format.encode('utf-8')
|
||||
locale = babel.Locale.parse(lang.code)
|
||||
|
||||
if isinstance(value, basestring):
|
||||
value = datetime.datetime.strptime(
|
||||
value, openerp.tools.DEFAULT_SERVER_DATE_FORMAT)
|
||||
|
||||
return value.strftime(out_format)
|
||||
if options and 'format' in options:
|
||||
pattern = options['format']
|
||||
else:
|
||||
strftime_pattern = lang.date_format
|
||||
pattern = openerp.tools.posix_to_ldml(strftime_pattern, locale=locale)
|
||||
|
||||
return babel.dates.format_datetime(
|
||||
value, format=pattern,
|
||||
locale=locale)
|
||||
|
||||
class DateTimeConverter(osv.AbstractModel):
|
||||
_name = 'ir.qweb.field.datetime'
|
||||
|
@ -643,17 +650,21 @@ class DateTimeConverter(osv.AbstractModel):
|
|||
def value_to_html(self, cr, uid, value, column, options=None, context=None):
|
||||
if not value: return ''
|
||||
lang = self.user_lang(cr, uid, context=context)
|
||||
|
||||
out_format = (u"%s %s" % (lang.date_format, lang.time_format)).encode('utf-8')
|
||||
locale = babel.Locale.parse(lang.code)
|
||||
|
||||
if isinstance(value, basestring):
|
||||
value = datetime.datetime.strptime(
|
||||
value, openerp.tools.DEFAULT_SERVER_DATETIME_FORMAT)
|
||||
|
||||
value = column.context_timestamp(
|
||||
cr, uid, timestamp=value, context=context)
|
||||
|
||||
return value.strftime(out_format)
|
||||
if options and 'format' in options:
|
||||
pattern = options['format']
|
||||
else:
|
||||
strftime_pattern = (u"%s %s" % (lang.date_format, lang.time_format))
|
||||
pattern = openerp.tools.posix_to_ldml(strftime_pattern, locale=locale)
|
||||
|
||||
return babel.dates.format_datetime(value, format=pattern, locale=locale)
|
||||
|
||||
class TextConverter(osv.AbstractModel):
|
||||
_name = 'ir.qweb.field.text'
|
||||
|
|
|
@ -304,6 +304,22 @@ class TestDatetimeExport(TestBasicExport):
|
|||
# default lang/format is US
|
||||
self.assertEqual(value, '05/03/2011 00:12:13')
|
||||
|
||||
def test_custom_format(self):
|
||||
converter = self.get_converter('datetime')
|
||||
converter2 = self.get_converter('date')
|
||||
opts = {'format': 'MMMM d'}
|
||||
|
||||
value = converter('2011-03-02 11:12:13', options=opts)
|
||||
value2 = converter2('2001-03-02', options=opts)
|
||||
self.assertEqual(
|
||||
value,
|
||||
'March 2'
|
||||
)
|
||||
self.assertEqual(
|
||||
value2,
|
||||
'March 2'
|
||||
)
|
||||
|
||||
class TestDurationExport(TestBasicExport):
|
||||
def setUp(self):
|
||||
super(TestDurationExport, self).setUp()
|
||||
|
|
|
@ -1,7 +1,12 @@
|
|||
# This test can be run stand-alone with something like:
|
||||
# > PYTHONPATH=. python2 openerp/tests/test_misc.py
|
||||
|
||||
import datetime
|
||||
import locale
|
||||
import unittest2
|
||||
|
||||
import babel
|
||||
import babel.dates
|
||||
|
||||
from ..tools import misc
|
||||
|
||||
|
||||
|
@ -35,5 +40,44 @@ class test_countingstream(unittest2.TestCase):
|
|||
self.assertIsNone(next(s, None))
|
||||
self.assertEqual(s.index, 0)
|
||||
|
||||
lname, _ = locale.getdefaultlocale()
|
||||
class TestPosixToBabel(unittest2.TestCase):
|
||||
def setUp(self):
|
||||
super(TestPosixToBabel, self).setUp()
|
||||
self.d = datetime.datetime(2007, 9, 8, 4, 5, 1)
|
||||
|
||||
def assert_eq(self, fmt, d=None):
|
||||
if d is None: d = self.d
|
||||
|
||||
ldml_format = misc.posix_to_ldml(fmt, locale=babel.Locale.parse(lname))
|
||||
self.assertEqual(
|
||||
d.strftime(fmt),
|
||||
babel.dates.format_datetime(d, format=ldml_format),
|
||||
"%r resulted in a different result than %r for %s" % (
|
||||
ldml_format, fmt, d))
|
||||
|
||||
def test_empty(self):
|
||||
self.assert_eq("")
|
||||
|
||||
def test_literal(self):
|
||||
self.assert_eq("Raw test string")
|
||||
|
||||
def test_mixed(self):
|
||||
self.assert_eq("m:%m d:%d y:%y")
|
||||
self.assert_eq("m:%m d:%d y:%y H:%H M:%M S:%S")
|
||||
|
||||
def test_escape(self):
|
||||
self.assert_eq("%%m:%m %%d:%d %%y:%y")
|
||||
|
||||
def test_xX(self):
|
||||
self.assert_eq('%x %X')
|
||||
|
||||
def test_various_examples(self):
|
||||
self.assert_eq("%x - %I:%M%p")
|
||||
self.assert_eq('%Y-%m-%dT%H:%M:%S')
|
||||
self.assert_eq("%Y-%j")
|
||||
self.assert_eq("%a, %d %b %Y %H:%M:%S")
|
||||
self.assert_eq("%a, %b %d %I:%M.%S")
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest2.main()
|
||||
|
|
|
@ -819,6 +819,76 @@ DATETIME_FORMATS_MAP = {
|
|||
'%Z': '',
|
||||
}
|
||||
|
||||
POSIX_TO_LDML = {
|
||||
'a': 'E',
|
||||
'A': 'EEEE',
|
||||
'b': 'MMM',
|
||||
'B': 'MMMM',
|
||||
#'c': '',
|
||||
'd': 'dd',
|
||||
'H': 'HH',
|
||||
'I': 'hh',
|
||||
'j': 'DDD',
|
||||
'm': 'MM',
|
||||
'M': 'mm',
|
||||
'p': 'a',
|
||||
'S': 'ss',
|
||||
'U': 'w',
|
||||
'w': 'e',
|
||||
'W': 'w',
|
||||
'y': 'yy',
|
||||
'Y': 'yyyy',
|
||||
# see comments above, and babel's format_datetime assumes an UTC timezone
|
||||
# for naive datetime objects
|
||||
#'z': 'Z',
|
||||
#'Z': 'z',
|
||||
}
|
||||
|
||||
def posix_to_ldml(fmt, locale):
|
||||
""" Converts a posix/strftime pattern into an LDML date format pattern.
|
||||
|
||||
:param fmt: non-extended C89/C90 strftime pattern
|
||||
:param locale: babel locale used for locale-specific conversions (e.g. %x and %X)
|
||||
:return: unicode
|
||||
"""
|
||||
buf = []
|
||||
pc = False
|
||||
quoted = []
|
||||
|
||||
for c in fmt:
|
||||
# LDML date format patterns uses letters, so letters must be quoted
|
||||
if not pc and c.isalpha():
|
||||
quoted.append(c if c != "'" else "''")
|
||||
continue
|
||||
if quoted:
|
||||
buf.append("'")
|
||||
buf.append(''.join(quoted))
|
||||
buf.append("'")
|
||||
quoted = []
|
||||
|
||||
if pc:
|
||||
if c == '%': # escaped percent
|
||||
buf.append('%')
|
||||
elif c == 'x': # date format, short seems to match
|
||||
buf.append(locale.date_formats['short'].pattern)
|
||||
elif c == 'X': # time format, seems to include seconds. short does not
|
||||
buf.append(locale.time_formats['medium'].pattern)
|
||||
else: # look up format char in static mapping
|
||||
buf.append(POSIX_TO_LDML[c])
|
||||
pc = False
|
||||
elif c == '%':
|
||||
pc = True
|
||||
else:
|
||||
buf.append(c)
|
||||
|
||||
# flush anything remaining in quoted buffer
|
||||
if quoted:
|
||||
buf.append("'")
|
||||
buf.append(''.join(quoted))
|
||||
buf.append("'")
|
||||
|
||||
return ''.join(buf)
|
||||
|
||||
def server_to_local_timestamp(src_tstamp_str, src_format, dst_format, dst_tz_name,
|
||||
tz_offset=True, ignore_unparsable_time=True):
|
||||
"""
|
||||
|
|
Loading…
Reference in New Issue