Converting DateTimes by Offsets with NodaTimeWed, Jan 20, 2016
There must be a simple way to convert one
DateTime to another
DateTime using only a GMT/UTC Offset integer… right?
What do I mean by
- The local time on my watch?
- The present global moment in time?
There are constraints on converting between and within these Times. For example, Offset != Time Zone so you must be aware of ambiguities resulting from Daylight Savings Time transitions.
Time is difficult, especially when you start thinking about it. Big mistakes can be made when you don’t think about it.
BCL or No?
There are ways to manipulate Time with the BCL’s
DateTimeOffset classes. However, with its
DateTime violates the Single Responsibility Principle. It can have different behaviors based on this property (Matt Johnson)
Let’s rephrase the original problem so I can to introduce you to a library that I guarantee will help you work with Time more clearly.
Is there a simple way to:
- Given a UTC Offset integer in hours
- *Convert one Global
DateTimeto another Global
DateTimeby UTC Offset?*
There is a simple way, and NodaTime lets us be clear about what we’re trying to do.
Noda Time is an alternative date and time API for .NET. It helps you to think about your data more clearly, and express operations on that data more precisely. - NodaTime.org
NodaTime forces you to make decisions about your use case for Time. This is a good thing. Beyond a slight learning curve, it makes Time easier.
In our case, we have a Global Instant - a moment that the world is observing. Let’s say this Instant at UTC (Offset = 0) is
Instant instant = Instant.FromUtc(2016, 1, 21, 20, 6); // 2016-01-21T20:06:00Z
What Time would this be at UTC-05?
Since we don’t know what Time Zone we are in, we can use Noda’s
OffsetDateTime class. “It preserves the offset information you genuinely have, but without giving the impression of knowing the “real” time zone” (NodaTime User Guide)
Offset offset = Offset.FromHours(-5); OffsetDateTime sourceOffsetDateTime = instant.WithOffset(offset); // 2016-01-21T15:06:00-05
It’s that simple… for this use case.
If we were given a Local
DateTime, we could use Noda’s
LocalDateTime class. If we were concerned about Daylight Savings Time and other Time Zone rules, we could use Noda’s
NodaTime gives you clear separation of concerns with its
We asked if there was a simple way to manipulate
DateTime by UTC Offset.
While there are ways to do this with the BCL’s
DateTime classes, NodaTime forces you to be aware of the different representations of Time and their constraints.
Noda provided us with
OffsetDateTime to help us stay honest about what we could do with UTC Offset. It turned out to be a simple calculation once we clarified our use case.
Some sample code where I was testing a few different calculations with both NodaTime and the BCL can be found here.
As always, stay tuned by sign up for my newsletter. I look forward to hearing from you! Have a great day!
- timeanddate.com. The Difference Between GMT and UTC
- NodaTime.org. NodaTime Core Types Quick Reference
- NodaTime Source. Github
- Matt Johnson. Code of Matt
- Matt Johnson. Code of Matt. Beware the Edge Case of Time
- Matt Johnson. NodaTime Blog. What’s Wrong with DateTime anyway?
- Matt Johnson. TimeZoneNames Library
- Stack Overflow. DateTime vs DateTimeOffset