Timestamps
Ormed provides automatic timestamp management for created_at and updated_at columns.
Enabling Timestamps
Add the Timestamps marker mixin to your model:
(table: 'posts')
class TimestampPost extends Model<TimestampPost> with Timestamps {
const TimestampPost({required this.id, required this.title});
(isPrimaryKey: true, autoIncrement: true)
final int id;
final String title;
}
The code generator detects this mixin and:
- Adds virtual
createdAtandupdatedAtfields if not explicitly defined - Applies timestamp implementation to the generated tracked class
- Automatically sets timestamps on insert/update operations
Carbon Integration
Ormed integrates with the Carbonized library to provide a fluent API for date manipulation. The createdAt and updatedAt getters return a CarbonInterface? instance.
final user = await repo.find(1);
if (user != null) {
print(user.createdAt?.diffForHumans()); // "2 hours ago"
print(user.updatedAt?.addDays(1).isFuture); // true
}
:::tip Timestamps are Immutable
Ormed returns immutable Carbon instances from timestamp getters. This means you can safely chain methods like subDay() without accidentally mutating the model's state:
final yesterday = user.createdAt?.subDay(); // Safe! Returns new instance
print(user.createdAt); // Original value unchanged
See the Date and Time Handling guide for more details on mutable vs immutable Carbon behavior. :::
Flexible Setters
The createdAt and updatedAt setters accept both standard Dart DateTime objects and CarbonInterface instances.
user.updatedAt = DateTime.now();
// or
user.updatedAt = Carbon.now().subDays(1);
Timezone-Aware Timestamps
For timestamps stored in UTC, use TimestampsTZ:
(table: 'articles')
class TimestampArticleTz extends Model<TimestampArticleTz> with TimestampsTZ {
const TimestampArticleTz({required this.id, required this.title});
(isPrimaryKey: true, autoIncrement: true)
final int id;
final String title;
}
This ensures:
- All timestamps are converted to UTC before storage
- Timestamps remain in UTC when retrieved
- Your application handles timezone conversion for display
Prefer UTC storage for multi-region systems; localize only at presentation boundaries.
Migration Setup
Add timestamp columns in your migration:
- Notes
- Code
If you use Timestamps/TimestampsTZ, keep the schema column names aligned with your model configuration.
class AddTimestampsToPosts extends Migration {
const AddTimestampsToPosts();
void up(SchemaBuilder schema) {
schema.table('posts', (table) {
// Non-timezone aware (stored as-is)
table.timestamps();
// OR timezone aware (UTC storage)
// table.timestampsTz();
// OR nullable timestamps
// table.nullableTimestamps();
// table.nullableTimestampsTz();
});
}
void down(SchemaBuilder schema) {
schema.table('posts', (table) {
table.dropColumn('created_at');
table.dropColumn('updated_at');
});
}
}
Custom Column Names
By default, Ormed uses created_at and updated_at. These can be customized via model configuration if needed.
Behavior
On Insert
created_atis set to the current timestampupdated_atis set to the current timestamp
On Update
updated_atis automatically updatedcreated_atremains unchanged
Manual Control
You can manually set timestamps if needed:
// You can manually set timestamps using DateTime or Carbon:
// final post = $TimestampPost(
// id: 0,
// title: 'My Post',
// createdAt: DateTime(2024, 1, 1),
// updatedAt: Carbon.now().subDays(1),
// );
Disabling Automatic Updates
If you still want timestamp columns but need to control updates yourself, disable auto-updates at the model level:
(table: 'audit_logs', timestamps: false)
class AuditLog extends Model<AuditLog> with Timestamps {
const AuditLog({required this.id, required this.message});
(isPrimaryKey: true)
final int id;
final String message;
}
You can also suppress timestamp updates for a scoped block:
await Model.withoutTimestampsOn(<Type>[Post], () async {
await Posts.query().where('id', 42).update({'title': 'No touch'});
});
Without Timestamps
If you don't need automatic timestamps, simply don't include the mixin:
(table: 'logs')
class Log extends Model<Log> {
// No timestamps mixin - manual control
const Log({required this.id, required this.message, this.timestamp});
(isPrimaryKey: true)
final int id;
final String message;
final DateTime? timestamp;
}
Read This Next
Verify Timestamp Behavior
- Insert model and confirm both
created_at+updated_atare set. - Update model and confirm only
updated_atchanges. - Validate timezone behavior (
TimestampsvsTimestampsTZ) in your runtime.