(#163) How to Manage Date & Datetime Fields in Odoo 18

(#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

  • fields.Date: Stores only the date (YYYY-MM-DD).
  • fields.Datetime: Stores full timestamp (YYYY-MM-DD HH:MM:SS).

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:

  • Scheduled actions
  • Comparisons in custom code
  • Report generation

⚙️ 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

  • required=True
  • default=...
  • readonly=True
  • index=True

🌍 Timezone Handling

Odoo’s Timezone System

  • Datetime fields stored in UTC
  • Displayed based on user's timezone (from user preferences)

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:

  • Settings → Translations → Languages → Date Format

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

  • Format with <field> directly
  • Use options="{'datepicker': True}" if needed

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

  • Error: ValueError: time data does not match format

Fix your strptime() format string.

  • Issue: Datetime mismatch between frontend/backend

Always check user timezone.

Tip: Log raw UTC values before applying filters.

📌 Best Practices

  • Always store datetimes in UTC.
  • Use fields.Datetime.now() not datetime.now().
  • Don’t hardcode timezones.
  • Be cautious with frontend calendar views.
  • For APIs, always return ISO 8601 datetime strings.

🎯 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.


To view or add a comment, sign in

Others also viewed

Explore topics