Introduction
Dates and timestamps are built into almost every business process. When was this order placed? When is the delivery scheduled? When did the employee check in? In Odoo, the Datetime field is the standard way to capture and store this kind of information.
Unlike the Date field, which stores only a calendar date, the Datetime field captures both the date and the exact time. This distinction matters more than it might seem, especially in environments with users across multiple timezones or when tracking events at the hour and minute level.
This guide covers everything you need to know about the Datetime field in Odoo: what it stores, how it behaves in the data model, how to create and configure it using Odoo Studio or Python, and practical examples from real business workflows.
What is the Datetime Field in Odoo
In the Odoo ORM, fields.Datetime stores a combined date and time value, down to the second. At the database level, it maps to a TIMESTAMP column in PostgreSQL. Odoo always stores Datetime values in UTC internally and converts them to the active user's local timezone when displaying them in the interface.
From the user perspective, a Datetime field appears as a combined date and time picker in forms. It shows a calendar widget alongside a time input. In list views and reports, the value is formatted according to the language and timezone settings of the active user.
Here is how a Datetime field looks in a Python model definition:
from odoo import fields, models
class SaleOrder(models.Model):
_inherit = 'sale.order'
x_confirmed_on = fields.Datetime(
string='Confirmed On',
default=fields.Datetime.now,
readonly=True,
copy=False,
)
The string parameter sets the label shown in the interface. The default parameter automatically fills the field with the current timestamp when a new record is created. The readonly parameter prevents manual editing, which is common for audit timestamps.
In Odoo Studio, this field type is called a Date & Time field. When created through Studio, it gets an x_studio_ prefix automatically. When created via code or the XML-RPC API, you define the technical name yourself.
How the Field Works
When you define a Datetime field in Odoo, the framework creates the corresponding database column automatically during module installation or upgrade. There is no need to write SQL migrations by hand.
One thing that surprises many developers and business users is how Odoo handles timezones. The database always stores the value in UTC. When a user in Paris sets a meeting time to 3:00 PM, Odoo saves 1:00 PM UTC in the database. A user in New York reading the same record will see 9:00 AM in their interface. The Odoo ORM handles this conversion transparently based on the timezone configured in each user's profile.
Key Field Attributes
Here are the most important properties of a Datetime field in the Odoo framework:
- default: Often set to
fields.Datetime.nowto auto-fill with the current UTC timestamp when a record is created. - required: Makes the field mandatory in forms and at the model level.
- readonly: Prevents manual editing in the interface. Common for auto-generated timestamps.
- compute: Links a Python method that computes the field value dynamically from other fields or business logic.
- store: When combined with
compute, persists the computed value in the database for use in searches and reports. - copy: Controls whether the value is duplicated when copying a record. Defaults to
True. Set toFalsefor timestamps that should not carry over to duplicates. - index: Creates a database index. Useful on fields that are frequently used in filters, such as scheduled dates on large tables.
How It Appears in Views
In form views, a Datetime field renders as a combined date and time picker. Users click to open a calendar and set the time directly in the same input. In list views, the value appears as a formatted string based on the user's language settings. In search views, Datetime fields support date range filters such as before, after, and between a specific period.
You can also pair a Datetime field with the date_range widget to display a range selection directly in the form, which is useful for scheduling windows and time-bound tasks.
Datetime vs Date: Choosing the Right Field
A common question in Odoo development is when to use fields.Datetime versus fields.Date. The rule is straightforward: use fields.Date when the time of day is irrelevant, and fields.Datetime when you need precision at the hour or minute level.
Use Date for: invoice due dates, birthdays, product expiration dates, contract renewal dates.
Use Datetime for: order confirmation timestamps, meeting start times, employee attendance records, scheduled warehouse operations.
Using Datetime unnecessarily adds timezone complexity without any real benefit. When in doubt, ask whether the time of day genuinely matters for the business process you are modeling.
Business Use Cases
The Datetime field appears across nearly every module in Odoo. Here are five practical examples from real business workflows.
CRM: Lead Activity Tracking
In the CRM module, several native Datetime fields track when key events happened. The date_open field records when a lead was set to In Progress. The date_deadline field schedules a follow-up. Sales managers use these fields to measure response times, identify stale opportunities, and report on team activity. Custom Datetime fields can extend this further, for example to log when a quote was sent or when a specific call took place.
Sales: Order Confirmation Timestamps
The date_order field on sale.order is a Datetime field. It captures the exact moment a sale was confirmed. This is valuable for reporting on daily or hourly sales activity, calculating how long orders take to be processed, and auditing changes made after confirmation. Filtering sales orders by this field is one of the most common reporting operations in any Odoo sales setup.
Inventory: Scheduled Transfer Dates
The scheduled_date field on stock.picking is a Datetime field that warehouse teams use to plan when a receipt or shipment should take place. Automated actions in Odoo can trigger workflows based on how this date compares to the current time. For example, an automated email can go out when a delivery has been overdue for a certain number of hours, enabling proactive communication with customers before they reach out.
Manufacturing: Production Start and End Times
Manufacturing orders use Datetime fields to record when production started and when it was completed. This data feeds directly into capacity planning, efficiency reporting, and performance analysis. For companies running multiple shifts, capturing the precise time is essential to understanding actual versus planned production output and identifying bottlenecks by time of day or by operator.
HR: Attendance and Leave Management
The HR Attendance module uses Datetime fields to record employee check-in and check-out times. Leave requests rely on Datetime to define the exact start and end of an absence. Payroll calculations and overtime rules often depend on these values being accurate down to the minute. Any drift or missing timestamp in attendance records can affect compensation calculations directly, making precision here a real business requirement rather than a technical preference.
Creating or Customizing the Datetime Field
There are three main ways to add a Datetime field to an Odoo model, depending on your technical setup and whether you prefer a no-code or developer approach.
Using Odoo Studio (No Code)
Odoo Studio is the built-in customization tool that lets you add fields without writing any code. To add a Datetime field through Studio:
- Open Odoo Studio from the main menu.
- Navigate to the form where you want to add the field.
- Drag a Date & Time field from the sidebar onto the form.
- Set the label, required status, and optionally a default value in the field properties panel.
- Save and close Studio.
Studio automatically creates the field with an x_studio_ prefix and adds it to the form view. No database migration is needed on your side. Odoo handles all of that automatically when you save. This is the recommended approach for business users who need to add a timestamp to an existing form without developer involvement.
Using Python in a Custom Module
For developers building Odoo modules, Datetime fields are defined in Python model files. This is the recommended approach for any customization that needs to be version-controlled and deployed across multiple environments:
from odoo import fields, models
class ResPartner(models.Model):
_inherit = 'res.partner'
x_last_contact_date = fields.Datetime(
string='Last Contact Date',
default=fields.Datetime.now,
copy=False,
)
After defining the field in the model, add it to the relevant view XML file so it appears in the interface. Odoo creates the TIMESTAMP column automatically when you install or upgrade the module. No manual SQL is needed.
Using the XML-RPC API
If you manage Odoo customizations programmatically, for example as part of a deployment pipeline or a remote configuration script, you can create Datetime fields via the XML-RPC API:
field_id = models.execute_kw(
ODOO_DB, uid, ODOO_API_KEY,
'ir.model.fields', 'create',
[{
'name': 'x_last_contact_date',
'field_description': 'Last Contact Date',
'model_id': model_id,
'ttype': 'datetime',
'state': 'manual',
}]
)
The ttype: datetime value tells Odoo to create a Datetime field. The state: manual value indicates this field was created outside of a module installation, which is the correct setting for fields created through Studio or the API. This is how Dasolo manages remote field creation for clients as part of automated configuration scripts.
Best Practices
1. Use fields.Datetime.now as a function reference, not a call
When setting a default, write default=fields.Datetime.now without parentheses. If you add parentheses, Python evaluates the function once when the class is loaded, and every record created for the lifetime of the Odoo process will share the same frozen timestamp. Without parentheses, Odoo calls the function at record creation time, giving each record its own accurate timestamp.
2. Set copy=False on event timestamps
If a field records when something happened, such as a confirmation date or a completion timestamp, set copy=False. When users duplicate a record, these timestamps should not carry over from the original. A duplicated sale order should not show the confirmation date of the order it was copied from. Without this setting, historical data becomes quietly unreliable.
3. Always pass UTC when writing via the API
When creating or updating records through the XML-RPC API, always pass Datetime values in UTC using the YYYY-MM-DD HH:MM:SS string format. The API does not perform timezone conversion on write. Whatever string you pass is stored directly in the database as if it were UTC, so passing a local time will silently create an offset error that is difficult to diagnose later.
4. Use readonly for auto-generated timestamps
Fields that capture when something happened should generally be set as readonly in the interface. This prevents users from manually adjusting timestamps that should reflect actual system events. If there is a legitimate reason to allow editing, control access through Odoo's field-level security settings rather than leaving the field openly editable.
5. Choose Date instead of Datetime when time is not needed
If a field only needs to track a calendar date, such as a delivery deadline, a renewal date, or an invoice due date, use fields.Date. Datetime adds timezone handling complexity that serves no purpose when the time component is always irrelevant. Keeping the field type as simple as the use case requires makes the data model easier to understand and maintain.
Common Pitfalls
Timezone confusion when reading raw values
This is the most frequent source of confusion with Datetime fields. When you read a value directly from the database or through the API, you see the UTC value, not the user's local time. Many developers build reports or integrations based on raw API output and end up with timestamps that are off by one or more hours. Always apply timezone conversion on the client side when presenting API results to end users, and make this an explicit step in any integration you build.
Writing localized times via the API
If you pass a Datetime value that is already in a local timezone to the Odoo API, the database will store it as if it were UTC. A meeting set at 3:00 PM Paris time, written as 2026-01-01 15:00:00 to the API, will be displayed as 4:00 PM or 5:00 PM for a user in Paris, depending on summer or winter time. This is one of those bugs that only appears in production when real users in real timezones start using the system.
Using default=fields.Datetime.now() with parentheses
Adding parentheses to the default is a subtle but serious mistake. fields.Datetime.now() is evaluated once when the Python class is loaded. Every record created for the entire lifetime of the Odoo worker process will share that same frozen timestamp. The records will look correct initially but break any analysis based on creation times. This is a silent bug that can take a long time to spot because timestamps appear to exist, they are just all identical.
Forgetting copy=False on event timestamps
Without copy=False, a duplicated record carries over all Datetime values from the original. An order confirmation date, a lead creation time, or a production start timestamp from the source record will appear unchanged on the new one. This silently contaminates historical reports and makes audit trails unreliable. It is a small configuration detail that has a disproportionate impact on data quality.
Using Datetime when Date is sufficient
Choosing Datetime for a field like an invoice due date or a product expiration date adds unnecessary complexity. Users see a time component they do not need, timezone calculations run on every display without any benefit, and the interface becomes slightly more cumbersome for no reason. The right field type is the simplest one that correctly models the business requirement.
Conclusion
The Datetime field is one of the most useful field types in Odoo when precision matters. From tracking when a lead was opened to recording production start times and employee attendance, it appears across nearly every module in the system.
The key thing to internalize is the UTC storage model. Everything stored in the database is in UTC. The interface handles timezone display for users automatically, but any external reads or writes through the API need to account for this explicitly. Most timezone-related bugs in Odoo integrations trace back to this one misunderstanding.
Beyond that, using the right default syntax, setting copy=False where appropriate, and choosing Date over Datetime when time is irrelevant will keep your data model clean and your reports trustworthy.
At Dasolo, we help companies implement, customize, and optimize Odoo across all departments. Whether you need help designing a solid data model, adding custom fields to your workflows, or building a full Odoo module from scratch, our team is ready to help. Reach out to us and let's talk about your Odoo project.