(#163) How to Manage Date & Datetime Fields in Odoo 18
Introduction
In the world of business applications, time is everything—and that’s not just a metaphor. Dates and datetimes are the soul of planning, automation, invoicing, manufacturing, HR... you name it. But here’s the catch: handling date and datetime fields in Odoo 18 isn’t always a walk in the park.
If you've ever battled with strange timezone bugs, seen your scheduled actions misfire, or wondered why a date filter doesn’t catch what it should—this is for you, Odoo warrior. Let’s decode the technical ins and outs of date and datetime fields in Odoo 18.
🧩 Basics of Date & Datetime in Odoo
Difference Between date and datetime Fields
If you don’t need the time component—don’t use datetime. Simple.
Default Behavior in the Odoo ORM
When you define a model field like this:
python
date_field = fields.Date(string="Due Date") datetime_field = fields.Datetime(string="Meeting Time")
Odoo automatically handles their types internally with PostgreSQL and manages them using Python datetime and date.
Timezone Awareness: The Hidden Catch
Datetime fields are stored in UTC in the backend—but shown in the user’s local time on the frontend. This can mess with:
⚙️ Defining Date & Datetime Fields
Using fields.Date in Odoo
python
fields.Date(string="Start Date", required=True)
Using fields.Datetime in Odoo
python
fields.Datetime(string="Meeting Time", default=lambda self: fields.Datetime.now())
Must-Know Attributes
🌍 Timezone Handling
Odoo’s Timezone System
What It Means
python
fields.Datetime.now() # Returns UTC
datetime.now() # Returns server's local time
You must convert when comparing or setting logic. Always.
🌐 Formatting and Localization
Change Format Globally
In the language settings:
Using babel.dates for Custom Formats
python
from babel.dates import format_datetime
format_datetime(datetime.utcnow(), locale='en_US')
🐍 Python datetime vs Odoo’s Helpers
What to Use When
Converting Between Formats
python
from datetime import datetime
datetime.strptime('2025-07-23', '%Y-%m-%d')
🖼️ Using Date/Datetime in Views
Form Views
xml
<field name="start_date" widget="date"/>
<field name="meeting_time" widget="datetime"/>
Tree Views
Calendar Views
Map the start_datetime and stop_datetime for precise rendering.
📆 Default Values & Smart Defaults
Using Today’s Date
python
default=lambda self: fields.Date.today()
Using Now for Datetime
python
default=lambda self: fields.Datetime.now()
You can also use context-based defaults like:
python
default=lambda self: self.env.context.get('default_date')
🧮 Domain Filters Using Dates
Basic Filtering
python
('start_date', '=', fields.Date.today())
Filtering by Range
python
('date_field', '>=', '2025-01-01'),
('date_field', '<=', '2025-01-31'),
Dynamic Domains
Use context_today(self) for safer filtering:
python
from odoo.tools import context_today
context_today(self)
🔍 Date Range Filtering in Search Views
Use filter options like:
xml
<filter string="This Month" domain="[('date_field','>=', (context_today().replace(day=1)))]"/>
Also, create custom ranges using context filters.
⏰ Scheduled Actions and Datetime
Set triggers for automation:
xml
<record id="ir_cron_my_task" model="ir.cron">
<field name="interval_type">days</field>
<field name="interval_number">1</field>
<field name="nextcall">2025-07-25 09:00:00</field>
</record>
Be careful—always use UTC for nextcall.
🔐 SQL Constraints & Validation
If you want to ensure a field is unique by date:
python
sqlconstraints = [
('unique_date', 'unique(date_field)', 'Date must be unique!')
]
You can also validate dates:
python
@api.constrains('start_date', 'end_date')
def checkdate_order(self):
if self.end_date < self.start_date:
raise ValidationError("End date cannot be before start date.")
🐞 Common Errors & Debugging Tips
Fix your strptime() format string.
Always check user timezone.
Tip: Log raw UTC values before applying filters.
📌 Best Practices
🎯 Conclusion
Managing date and datetime fields in Odoo 18 can be surprisingly emotional—frustrating, enlightening, and often humbling. But once you understand the inner workings—timezones, defaults, formatting, and views—it all starts to click. Your modules behave better. Your reports align. Your automations run like clockwork (literally).
So whether you’re scheduling a cron job or filtering invoices from last week, never underestimate the power of time well managed.