OCA/server-tools

View on GitHub
datetime_formatter/models.py

Summary

Maintainability
A
2 hrs
Test Coverage
# -*- coding: utf-8 -*-
# © 2015 Grupo ESOC Ingeniería de Servicios, S.L.U. - Jairo Llopis
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
from datetime import datetime, timedelta
from openerp import api, exceptions, fields, models
from openerp.tools import (DEFAULT_SERVER_DATE_FORMAT,
                           DEFAULT_SERVER_TIME_FORMAT)
from . import exceptions as ex

# Available modes for :param:`.ResLang.datetime_formatter.template`
MODE_DATETIME = "MODE_DATETIME"
MODE_DATE = "MODE_DATE"
MODE_TIME = "MODE_TIME"


class ResLang(models.Model):
    _inherit = "res.lang"

    @api.model
    @api.returns('self')
    def best_match(self, lang=None, failure_safe=True):
        """Get best match of current default lang.

        :param str lang:
            If a language in the form of "en_US" is supplied, it will have the
            highest priority.

        :param bool failure_safe:
            If ``False`` and the best matched language is not found installed,
            an exception will be raised. Otherwise, the first installed
            language found in the DB will be returned.
        """
        # Find some installed language, as fallback
        first_installed = self.search([("active", "=", True)], limit=1)

        if not lang:
            lang = (
                # Object's language, if called like
                # ``record.lang.datetime_formatter(datetime_obj)``
                (self.ids and self[0].code) or

                # Context language
                self.env.context.get("lang") or

                # User's language
                self.env.user.lang or

                # First installed language found
                first_installed.code)

        # Get DB lang record
        record = self.search([("code", "=", lang)])

        try:
            record.ensure_one()
        except exceptions.except_orm:
            if not failure_safe:
                raise ex.BestMatchedLanguageNotFoundError(lang)
            else:
                record = first_installed

        return record

    @api.model
    def datetime_formatter(self, value, lang=None, template=MODE_DATETIME,
                           separator=" ", failure_safe=True):
        """Convert a datetime field to lang's default format.

        :type value: `str`, `float` or `datetime.datetime`
        :param value:
            Datetime that will be formatted to the user's preferred format.

        :param str lang:
            See :param:`lang` from :meth:`~.best_match`.

        :param bool failure_safe:
            See :param:`failure_safe` from :meth:`~.best_match`.

        :param str template:
            Will be used to format :param:`value`. If it is one of the special
            constants :const:`MODE_DATETIME`, :const:`MODE_DATE` or
            :const:`MODE_TIME`, it will use the :param:`lang`'s default
            template for that mode.

        :param str separator:
            Only used when :param:`template` is :const:`MODE_DATETIME`, as the
            separator between the date and time parts.
        """
        # Get the correct lang
        lang = self.best_match(lang)

        # Get the template
        if template in {MODE_DATETIME, MODE_DATE, MODE_TIME}:
            defaults = []
            if "DATE" in template:
                defaults.append(lang.date_format or
                                DEFAULT_SERVER_DATE_FORMAT)
            if "TIME" in template:
                defaults.append(lang.time_format or
                                DEFAULT_SERVER_TIME_FORMAT)
            template = separator.join(defaults)

        # Convert str to datetime objects
        if isinstance(value, (str, unicode)):
            try:
                value = fields.Datetime.from_string(value)
            except ValueError:
                # Probably failed due to value being only time
                value = datetime.strptime(value, DEFAULT_SERVER_TIME_FORMAT)

        # Time-only fields are floats for Odoo
        elif isinstance(value, float):
            # Patch values >= 24 hours
            if value >= 24:
                template = template.replace("%H", "%d" % value)

            # Convert to time
            value = (datetime.min + timedelta(hours=value)).time()

        return value.strftime(template)