Odoo 19 provides useful tools for working with dates and times, including Date, Datetime, and its built-in date_utils. These tools make it easy to create, compare, and format date and time values, which are important for tasks like scheduling, tracking, and reporting in Odoo apps.
In this blog, we’ll look at how to use Date and Datetime fields effectively, along with Odoo’s date utilities, to handle time-related data in your models.
1. fields.Datetime.now(value)
Provides the current date and time in YYYY-MM-DD HH:MM:SS format in UTC.
from odoo import fields
print("Now:", fields.Datetime.now())
Output:
Now: 2025-09-20 09:03:48
2. fields.Datetime.to_string(value)
Converts a Python datetime object into a string in YYYY-MM-DD HH:MM:SS format.
from odoo import fields
print("To String:", fields.Datetime.to_string(value))
Output:
To String: 2025-09-20 09:16:06
3. fields.Datetime.from_string(value)
Converts a string in YYYY-MM-DD HH:MM:SS format into a Python datetime object.
from odoo import fields
date_str = '2025-09-20 15:30:00'
print(fields.Datetime.from_string(date_str))
Output:
From String: 2025-09-20 15:30:00
4. fields.Datetime.to_datetime(value)
Turns a string or datetime object into a Python datetime object in Odoo format; it does not work directly with date objects.
date_str = '2025-09-20 15:30:00'
print(fields.Datetime.to_datetime(date_str))
# Using a date object
date = datetime(2025, 9, 20, 15, 30)
print("datetime object->", fields.Datetime.to_datetime(date))
Output:
2025-09-20 15:30:00
datetime object > 2025-09-20 15:30:00
5. fields.Datetime.context_timestamp(self, timestamp)
Converts a UTC (naive) datetime into a timezone-aware datetime using the current user’s timezone from the Odoo context.
date = fields.Datetime.context_timestamp(self, fields.Datetime.now())
print("context_timestamp:", date)
Output:
2025-09-20 15:19:47+05:30
6. fields.Date.to_date(value)
Converts a string, datetime, or date object into a Python date object.
date_obj = fields.Date.to_date("2025-10-04")
print("Context_timestamp:", date_obj)Output:
Context_timestamp: 2025-10-04
7. fields.Date.context_today(self)
Returns today’s date in the user’s timezone, based on the Odoo context.
today = fields.Date.context_today(self)
print("Context_today:", today)
Output:
Context_today: 2025-10-04
8. fields.Date.today()
Returns the current date in UTC (without considering the user’s timezone).
today_date = fields.Date.today()
print("Today:", today_date)
Output:
Today: 2025-10-04
9. date_utils.date_range(fill_from, fill_to, interval)
Generates a list of dates between two dates (fill_from to fill_to) with the given step (interval).
start = date(2025, 10, 1)
end = date(2025, 10, 7)
dates_gen = date_utils.date_range(start, end, timedelta(days=2))
dates = list(dates_gen) # convert generator to list
print("Date_range", dates)
Output:
Date_range: [datetime.date(2025, 10, 1), datetime.date(2025, 10, 3), datetime.date(2025, 10, 5), datetime.date(2025, 10, 7)]
10. float_to_time(hours: float) > time
Converts a number of hours (as a float) into a Python time object. Handles fractional hours and treats 24.0 as time.max (23:59:59.999999).
test_values = [9.5, 14.75, 24.0, 0.25, 6.1]
for val in test_values:
result = float_to_time(val)
print(f"float_to_time({val}) => {result}")
Output:
float_to_time(9.5) > 09:30:00
float_to_time(14.75) > 14:45:00
float_to_time(24.0) > 23:59:59.999999
float_to_time(0.25) > 00:15:00
float_to_time(6.1) > 06:06:00
11. date_utils.get_fiscal_year(date)
Returns a tuple (start_date, end_date) for the fiscal year containing the given date, based on the company’s fiscal year configuration.
example_date = date(2025, 10, 4)
fiscal_year = date_utils.get_fiscal_year(example_date)
print("Fiscal_year:", fiscal_year)
Output:
Fiscal_year: (datetime.date(2025, 1, 1), datetime.date(2025, 12, 31))
12. date_utils.get_month(date)
Returns a tuple (start_date, end_date) for the month containing the given date.
example_date = date(2025, 10, 4)
month_range = date_utils.get_month(example_date)
print("Month_range:", month_range)
Output:
Month_range: (datetime.date(2025, 10, 1), datetime.date(2025, 10, 31))
13.date_utils.get_quarter(date)
Returns a tuple (start_date, end_date) for the quarter containing the given date.
example_date = date(2025, 10, 4)
quarter_range = date_utils.get_quarter(example_date)
print("Quarter_range:", quarter_range)
Output:
Quarter_range: (datetime.date(2025, 10, 1), datetime.date(2025, 12, 31))
14. date_utils.get_quarter_number(date)
Returns the quarter number (1–4) of the given date.
example_date = date(2025, 10, 4)
quarter_number = date_utils.get_quarter_number(example_date)
print('quarter_number:',quarter_number)
Output:
quater_number: 4
15. date_utils.get_timedelta(amount, unit)
gives you a relative time difference object (relativedelta) you can use to add or subtract whole days, months, or years.
today = date.today()
tomorrow = today + date_utils.get_timedelta(1, "day")
print('tomorrow:',tomorrow)
Output:
tomorrow: 2025-10-05
16. localized(date)
Ensures a datetime has timezone information (tzinfo). If the datetime is naive (no timezone), it adds UTC as the timezone. If it already has timezone info, it returns it unchanged.
dt_naive = datetime(2025, 10, 4, 12, 0)
print("Adds tzinfo",localized(dt_naive))
Output:
Adds tzinfo 2025-10-04 12:00:00+00:00
17. parse_date(value, env)
converts a date written as text into a real date or datetime object. It understands full date formats like "2025-10-04" and also flexible formats such as "today +3d" or "now -1m".
It starts from the current date and time in the user’s timezone, applies changes like adding days, months, or setting specific weekdays, and then gives back the adjusted date or time in a simple format.
print(parse_date("today", self.env))
print(parse_date("today +3d", self.env))Output:
2025-10-04
2025-10-07
18. parse_iso_date(date)
Converts a date string in ISO format (like "2025-10-04" or "2025-10-04T15:00:00") into a date or datetime object.
- If the string is short (=10 characters), it’s treated as a date only.
- If the datetime contains a timezone, it raises an error because only timezone-free datetimes are allowed.
print(parse_iso_date("2025-10-04"))
print(parse_iso_date("2025-10-04T15:00:00"))Output:
2025-10-04
2025-10-04 15:00:00
19. sum_intervals(intervals)
It takes a list of time intervals (each given as a pair of start and end datetimes) and calculates the total length of all intervals in hours.
intervals = [
(datetime(2025, 10, 4, 9), datetime(2025, 10, 4, 12)), # 3 hours
(datetime(2025, 10, 4, 14), datetime(2025, 10, 4, 16)), # 2 hours
]
print('SUM->',sum_intervals(intervals))
Output:
SUM > 5.0
20. time_to_float(duration)
Converts a time or timedelta into a number representing hours as a float.
- If given a timedelta, it converts the total seconds into hours.
- If given a time equal to the maximum possible time (23:59:59.999999), it returns 24.0.
- Otherwise, it calculates the hours including minutes, seconds, and microseconds.
print(time_to_float(time(3, 30))) # 3.5 hours
print(time_to_float(timedelta(hours=2))) # 2.0 hours
print(time_to_float(time.max))
Output:
3.5
2.0
24.0
21. to_timezone(tz)
Returns a function that converts any datetime to the given timezone.
- If tz is None, it converts the datetime to UTC and removes timezone info.
- If tz is given, it converts the datetime to that specific timezone.
utc = timezone.utc
to_tz = to_timezone(pytz.timezone("Asia/Kolkata"))
dt = datetime(2025, 10, 4, 12, 0, tzinfo=utc)
print(to_tz(dt))
Output:
2025-10-04 17:30:00+05:30
22. start_of(value, granularity)
Returns the starting point of a given time period for a date or datetime.
print(start_of(date(2025, 10, 4), "year"))
print(start_of(date(2025, 10, 4), "month"))
print(start_of(date(2025, 10, 4), "week"))
print(start_of(datetime(2025, 10, 4, 15, 30), "hour"))
Output:
2025-01-01
2025-10-01
2025-09-29
2025-10-04 15:00:00
23. end_of(value, granularity)
Returns the ending point of a given time period for a date or datetime.
print(end_of(date(2025, 10, 4), "year"))
print(end_of(date(2025, 10, 4), "month"))
print(end_of(date(2025, 10, 4), "week"))
Output:
2025-12-31
2025-10-31
2025-10-05
2025-10-04 15:59:59.999999
24. date_utils.add(value, **kwargs)
Adds a relative time to the date/datetime.
print("Adding 1 Year:", date_utils.add(date.today(), years=1))Output:
Adding 1 Year: 2026-10-04
25. date_utils.subtract(value, **kwargs)
Subtracts a relative delta from a date or datetime.
print("Subtracting 1 Month:", date_utils.subtract(date.today(), months=1))Output:
Subtracting 1 Month: 2025-09-04
In Odoo 19, date, datetime, and date_utils provide essential tools for handling time data efficiently. They simplify parsing, formatting, and date calculations, ensuring accuracy and consistency across applications. Mastering these tools helps developers build more reliable and maintainable solutions.
To read more about How to Manage Date & Datetime Fields in Odoo 18, refer to our blog How to Manage Date & Datetime Fields in Odoo 18.