How to Manage Date & Datetime Fields in Odoo 18
By Braincuber Team
Published on January 17, 2026
Every ERP system revolves around dates: order dates, due dates, expiry dates, fiscal periods, scheduled actions. Odoo 18 provides a comprehensive toolkit for working with dates and datetimes through fields.Date, fields.Datetime, and the powerful date_utils module. These utilities handle everything from simple "today's date" to complex fiscal year calculations.
This tutorial documents the essential date and datetime methods available in Odoo 18, with practical examples for each. Whether you're computing deadlines, building reports, or filtering records by date ranges, you'll find the right tool here.
Key Imports:
from odoo import fields— for Date and Datetime field methodsfrom odoo.tools import date_utils— for advanced date manipulation
Core Date Methods
1. fields.Date.today()
Returns the current date as a string in YYYY-MM-DD format.
from odoo import fields
# Get today's date
today = fields.Date.today()
print("Today:", today)
# Output: Today: 2025-01-17
Use Case: Default values for date fields, record filtering, deadline calculations.
2. fields.Datetime.now()
Returns the current datetime in YYYY-MM-DD HH:MM:SS format.
from odoo import fields
# Get current datetime
now = fields.Datetime.now()
print("Now:", now)
# Output: Now: 2025-01-17 08:30:45
Use Case: Timestamps for audit logs, scheduled actions, tracking creation/modification times.
Period Boundaries
3. date_utils.start_of(value, granularity)
Returns the start of a time period. Granularity options: hour, day, week, month, quarter, year.
from odoo.tools import date_utils
from odoo import fields
today = fields.Datetime.now()
# Start of month
print("Start of Month:", date_utils.start_of(today, "month"))
# Output: 2025-01-01 00:00:00
# Start of week
print("Start of Week:", date_utils.start_of(today, "week"))
# Output: 2025-01-13 00:00:00
# Start of quarter
print("Start of Quarter:", date_utils.start_of(today, "quarter"))
# Output: 2025-01-01 00:00:00
4. date_utils.end_of(value, granularity)
Returns the end of a time period.
# End of month
print("End of Month:", date_utils.end_of(today, "month"))
# Output: 2025-01-31 23:59:59.999999
# End of year
print("End of Year:", date_utils.end_of(today, "year"))
# Output: 2025-12-31 23:59:59.999999
Use Case: Report date ranges, filtering records within a period.
Date Arithmetic
5. date_utils.add(value, **kwargs)
Adds time to a date/datetime. Accepts: days, weeks, months, years.
# Add 30 days
deadline = date_utils.add(today, days=30)
print("Due Date:", deadline)
# Add 1 year for annual renewal
renewal = date_utils.add(today, years=1)
print("Renewal Date:", renewal)
# Add 3 months
next_quarter = date_utils.add(today, months=3)
print("Next Quarter:", next_quarter)
6. date_utils.subtract(value, **kwargs)
Subtracts time from a date/datetime.
# Get last month
last_month = date_utils.subtract(today, months=1)
print("Last Month:", last_month)
# Get date 7 days ago
week_ago = date_utils.subtract(today, days=7)
print("Week Ago:", week_ago)
# Last year
previous_year = date_utils.subtract(today, years=1)
print("Previous Year:", previous_year)
Use Case: Historical data analysis, "last 30 days" reports, age calculations.
Period Ranges
7. date_utils.get_month(value)
Returns a tuple of (start, end) for the month containing the given date.
month_range = date_utils.get_month(today)
print("Month Range:", month_range)
# Output: (datetime(2025, 1, 1, 0, 0), datetime(2025, 1, 31, 0, 0))
8. date_utils.get_quarter(value)
Returns a tuple of (start, end) for the quarter.
quarter_range = date_utils.get_quarter(today)
print("Quarter Range:", quarter_range)
# Output: (datetime(2025, 1, 1, 0, 0), datetime(2025, 3, 31, 0, 0))
9. date_utils.get_quarter_number(value)
Returns the quarter number (1-4).
quarter_num = date_utils.get_quarter_number(today)
print("Quarter Number:", quarter_num)
# Output: Quarter Number: 1 (for January)
10. date_utils.get_fiscal_year(value)
Returns a tuple of (start, end) for the fiscal year (calendar year by default).
fiscal_year = date_utils.get_fiscal_year(today)
print("Fiscal Year:", fiscal_year)
# Output: (datetime(2025, 1, 1, 0, 0), datetime(2025, 12, 31, 0, 0))
Context-Aware Methods
11. fields.Date.context_today(self)
Returns today's date adjusted to the user's timezone.
# Inside a model method
user_today = fields.Date.context_today(self)
print("User's Today:", user_today)
12. fields.Datetime.context_timestamp(self, timestamp)
Converts a naive datetime to user's timezone.
# Inside a model method
user_time = fields.Datetime.context_timestamp(self, fields.Datetime.now())
print("User's Timestamp:", user_time)
Important: Context methods require self to access the user's timezone from the environment. Use these in model methods, not in standalone scripts.
Type Conversions
13. fields.Date.to_date(value)
Converts a string to a Python datetime.date object.
date_string = '2025-06-15'
date_obj = fields.Date.to_date(date_string)
print("Date Object:", date_obj)
print("Type:", type(date_obj))
# Output: datetime.date(2025, 6, 15)
14. fields.Date.to_string(value)
Converts a date object to a YYYY-MM-DD string.
from datetime import date
date_obj = date(2025, 6, 15)
date_string = fields.Date.to_string(date_obj)
print("Date String:", date_string)
# Output: 2025-06-15
Quick Reference Table
| Method | Returns | Use Case |
|---|---|---|
| fields.Date.today() | Current date | Defaults, filtering |
| fields.Datetime.now() | Current datetime | Timestamps, logging |
| date_utils.add() | Future date | Deadlines, renewals |
| date_utils.subtract() | Past date | Historical reports |
| date_utils.get_month() | (start, end) tuple | Monthly reports |
| date_utils.get_quarter() | (start, end) tuple | Quarterly reports |
| date_utils.get_fiscal_year() | (start, end) tuple | Fiscal reporting |
Conclusion
Odoo 18's date utilities cover every common date manipulation scenario: getting current dates, calculating periods, adding/subtracting time, handling timezones, and converting between formats. By using date_utils instead of raw Python datetime operations, your code stays consistent with Odoo's conventions and handles edge cases properly.
Key Takeaway: Use fields.Date.today() and fields.Datetime.now() for current values. Use date_utils.start_of()/end_of() for period boundaries. Use add()/subtract() for date arithmetic. Use get_month(), get_quarter(), get_fiscal_year() for range calculations.
