DateTime vs DateTimeOffset vs long (ticks) for timestamps
See original GitHub issueWe have to decide whether we should use DateTime
, DateTimeOffset
or long
(ticks) for timestamps. Unfortunately, it seems like all of them have certain disadvantages…
Interesting articles:
- Choosing between DateTime, DateTimeOffset, TimeSpan, and TimeZoneInfo
- Converting Times between Time Zones
- Converting between DateTime and DateTimeOffset
Some important quotes:
The
DateTime
structure is suitable for applications that do the following:
- …, Work with UTC dates and times only, …
- When saving or sharing DateTime data, UTC should be used and the DateTime value’s Kind property should be set to DateTimeKind.Utc
The
DateTimeOffset
type includes all of the functionality of the DateTime type along with time zone awareness. This makes it is suitable for applications that do the following:
- Uniquely and unambiguously identify a single point in time. The DateTimeOffset type can be used to unambiguously define the meaning of “now”, to log transaction times, to log the times of system or application events, and to record file creation and modification times.
- Note: These uses for DateTimeOffset values are much more common than those for DateTime values. As a result, DateTimeOffset should be considered the default date and time type for application development.
Converting:
For UTC and local DateTime values, the Offset property of the resulting DateTimeOffset value accurately reflects the UTC or local time zone offset.
However, for DateTime values whose Kind property is DateTimeKind.Unspecified, these two conversion methods produce a DateTimeOffset value whose offset is that of the local time zone.
Ifyour application requires that converted DateTime values unambiguously identify a single point in time, you should consider using the DateTimeOffset.UtcDateTime property to handle all DateTimeOffset to DateTime conversions.
This means, DateTime
would be possible if we would only use UTC. However, for some reason many developers don’t use DateTime.UtcNow
and DateTime.Now
properly. While the former correctly returns a UTC timestamp, the latter returns a timestamp for the current timezone on which the host is running - and this of course is wrong for server scenarios.
Since it’s not guaranteed that everybody uses UtcNow
, if we would use DateTime
, every trace implementation would have to make sure that it either always calls ToUniversalTime()
(or only if Kind
is “Local”). there’s also DateTimeKind.Unspecified which seems to be handled similar to local - this is the kind you get when you manually create a DateTime object.
DateTimeOffset
seems to be more explicit about all of this, however it still uses the local server time zone when you pass a date with kind=Unspecified.
By using DateTime
or DateTimeOffset
we would need to define some recommendations - e.g. Users should always use UTC, tracer implementations should convert kind=local to UTC, tracer implementations should throw an exception if kind=Unspecified, …
Using long ticks
would be an alternative which maybe would make it a bit more obvious for users that they can’t just pass a regular DateTime.Now
and instead have to think about the right thing to do. However, I guess you might still run into the same issues if you use DateTime.Now.Ticks
or new DateTime(...).Ticks
with an unspecified kind. I haven’t yet tested this though.
Other drawbacks of using ticks are that the trace implementations now can’t do any validation and it’s not obvious for users and trace implementations, whether the ticks are UNIX epoch ticks or Windows ticks.
Your opinions?
Issue Analytics
- State:
- Created 7 years ago
- Comments:9 (8 by maintainers)
Top GitHub Comments
@cwe1ss @yurishkuro
While I think it’s fine to use the idiomatic time function per-platform, I feel somewhat strongly that timezones should be avoided in monitoring ingest APIs, except when human-user-facing frontends are involved. I.e., whatever time type we use should support something like epoch microseconds.
@cwe1ss I have no strong opinion, I have no experience with DateTimeOffset, and as you say, if we choose DateTime, we can change later without breaking the client.
I did some more benchmarks, and the really slow operations are DateTime.Now and .ToUniversalTime() on a DateTime with LocalTime. It shows that you should really try to work with UTC instead of local time.