第一次踩odoo时差的坑,才知道原来odoo在存储日期数据时,是以UTC0时区存放的,和北京时间相差8个小时。只是odoo本身能很好的处理日期数据的存储和展示,所以刚开始接触odoo,不容易发现这个问题。

在做货运管理的时候,生成货运订单编号的格式是自己定义的,根据当日的运单数量自动往下递增,如下所示:

但是在第二天早上,新增加运单的时候,发现运单号上面的日期依然是昨天的,很是奇怪,搜索了下相关的资料,才发现是时差的原因导致的,虽然可以通过已知的8个小时的时差做计算,但这显然不是我们想要的,如果系统使用的地方采用的不是东8区的时间怎么办呢?以下是采用的最终方案代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
    # 生成自定义编号数据
    def generate_custom_code(self):
        # 获取当前用户时区
        tz_name = self._context.get('tz') or self.env.user.tz
        # 计算当前时区和UTC0时差      
        utc_time = fields.Datetime.now()
        local_time = utc_time.astimezone(pytz.timezone(tz_name))
        date_format = "%Y-%m-%d %H:%M:%S"
        string_utc = utc_time.strftime(date_format)
        string_local = local_time.strftime(date_format)
        datetime_utc = datetime.strptime(string_utc, date_format)
        datetime_local = datetime.strptime(string_local, date_format)
        time_difference = (datetime_local-datetime_utc).total_seconds()/3600
        tz_hours = timedelta(hours=time_difference)
        hours = timedelta(hours=24-time_difference)
        # 构造查询数据条件
        current_time = fields.Datetime.now()
        local_date = (current_time + tz_hours).replace(hour=0,
                                                       minute=0, second=0, microsecond=0)
        date_start = local_date-tz_hours
        date_end = local_date+hours
        record_count = self.search_count(
            [('create_date', '>=', date_start), ('create_date', '<', date_end)])
        return f'HY{local_date.strftime("%Y%m%d")}{record_count + 1:04d}'

通过计算odoo当前用户的时区和utc0之间的时差,然后再做相关的计算处理。这样一来,即使用户在其他的地方使用,也不受影响。

点击链接查看完整源码:github

作者 菜园君