Odoo考勤报表时区问题:打印时间多2小时及服务器时区转用户时区方法
解决Odoo考勤报表的时区问题
问题1:打印报表时时间多2小时
这个问题十有八九是因为报表模板直接读取了Odoo存储的UTC原始时间,没做用户时区转换。Odoo后台所有datetime类型字段都是以UTC存储的,UI界面会自动根据当前用户的时区设置转换显示,但报表模板如果没处理,就会直接输出UTC时间——刚好和你的用户时区差2小时(比如你所在时区是UTC+2)。
修复方法很简单,在你的QWeb报表模板里,给时间字段加上时区转换:
- 推荐用
format_datetime过滤器:<span t-esc="format_datetime(record.check_in, format='%Y-%m-%d %H:%M:%S', tz=user.tz)"/> <span t-esc="format_datetime(record.check_out, format='%Y-%m-%d %H:%M:%S', tz=user.tz)"/> - 或者用
strftime配合时区参数:<span t-esc="record.check_in.strftime('%Y-%m-%d %H:%M:%S') if record.check_in else ''" t-options='{"tz": user.tz}'/>
如果你的报表是通过Python代码生成数据(比如在报表的.py文件里),也可以在数据处理阶段就转换时区:
from pytz import timezone def get_report_values(self, docids, data=None): docs = self.env['hr.attendance'].browse(docids) user_tz = timezone(self.env.user.tz or 'UTC') attendance_records = [] for rec in docs: converted_check_in = rec.check_in.astimezone(user_tz) if rec.check_in else None converted_check_out = rec.check_out.astimezone(user_tz) if rec.check_out else None attendance_records.append({ 'employee': rec.employee_id.name, 'check_in': converted_check_in.strftime('%Y-%m-%d %H:%M:%S') if converted_check_in else '', 'check_out': converted_check_out.strftime('%Y-%m-%d %H:%M:%S') if converted_check_out else '', }) return { 'doc_ids': docids, 'doc_model': 'hr.attendance', 'records': attendance_records, 'user': self.env.user, }
问题2:报表中使用用户时区而非服务器时区
首先要明确:Odoo服务器的时区不建议修改(后台统一用UTC存储时间是最佳实践),正确的做法是在报表中对时间字段进行用户时区转换——上面的方法其实已经解决了这个问题。
额外要注意:确保每个用户都在个人偏好设置里正确配置了时区(路径:设置 > 偏好设置 > 时区)。如果用户没有设置,代码里要默认用UTC,避免出现转换错误。
另外,如果你是基于原生报表做的自定义,也可以检查下原生报表的时间处理逻辑,确保你的自定义代码没有覆盖掉时区转换的部分。
内容的提问来源于stack exchange,提问作者Mohamed Fouad
相关产品推荐
相关产品推荐

