C# datetime format and storing timezone info - c#

I am getting strings in the form:
"2011-10-12T11:55:34.803EST"
"2011-10-05T16:58:05.043GMT"
I would like to store these values as DateTime objects but a simple DateTime.Parse() does not work. Is there anyway I can convert those strings to DateTime objects? As far as I can tell, DateTime does not know about timezones.

You can replace GMT with z and it will work:
string date = "2011-10-05T16:58:05.043GMT".Replace("GMT", "z");
Console.WriteLine(DateTime.Parse(date));
Zulu time

+1 to IAbstractDownvoteFactor - Z is the best zone.
Your date time look almost like Iso8601, but with custom time zones (http://en.wikipedia.org/wiki/ISO_8601#Time_zone_designators for initial information).
Working with time zones is very hard as rules for them may change and some can appear and disappear. If you can influence incoming format - ask for UTC (Z) or absolute offset (+08:00) in time zones.
Otherwise you need to figure out what time zone you need to support, figure out if rules ever changed and if daylight saving zones are set correctly (i.e. PDT/PST used when appropriate). Have fun.

Related

How to change UTC timezone and get actual time?

The thing I am trying to achieve is, by using int values, change UTC datetime and receive time from different timezones.
Int values supposed to be:
0 = UTC+00:00
1 = UTC+01:00
...
By logic, it supposed to be something like:
int timezoneInt = 1;
var newDate = DateTime.UtcNow.AddMinutes(timezoneInt*60);
But the problem is that this not include summer/winter time.
For example:
My location is in UTC+02:00 and time is 09:20 AM. I need to get UTC+00:00 (which is equal to DateTime.UtcNow and supposed to be(?) 07:20 AM). Because of summer time, right now .UtcNow is 06:20 AM, so I can't just multiply 60 minutes by int value, I also need to include summer time factor somehow.
How I suposed to accomplish that, or what I am missing or understanded whong?
EDIT:
Was marked as dublicate. Well, here I don't see anything which will help change time by using int value as timezone.
Adjustments for daylight savings require an extensive timezone database which also records the dates and times when that zone changes to daylight savings, and what the new UTC offset is.
DST databases are not easy to build (or even use, in some cases) and must be manually researched and maintained as they are political, not technical - countries can change their daylight savings dates as they wish and so the database also needs to record historical dates.
The .NET Framework has a built-in TimeZoneInfo class (which obsoletes the TimeZone class) which makes use of the timezone database built-in to Windows or whatever the host OS is. Windows' timezone database uses full names to identify zones, whereas Linux and tzdb use IDs like America/New_York.
Note that generally you should never perform these calculations yourself as there are always numerous edge-cases to be aware of. Just use DateTimeOffset.
Also, there is not a 1:1 mapping between UTC offsets and timezones: different timezones share the same UTC offset but have different daylight savings rules (e.g. the British Time timezone uses UTC+0 as their normal UTC offset but UTC+1 in summer, but if you see "UTC+1" that could be either the British zone in summer or a West-African timezone such as Algeria's which is UTC+1, but does not use daylight savings at all.
Copied verbatim from the timezone tag wiki:
Time Zone != Offset
A time zone can not be represented solely by an offset from UTC. Many time zones have more than one offset due to daylight saving time (aka "summer time") rules. The dates that offsets change are also part of the rules for the time zone, as are any historical offset changes. Many software programs, libraries, and web services disregard this important detail, and erroneously call the standard or current offset the "zone". This can lead to confusion, and misuse of the data. Please use the correct terminology whenever possible.
An offset is just a number that represents how far a particular date/time value is ahead or behind UTC.
Most offsets are expressed in whole hours.
But there are many that are 30-minute offset.
And there are a few that are 45-minute offset.
A time zone contains much more:
A name or ID that can be used to identify the zone.
One or more offsets from UTC
The specific dates and times that the zone transitions between offsets.
Sometimes, a separate language-specific display name that can be presented to a user.
One can determine the correct offset, given a time zone and a datetime. But one cannot determine the correct time zone given just an offset.
You are asking how to ignore this fact and make it work anyway - which is not possible. You cannot use an integer offset and expect it to understand daylight saving time. Any solution that tries to defeat this will be taking a bias towards one particular set of daylight saving time rules, which are quite different from country to country.

How to combine date time and Timezone offset in an ASP.net application?

My web service call to a third party applications returns the date,time zone and timezone_offset values. I need to add this to a calendar in Asp.net application. What is the best way to combine this together so that my date object understands that its from Eastern time zone?
<start_date>2014-11-17 19:00:00</start_date>
<timezone>America/New_York</timezone>
<timezone_offset>GMT-0500</timezone_offset>
Since you have the offset too, you can use DateTimeOffset.Parse() to get the DateTimeOffset. From there, you can read the DateTime property. The output dt variable will have 2014-11-17 7:00:00 PM with DateTimeKind property set to "Unspecified"
var dtOffset = DateTimeOffset.Parse("2014-11-17 19:00:00-0500", CultureInfo.InvariantCulture);
var dt = dtOffset.DateTime;
A DateTimeOffset represents a point in time. Usually, its relative to UTC. So, it is a natural structure to initially parse the fields that you have.
If you want a reference to the same datetime in UTC, you can use this. Here the output dt variable will have 2014-11-18 12:00:00 AM with DateTimeKind property set to "Utc"
var dt = DateTime.Parse("2014-11-17 19:00:00-0500", CultureInfo.InvariantCulture).ToUniversalTime();
If you don't have the offset but just have the timeZoneId, you can still do it but you need NodaTime for that.
I'll focus on this part of the question:
What is the best way to combine this together so that my date object understands that its from Eastern time zone?
There is no data type built in to .NET that can sufficiently do that. The DateTimeOffset type associates with a particular offset, such as the -05:00 or -04:00 that might be in use by the Eastern time zone (depending on the date). But those same offsets might also be sourced from some other time zone entirely. A time zone has one or more offsets, but an offset isn't a time zone itself.
Fortunately there are solutions. There are two options to consider:
You could pair a DateTimeOffset with a TimeZoneInfo object. When storing or transmitting these, you would only send the full DateTimeOffset along with the Id of the time zone.
The Noda Time library is a much more effective way to work with date and time, especially when it comes to time zone concerns. It contains a type called ZonedDateTime that already combines a date, time, offset, and time zone. It can also be used to work with IANA time zone identifiers, such as the "America/New_York" time zone you specified in the question.

How to convert Datetimes into UTC based timing values to compare timings- C#

I've string (variable is fileDate) with Date values in the following format:
2/12/2011 11:58 AM
Now I want to convert this to a date and then to UTC time based as I've problems in comparing dates in different machines, so *I always want to convert all strings (which are getting compared) to Utc_date values.*
I tried this code below but it did not work as I'm not able to convert the above string to Datetime based (as it does not have seconds).
DateTime date = Convert.ToDateTime(fileDate);
date = DateTime.SpecifyKind(date, DateTimeKind.Utc);
fileDate = date.ToString("MM/dd/yyyy hh:mm tt");
Above did not work showing FormatException.
Can you pl help?
To start with, I'd suggest using DateTime.ParseExact or TryParseExact - it's not clear to me whether your sample is meant to be December 2nd or February 12th. Specifying the format may well remove your FormatException.
The next problem is working out which time zone you want to convert it with - are you saying that 11:58 is a local time in some time zone, or it's already a UTC time?
If it's a local time in the time zone of the code which is running this, you can use DateTimeStyles.AssumeLocal | DateTimeStyles.AdjustToUniversal to do it as part of parsing.
If it's already a universal time, use DateTimeStyles.AssumeUniversal
If it's a local time in a different time zone, you'll need to use TimeZoneInfo to perform the conversion.
Also, if it's a local time you'll need to consider two corner cases (assuming you're using a time zone which observes daylight saving time):
A local time may be skipped due to DST transitions, when the clocks go forward. So if the clocks skip from 1am to 2am, then 1:30am doesn't exist at all.
A local time may be ambiguous due to DST transitions, when the clocks go back. So if the clocks go back from 2am to 1am, then 1:30am occurs twice at different UTC times - which occurrence are you interested in?
You should decide how you want to handle these cases, and make sure they're covered in your unit tests.
Another option is to use my date and time library, Noda Time, which separates the concepts of "local date/time" and "date/time in a particular time zone" (and others) more explicitly.
you should be using DateTime.ParseExact to get the value into a proper DateTime instance, and then you can use .ToUniversalTime() to get the UTC time (this would be with respect to the difference of time as in your server machine)
you can use :
DateTime.Now.ToUniversalTime();
i don't mean to say to you should use "DateTime.Now" but you get the point that as a part of the DateTime object you have a method to transform it to Universal time
http://msdn.microsoft.com/en-us/library/system.datetime.touniversaltime.aspx

How to store my dates?

I don't have much experience with Utc Dates, but from what I know, they are in most cases the best way to store dates.
But I'm currently working on a program and I'm in doubt what will be the best way to store my dates. In the program, a user can follow a course for five weeks, starting on the day of registration. Every day he has to fill in a form, which is saved for that day.
Currently, I'm saving the StartDate and EndDate of the course as DateTime (no Utc) Should I save this as Utc, or isn't it necessary? Because I only need the day (if the user registers on February 8th at 10:04, all the system needs to know is that February 8th is the first day of the course. Is there maybe a better way to store this information? And what would be the best way to save system-event-dates (like user logged in, account created, etc)?
I used to store the form-data also with a DateTime, to calculate on which day it was submitted, but I changed it so it only saves the relative day-number (e.g. day 5).
Btw, I'm using C# and a SQL Server database.
UTC (Coordinated Universal Time) has to do with the time component of a date. It's a standard way to store DateTimes so that you can compare without worrying about timezones.
If all you are worried about is the Date Component & Timezone/Location is unimportant you could just store it in the database as 2012-02-01 00:00:00
You can get the date only component in .NET using
System.DateTime.Today;
Alternatively if you're working with some other Date...
DateTime dt = DateTime.Now;
dt.Date; // <--- this will give the Date Component with the Time stripped back to 00:00:00
Why don't you just store the dates in a DATE database column, and not worry about time zones at all?
Generally you want to store in UTC if there is a functional requirement for your system to be able to work with users in different timezones.
Let's say you have a user in Hong Kong and a user in Sydney looking at the same event. If you want them both see the event date (and time) in their timezones, then here we are, you will probably need to store it in UTC and then present to users respecting their geo locations.
If you don't have such requirements, you don't do such conversions and you only assume one timezone then you don't need to add more complexity into your system, just use Date column and store the current date there.
But if you do - go for UTC. In this scenario you will need DateTime, not just Date. This is because 21:30 in one timezone can be 2:30 next day in another timezone so time really matters.
When showing to a user you may convert it to the user's timezone and then throw time away, but in order to make the conversion correct you will need to keep time.
It is easy to work with UTC in .NET, DateTime has .ToUniversalTime() method that converts a datetime value to UTC for you:
var utcNow = DateTime.Now.ToUniversalTime();
there is also a property:
var utcNow = DateTime.UtcNow;
EDITED
Use TimeZoneInfo static class to convert datetimes from/to timezones you need (for example from UTC to the specified user's timezone:
TimeZoneInfo.ConvertTimeToUtc(...)
TimeZoneInfo.ConvertTimeFromUtc(...)

DateTime vs DateTimeOffset

What is the difference between a DateTime and a DateTimeOffset and when should one be used?
Currently, we have a standard way of dealing with .NET DateTimes in a TimeZone-aware way: Whenever we produce a DateTime we do it in UTC (e.g. using DateTime.UtcNow), and whenever we display one, we convert back from UTC to the user's local time.
That works fine, but I've been reading about DateTimeOffset and how it captures the local and UTC time in the object itself.
DateTimeOffset is a representation of instantaneous time (also known as absolute time). By that, I mean a moment in time that is universal for everyone (not accounting for leap seconds, or the relativistic effects of time dilation). Another way to represent instantaneous time is with a DateTime where .Kind is DateTimeKind.Utc.
This is distinct from calendar time (also known as civil time), which is a position on someone's calendar, and there are many different calendars all over the globe. We call these calendars time zones. Calendar time is represented by a DateTime where .Kind is DateTimeKind.Unspecified, or DateTimeKind.Local. And .Local is only meaningful in scenarios where you have an implied understanding of where the computer that is using the result is positioned. (For example, a user's workstation)
So then, why DateTimeOffset instead of a UTC DateTime? It's all about perspective. Let's use an analogy - we'll pretend to be photographers.
Imagine you are standing on a calendar timeline, pointing a camera at a person on the instantaneous timeline laid out in front of you. You line up your camera according to the rules of your timezone - which change periodically due to daylight saving time, or due to other changes to the legal definition of your time zone. (You don't have a steady hand, so your camera is shaky.)
The person standing in the photo would see the angle at which your camera came from. If others were taking pictures, they could be from different angles. This is what the Offset part of the DateTimeOffset represents.
So if you label your camera "Eastern Time", sometimes you are pointing from -5, and sometimes you are pointing from -4. There are cameras all over the world, all labeled different things, and all pointing at the same instantaneous timeline from different angles. Some of them are right next to (or on top of) each other, so just knowing the offset isn't enough to determine which timezone the time is related to.
And what about UTC? Well, it's the one camera out there that is guaranteed to have a steady hand. It's on a tripod, firmly anchored into the ground. It's not going anywhere. We call its angle of perspective the zero offset.
So - what does this analogy tell us? It provides some intuitive guidelines-
If you are representing time relative to some place in particular, represent it in calendar time with a DateTime. Just be sure you don't ever confuse one calendar with another. Unspecified should be your assumption. Local is only useful coming from DateTime.Now. For example, I might get DateTime.Now and save it in a database - but when I retrieve it, I have to assume that it is Unspecified. I can't rely that my local calendar is the same calendar that it was originally taken from.
If you must always be certain of the moment, make sure you are representing instantaneous time. Use DateTimeOffset to enforce it, or use UTC DateTime by convention.
If you need to track a moment of instantaneous time, but you want to also know "What time did the user think it was on their local calendar?" - then you must use a DateTimeOffset. This is very important for timekeeping systems, for example - both for technical and legal concerns.
If you ever need to modify a previously recorded DateTimeOffset - you don't have enough information in the offset alone to ensure that the new offset is still relevant for the user. You must also store a timezone identifier (think - I need the name of that camera so I can take a new picture even if the position has changed).
It should also be pointed out that Noda Time has a representation called ZonedDateTime for this, while the .Net base class library does not have anything similar. You would need to store both a DateTimeOffset and a TimeZoneInfo.Id value.
Occasionally, you will want to represent a calendar time that is local to "whomever is looking at it". For example, when defining what today means. Today is always midnight to midnight, but these represent a near-infinite number of overlapping ranges on the instantaneous timeline. (In practice we have a finite number of timezones, but you can express offsets down to the tick) So in these situations, make sure you understand how to either limit the "who's asking?" question down to a single time zone, or deal with translating them back to instantaneous time as appropriate.
Here are a few other little bits about DateTimeOffset that back up this analogy, and some tips for keeping it straight:
If you compare two DateTimeOffset values, they are first normalized to zero offset before comparing. In other words, 2012-01-01T00:00:00+00:00 and 2012-01-01T02:00:00+02:00 refer to the same instantaneous moment, and are therefore equivalent.
If you are doing any unit testing and need to be certain of the offset, test both the DateTimeOffset value, and the .Offset property separately.
There is a one-way implicit conversion built in to the .Net framework that lets you pass a DateTime into any DateTimeOffset parameter or variable. When doing so, the .Kind matters. If you pass a UTC kind, it will carry in with a zero offset, but if you pass either .Local or .Unspecified, it will assume to be local. The framework is basically saying, "Well, you asked me to convert calendar time to instantaneous time, but I have no idea where this came from, so I'm just going to use the local calendar." This is a huge gotcha if you load up an unspecified DateTime on a computer with a different timezone. (IMHO - that should throw an exception - but it doesn't.)
Shameless Plug:
Many people have shared with me that they find this analogy extremely valuable, so I included it in my Pluralsight course, Date and Time Fundamentals. You'll find a step-by-step walkthrough of the camera analogy in the second module, "Context Matters", in the clip titled "Calendar Time vs. Instantaneous Time".
From Microsoft:
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.
source: "Choosing Between DateTime, DateTimeOffset, TimeSpan, and TimeZoneInfo", MSDN
We use DateTimeOffset for nearly everything as our application deals with particular points in time (e.g. when a record was created/updated). As a side note, we use DATETIMEOFFSET in SQL Server 2008 as well.
I see DateTime as being useful when you want to deal with dates only, times only, or deal with either in a generic sense. For example, if you have an alarm that you want to go off every day at 7 am, you could store that in a DateTime utilizing a DateTimeKind of Unspecified because you want it to go off at 7am regardless of DST. But if you want to represent the history of alarm occurrences, you would use DateTimeOffset.
Use caution when using a mix of DateTimeOffset and DateTime especially when assigning and comparing between the types. Also, only compare DateTime instances that are the same DateTimeKind because DateTime ignores timezone offset when comparing.
DateTime is capable of storing only two distinct times, the local time and UTC. The Kind property indicates which.
DateTimeOffset expands on this by being able to store local times from anywhere in the world. It also stores the offset between that local time and UTC. Note how DateTime cannot do this unless you'd add an extra member to your class to store that UTC offset. Or only ever work with UTC. Which in itself is a fine idea btw.
This piece of code from Microsoft explains everything:
// Find difference between Date.Now and Date.UtcNow
date1 = DateTime.Now;
date2 = DateTime.UtcNow;
difference = date1 - date2;
Console.WriteLine("{0} - {1} = {2}", date1, date2, difference);
// Find difference between Now and UtcNow using DateTimeOffset
dateOffset1 = DateTimeOffset.Now;
dateOffset2 = DateTimeOffset.UtcNow;
difference = dateOffset1 - dateOffset2;
Console.WriteLine("{0} - {1} = {2}",
dateOffset1, dateOffset2, difference);
// If run in the Pacific Standard time zone on 4/2/2007, the example
// displays the following output to the console:
// 4/2/2007 7:23:57 PM - 4/3/2007 2:23:57 AM = -07:00:00
// 4/2/2007 7:23:57 PM -07:00 - 4/3/2007 2:23:57 AM +00:00 = 00:00:00
The most important distinction is that DateTime does not store time zone information, while DateTimeOffset does.
Although DateTime distinguishes between UTC and Local, there is absolutely no explicit time zone offset associated with it. If you do any kind of serialization or conversion, the server's time zone is going to be used. Even if you manually create a local time by adding minutes to offset a UTC time, you can still get bit in the serialization step, because (due to lack of any explicit offset in DateTime) it will use the server's time zone offset.
For example, if you serialize a DateTime value with Kind=Local using Json.Net and an ISO date format, you'll get a string like 2015-08-05T07:00:00-04. Notice that last part (-04) had nothing to do with your DateTime or any offset you used to calculate it... it's just purely the server's time zone offset.
Meanwhile, DateTimeOffset explicitly includes the offset. It may not include the name of the time zone, but at least it includes the offset, and if you serialize it, you're going to get the explicitly included offset in your value instead of whatever the server's local time happens to be.
There's a few places where DateTimeOffset makes sense. One is when you're dealing with recurring events and daylight savings time. Let's say I want to set an alarm to go off at 9am every day. If I use the "store as UTC, display as local time" rule, then the alarm will be going off at a different time when daylight savings time is in effect.
There are probably others, but the above example is actually one that I've run into in the past (this was before the addition of DateTimeOffset to the BCL - my solution at the time was to explicitly store the time in the local timezone, and save the timezone information along side it: basically what DateTimeOffset does internally).
TLDR if you don't want to read all these great answers :-)
Explicit:
Using DateTimeOffset because the timezone is forced to UTC+0.
Implicit:
Using DateTime where you hope everyone sticks to the unwritten rule of the timezone always being UTC+0.
(Side note for devs: explicit is always better than implicit!)
(Side side note for Java devs, C# DateTimeOffset == Java OffsetDateTime, read this: https://www.baeldung.com/java-zoneddatetime-offsetdatetime)
DateTime.Now
Fri 03 Dec 21 18:40:11
DateTimeOffset.Now
Fri 03 Dec 21 18:40:11 +02:00
So, DateTimeOffset stores information about how the time relates to UTC, basically the time zone.
A major difference is that DateTimeOffset can be used in conjunction with TimeZoneInfo to convert to local times in timezones other than the current one.
This is useful on a server application (e.g. ASP.NET) that is accessed by users in different timezones.
The only negative side of DateTimeOffset I see is that Microsoft "forgot" (by design) to support it in their XmlSerializer class. But it has since been added to the XmlConvert utility class.
XmlConvert.ToDateTimeOffset
XmlConvert.ToString
I say go ahead and use DateTimeOffset and TimeZoneInfo because of all the benefits, just beware when creating entities which will or may be serialized to or from XML (all business objects then).

Categories

Resources