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.

123 lines
4.3 KiB

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