You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

120 lines
4.2 KiB

  1. # -*- coding: utf-8 -*-
  2. # © 2015 Grupo ESOC Ingeniería de Servicios, S.L.U. - Jairo Llopis
  3. # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
  4. from datetime import datetime, timedelta
  5. from openerp import api, exceptions, fields, models
  6. from openerp.tools import (DEFAULT_SERVER_DATE_FORMAT,
  7. DEFAULT_SERVER_TIME_FORMAT)
  8. from . import exceptions as ex
  9. # Available modes for :param:`.ResLang.datetime_formatter.template`
  10. MODE_DATETIME = "MODE_DATETIME"
  11. MODE_DATE = "MODE_DATE"
  12. MODE_TIME = "MODE_TIME"
  13. class ResLang(models.Model):
  14. _inherit = "res.lang"
  15. @api.model
  16. @api.returns('self')
  17. def best_match(self, lang=None, failure_safe=True):
  18. """Get best match of current default lang.
  19. :param str lang:
  20. If a language in the form of "en_US" is supplied, it will have the
  21. highest priority.
  22. :param bool failure_safe:
  23. If ``False`` and the best matched language is not found installed,
  24. an exception will be raised. Otherwise, the first installed
  25. language found in the DB will be returned.
  26. """
  27. # Find some installed language, as fallback
  28. first_installed = self.search([("active", "=", True)], limit=1)
  29. if not lang:
  30. lang = (
  31. # Object's language, if called like
  32. # ``record.lang.datetime_formatter(datetime_obj)``
  33. (self.ids and self[0].code) or
  34. # Context language
  35. self.env.context.get("lang") or
  36. # User's language
  37. self.env.user.lang or
  38. # First installed language found
  39. first_installed.code)
  40. # Get DB lang record
  41. record = self.search([("code", "=", lang)])
  42. try:
  43. record.ensure_one()
  44. except exceptions.except_orm:
  45. if not failure_safe:
  46. raise ex.BestMatchedLanguageNotFoundError(lang)
  47. else:
  48. record = first_installed
  49. return record
  50. @api.model
  51. def datetime_formatter(self, value, lang=None, template=MODE_DATETIME,
  52. separator=" ", failure_safe=True):
  53. """Convert a datetime field to lang's default format.
  54. :type value: `str`, `float` or `datetime.datetime`
  55. :param value:
  56. Datetime that will be formatted to the user's preferred format.
  57. :param str lang:
  58. See :param:`lang` from :meth:`~.best_match`.
  59. :param bool failure_safe:
  60. See :param:`failure_safe` from :meth:`~.best_match`.
  61. :param str template:
  62. Will be used to format :param:`value`. If it is one of the special
  63. constants :const:`MODE_DATETIME`, :const:`MODE_DATE` or
  64. :const:`MODE_TIME`, it will use the :param:`lang`'s default
  65. template for that mode.
  66. :param str separator:
  67. Only used when :param:`template` is :const:`MODE_DATETIME`, as the
  68. separator between the date and time parts.
  69. """
  70. # Get the correct lang
  71. lang = self.best_match(lang)
  72. # Get the template
  73. if template in {MODE_DATETIME, MODE_DATE, MODE_TIME}:
  74. defaults = []
  75. if "DATE" in template:
  76. defaults.append(lang.date_format or
  77. DEFAULT_SERVER_DATE_FORMAT)
  78. if "TIME" in template:
  79. defaults.append(lang.time_format or
  80. DEFAULT_SERVER_TIME_FORMAT)
  81. template = separator.join(defaults)
  82. # Convert str to datetime objects
  83. if isinstance(value, (str, unicode)):
  84. try:
  85. value = fields.Datetime.from_string(value)
  86. except ValueError:
  87. # Probably failed due to value being only time
  88. value = datetime.strptime(value, DEFAULT_SERVER_TIME_FORMAT)
  89. # Time-only fields are floats for Odoo
  90. elif isinstance(value, float):
  91. # Patch values >= 24 hours
  92. if value >= 24:
  93. template = template.replace("%H", "%d" % value)
  94. # Convert to time
  95. value = (datetime.min + timedelta(hours=value)).time()
  96. return value.strftime(template)