Udostępnij za pośrednictwem


DateTimeOffset: A New DateTime Structure in .NET 3.5 [Justin Van Patten]

One thing we haven't publicized much on this blog yet is a new date time structure we've added in .NET 3.5 called DateTimeOffset (currently available as part of .NET Framework 3.5 Beta 1).  Kathy mentioned it on her blog a while back and Daniel Moth recently posted about it as well.

DateTimeOffset

DateTimeOffset is a new date time data structure that specifies an exact point in time relative to the UTC time zone.  It is made up of a date time and offset relative to the UTC time zone.  DateTimeOffset includes most of the functionality of the current DateTime and allows seamless conversion to DateTime.  DateTimeOffset also works great with TimeZoneInfo which is also new in .NET 3.5.

Samples

1. Creating a new DateTimeOffset:

DateTimeOffset now = DateTimeOffset.Now;

DateTimeOffset now2 = DateTime.Now;

DateTimeOffset now3 = new DateTimeOffset(DateTime.Now);

 

 

DateTime tvShowPremiere = new DateTime(2007, 6, 13, 8, 0, 0);

DateTimeOffset tvShowPremiereUTC = new DateTimeOffset(tvShowPremiere.ToUniversalTime());

DateTimeOffset tvShowPremiereLA = new DateTimeOffset(tvShowPremiere, new TimeSpan(-7, 0, 0));

DateTimeOffset tvShowPremiereNYC = new DateTimeOffset(tvShowPremiere, new TimeSpan(-4, 0, 0));

DateTimeOffset tvShowPremiereLocal = tvShowPremiere; // implicit cast

 

 

DateTimeOffset utcNewYear07 = new DateTimeOffset(2007, 1, 1, 0, 0, 0,

                                new TimeSpan(0, 0, 0));

DateTimeOffset seattleNewYear07 = new DateTimeOffset(2007, 1, 1, 0, 0, 0,

                                    new TimeSpan(-8, 0, 0));

2. Converting a DateTimeOffset to a DateTime:

DateTime dtSeatleNewYear07Utc = seattleNewYear07.UtcDateTime;

DateTime dtSeattleNewYear07Local = seattleNewYear07.LocalDateTime;

3. Parsing a DateTimeOffset:

DateTimeOffset dateA = DateTimeOffset.Parse("4/15/2006 6:00 AM -7:00");

DateTimeOffset dateB = DateTimeOffset.Parse("4/15/2006 6:00:00 AM -7:00");

DateTimeOffset dateC = DateTimeOffset.Parse("-7:00 4/15/2006 6:00 AM");

DateTimeOffset dateD = DateTimeOffset.Parse("4/15/2006 -7:00 6:00 AM");

Usage Guidance

Anthony Moore has some guidance on when to use DateTimeOffset vs. DateTime:

  • Use DateTimeOffset whenever you are referring to an exact point in time.  For example, use it to calculate "now", transaction times, file change times, logging event times, etc.  If the time zone is not known, use it with UTC.  These uses are much more common than the scenarios where DateTime is preferred, so this should be considered the default.
  • Use DateTime for any cases where the absolute point in time does not apply: e.g. store opening times that apply across time zones.
  • Use DateTime for interop scenarios where the information is a Date and Time without information about the time zone, e.g. OLE Automation, databases, existing .NET APIs that use DateTime, etc.
  • Use DateTime with a 00:00:00 time component to represent whole dates, e.g. Date of birth.
  • Use TimeSpan to represent times of day without a date.

As you can see, DateTimeOffset is the new preferred type to use for the most common date time scenarios.  Future BCL APIs will incrementally start to use and take advantage of DateTimeOffset where it makes sense.  This doesn't mean DateTimeOffset is meant to be a replacement for DateTime—DateTime is still useful in the scenarios mentioned above.

