Skip to content

Files

Latest commit

Apr 26, 2025
ee6d294 · Apr 26, 2025

History

History

demo_datetime_tutorial

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
Oct 19, 2020
Oct 19, 2020
Oct 19, 2020
Apr 26, 2025
Oct 19, 2020
Oct 19, 2020

odoo datetime 教學

建議觀看影片, 會更清楚 😄

Youtube Tutorial - odoo datetime 教學

建議在閱讀這篇文章之前, 請先確保了解看過以下的文章 (因為都有連貫的關係)

odoo 手把手建立第一個 addons

本篇文章將說明 odoo 中的 datetime 機制.

說明

注意 ❗

在 odoo 中所有的 date 和 datetime 都是使用 UTC 的時間 (包含保存進資料庫 db 的資料).

這樣你可能會問我, odoo 不是可以選時區, 這樣頁面上是怎麼呈現時區正確的時間的 ❓

odoo 會透過 session (或是你的設定) 去做 time zone 的轉換.

每個 user 都可以設定自己的時區, 系統會建議你設定和瀏覽器一樣的時區

alt tag

先來看一下 python 的 datetime

>>> from datetime import datetime
>>> datetime(2020, 1, 10, 0, 0)
datetime.datetime(2020, 1, 10, 0, 0)

# strptime, python 的 str -> datetime
>>> my_datetime = datetime.strptime('2020/11/23', '%Y/%m/%d')
>>> my_datetime
datetime.datetime(2020, 11, 23, 0, 0)

# strftime, python 的 datetime -> str
>>> datetime.strftime(my_datetime, '%Y-%m-%d')
'2020-11-23'

python 的 timedelta

>>> from datetime import date
>>> from datetime import timedelta
>>> date.today()
datetime.date(2020, 10, 14)

>>> date.today() + timedelta(days=7)
datetime.date(2020, 10, 21)

python 的時區轉換

>>> ## Asia/Taipei -> UTC
>>> from pytz import timezone
>>> from datetime import datetime
>>> today = datetime(2022, 7, 7, 10, 0)
>>> user_tz = timezone('Asia/Taipei')

>>> today = user_tz.localize(today)
>>> today
datetime.datetime(2022, 7, 7, 10, 0, tzinfo=<DstTzInfo 'Asia/Taipei' CST+8 :00:00 STD>)

>>> today = today.astimezone(timezone('UTC'))
>>> today
datetime.datetime(2022, 7, 7, 2, 0, tzinfo=<UTC>)


>>> ## UTC -> Asia/Taipei
>>> from pytz import timezone
>>> from datetime import datetime
>>> today = datetime(2022, 7, 7, 10, 0)
>>> user_tz = timezone('UTC')

>>> today = user_tz.localize(today)
>>> today
datetime.datetime(2022, 7, 7, 10, 0, tzinfo=<UTC>)

>>> today = today.astimezone(timezone('Asia/Taipei'))
>>> today
datetime.datetime(2022, 7, 7, 18, 0, tzinfo=<DstTzInfo 'Asia/Taipei' CST+8 :00:00 STD>)

odoo 中的 odoo.tools.date_utils

start_of(value, granularity)

end_of(value, granularity)

add(value, **kwargs)

subtract(value, **kwargs)

from odoo.tools import date_utils
from datetime import date

>>> date.today()
datetime.date(2020, 10, 14)

>>> date_utils.add(date.today(), days=2)
datetime.date(2020, 10, 16)

>>> date_utils.subtract(date.today(), months=2)
datetime.date(2020, 8, 14)

odoo 中的 fields.Date.today() fields.Datetime.now()

>>> from odoo import fields
>>> fields.Date.today()
datetime.date(2020, 10, 14)
>>> fields.Datetime.now()
datetime.datetime(2020, 10, 14, 10, 48, 25)

fields.Date to_date converts a string into a date object.

fields.Datetime to_datetime(value) converts a string into a datetime object.

fields.Date, fields.Datetime to_string(value) converts a date or datetime object into a string in the format expected by the Odoo server.

( 其實這個 to_string(value) 也只是使用 python 的 strftime 去轉換而已, 格式是預設的 DATETIME_FORMAT)

fields.Date.context_today(record, timestamp=None)

fields.Datetime.context_timestamp(record, timestamp)

>>> from odoo import fields
>>> my_datetime = fields.Datetime.to_datetime('2020-02-10 10 :00:00')
>>> my_datetime
datetime.datetime(2020, 2, 10, 10, 0)

>>> my_datetime = fields.Datetime.from_string('2020-02-10 10 :00:00')
>>> my_datetime
datetime.datetime(2020, 2, 10, 10, 0)

>>> fields.Datetime.to_string(my_datetime)
'2020-02-10 10 :00:00'

寫入資料時, 可以直接輸入 string, 會自動轉換成 date / datetime

>>> demo = self.env['demo.datetime'].browse(1)
>>> demo.my_datetime
datetime.datetime(2020, 10, 14, 9, 30, 8)
>>> demo.my_datetime = '2020-01-01 09 :00:00'
>>> demo.my_datetime
datetime.datetime(2020, 1, 1, 9, 0)

轉換時區

from pytz import timezone

# Convert to Asia/Taipei time zone

>>> demo = self.env['demo.datetime'].browse(1)
>>> demo.my_datetime
datetime.datetime(2020, 1, 1, 9, 0)

>>> demo.my_datetime.astimezone(timezone('Asia/Taipei'))
datetime.datetime(2020, 1, 1, 17, 0, tzinfo=<DstTzInfo 'Asia/Taipei' CST+8 :00:00 STD>)

將 addons 裝起來之後, 來看 models/models.py

......
       @api.multi
       def demo1(self):
           _logger.warning('db datetime')
           _logger.warning(self.my_datetime )

           _logger.warning('Asia/Taipei datetime')
           _logger.warning(self.my_datetime.astimezone(timezone('Asia/Taipei')))
......

alt tag

可以從輸出中看到一個是 db 保存的 utc 時間, 一個是轉換後的 Taipei 時間.

alt tag

db 中保存的時間

alt tag