Use the .NET DateTimeOffset over DateTime when the offset matters

Posted: (EET/GMT+2)

 

If you store timestamps in a .NET application, DateTimeOffset is often a safer choice than plain DateTime.

The difference is that DateTimeOffset stores the date and time together with the offset from UTC.

DateTimeOffset createdAt =
    new DateTimeOffset(2020, 9, 6, 10, 45, 0, TimeSpan.FromHours(3));

Console.WriteLine(createdAt);

This makes the value more explicit:

6.9.2020 10.45.00 +03:00

With DateTime, the value may be local time, UTC time, or unspecified time, depending on the Kind property.

DateTime createdAt = DateTime.Now;

Console.WriteLine(createdAt);
Console.WriteLine(createdAt.Kind);

That works fine inside a single process, but becomes easier to misunderstand when values are stored in a database, sent over an API, or written to logs.

DateTimeOffset makes the offset visible at the value level:

DateTimeOffset now = DateTimeOffset.Now;
DateTimeOffset utcNow = DateTimeOffset.UtcNow;

Console.WriteLine(now);
Console.WriteLine(utcNow);

In SQL Server, the matching column type is datetimeoffset:

CREATE TABLE Orders
(
    Id INT IDENTITY(1,1) PRIMARY KEY,
    CreatedAt DATETIMEOFFSET NOT NULL
);

This preserves the offset together with the timestamp.

For many applications, DateTime is still fine for simple local values. But when the timestamp describes an actual event that happened at a specific moment, DateTimeOffset usually communicates intent more clearly.

A rule of thumb: if the offset matters, store it. If the value is only a local business date or time, keep the model simple.