Comments

  • Anonymous
    June 14, 2007
    What's wrong with just using DateTime to refer to UTC? In all our code we have DateTime, and it's always UTC (as is the timezone on all our servers). What am I missing?

  • Anonymous
    June 14, 2007
    Microsoft, This DateTimeOffset type will not be sufficient. I need a DateTime (ie, something that extends DateTime), not something that can convert into a DateTime. Please unseal the type and I will do the work myself.

  • Anonymous
    June 14, 2007
    chronos, DateTime is a structure and thus cannot be inherited.

  • Anonymous
    June 14, 2007
    Then we need an IDateTime interface and all signatures taking a DateTime will need to be depreciated and replaced.

  • Anonymous
    June 14, 2007
    I always use DateTime.UtcNow whenever I'm referring to an exact point in time.

  • Anonymous
    June 14, 2007
    Axel, As do I. However, I have debugged code where specifying UTC was occasionally forgotten. It was a timely and expensive fix. I want it to always be in UTC. Nor do I want to worry that my team will get it right. Why should I always need to make the same settings every time? A UTC-only type would be much more desired. DateTimeOffset only complicates the situation further and is not an ideal solution. I agree that an IDateTime interface is needed.

  • Anonymous
    June 15, 2007
    The comment has been removed

  • Anonymous
    June 16, 2007
    The comment has been removed

  • Anonymous
    June 17, 2007
    >> In any case, an IDateTime interface is really needed and is the best long-term solution. I disagree. Better to make a clear distinction between the two types as has been suggested in the post.

  • Anonymous
    June 17, 2007
    Matthew, A default DateTime is broken 100% of the time. Every single time it will need to be manually set to be UTC. Any exceptions, probably accidental, and often even due to ignorance or poor design, is a bug to be found and fixed. I have fixed dozens of these bugs over the last six years at several different companies. I have created wrapper types to help solve the problem. However, the best that can be done is wrap DateTime because it can not be extended and there are no interfaces to implement. I have also created my own non-wrapper types that provide the necessary functionality. However, it does not fit into the framework because of incompatible signatures. While I have had many unpleasent encounters with this type in particular, the source of the problem is very prevalent throughout the BCL: 1) sealed types and 2) no interfaces. You can do better than this. I am perfectly fine if Microsoft does not want to provide the functionality. But let me. To integrate that into the BCL, though, I will need to be able to either extend the type or implement an interface (appropriate signatures will need to take interface, the implementation).

  • Anonymous
    June 19, 2007
    Will DataSets support DateTimeOffset ? We currently have the DateTimeMode property to control serialization of dateTimes from datasets. Although it has limitations, like you can't set it after you've loaded any rows, so it's a pain for untyped datasets - need to call FillSchema then Fill. And there were bugs with typed datasets - some claim these still aren't fixed in SP1 - see http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=208033&SiteID=1 So, will Datasets allow columns of type DateTimeOffset ? How would that work for untyped datasets where columns are created on the fly based on the SQL statement - do we need a "create dateTimes as DateTimeOffset's" property ? And could we specify a default timezone like UTC, or allow that to be picked up from a database column ? Whilst Oracle has a timestamp with timezone datatype which could map straight to DateTimeOffset, SQL Server doesn't, so how could we set default timezones in that case ? I don't want to get into discussion about whether datasets are evil or not (personally I use objects) but lots of developers do use datasets, so it needs considering.

  • Anonymous
    June 19, 2007
    Magari non è uno dei massimi problemi per chi lavora in Europa e generalmente ha a che fare con un solo

  • Anonymous
    June 20, 2007
    The comment has been removed

  • Anonymous
    August 19, 2007
    " Anthony Moore has some guidance on when to use DateTimeOffset vs. DateTime: Use DateTimeOffset whenever...

  • Anonymous
    September 13, 2007
    Visual Studio (VS) 2008 and .Net 3.5, code named “Orcas”, will be released in the near future. This release

  • Anonymous
    October 22, 2007
    Mein TechTalk ist nun zu Ende. Meine letzte Station heute in Berlin war Lustig und Amüsant, ich hoffe

  • Anonymous
    November 19, 2007
    .NET Framework 3.5 and Visual Studio 2008 have officially shipped! Soma has the announcement on his blog

  • Anonymous
    November 19, 2007
    .NET Framework 3.5 and Visual Studio 2008 have officially shipped! Soma has the announcement on his blog