What happens when we convert UTC Date time ToUniversalTime? - c#

What happens when we convert UTC Date time ToUniversalTime?
DateTime localDate = DateTime.Now.AddMinute(offsetTimeZone);
DateTime todayStart = localDate.Date.ToUniversalTime().AddHours(00).AddMinutes(00);

There is a -lot- going on when converting using ToUniversalTime. DST is addressed, local time, etc. etc.
Just go to the reference source and read through the code:
http://referencesource.microsoft.com/#mscorlib/system/datetime.cs,fddce8be2da82dfc

There is already the same question on stackoverflow.
here is no implicit timezone attached to a DateTime object. If you run ToUniversalTime() on it, it uses the timezone of the context that the code is running in.
For example, if I create a DateTime from the epoch of 1/1/1970, it gives me the same DateTime object no matter where in the world I am.
If I run ToUniversalTime() on it when I'm running the code in Greenwich, then I get the same time. If I do it while I live in Vancouver, then I get an offset DateTime object of -8 hours.
This is why it's important to store time related information in your database as UTC times when you need to do any kind of date conversion or localization. Consider if your codebase got moved to a server facility in another timezone ;)
You can find the question and the complete answer here.

DateTime objects by default are typed as DateTimeKind.Local. On parsing a date and set it as DateTimeKind.Utc, then ToUniversalTime() performs no conversion. If we run ToUniversalTime(), it uses the timezone of the context that the code is running in.

Related

DateTime in a TimeZone which is not UTC or Local

I have question pertaining to the DateTimeKind struct in C#.
If I have converted a DateTime to a new DateTime (which is not in my local Timezone) using something like:
TimeZoneInfo.ConvertTimeBySystemTimeZoneId(now, "Tokyo Standard Time");
what should I use for the Kind property of that new DateTime? Unspecified feels a bit weird and does not help much with conversions.
I get the feeling that as soon as you use a Timezone which is not your local and not UTC, then you absolutely have to start using the DateTimeOffset struct.
This is more a question about how to handle non-local TimeZones.
When you go beyond your local timezone, you really do need to use the DateTimeOffset class.
When writing a time service, you may want to add a method for converting a DateTime in one non-local timezone to another non-local timezone. This is pretty straight forward when using the DateTimeOffset class:
public DateTimeOffset ConvertToZonedOffset(DateTimeOffset toConvert, string timeZoneId)
{
var universalTime = toConvert.ToUniversalTime(); // first bring it back to the common baseline (or standard)
var dateTimeOffset = TimeZoneInfo.ConvertTime(universalTime, TimeZoneInfo.FindSystemTimeZoneById(timeZoneId));
return dateTimeOffset;
}
The incoming DateTimeOffset has the source offset and the timeZoneId being passed in gives enough information to realize the target timezone (and offset).
And the returned DateTimeOffset has the target offset.
It gets a bit clunkier when you do it with the DateTime struct, if you wanted to provide an equivalent method:
public DateTime ConvertToZonedOffset(DateTime toConvert, string sourceTimeZoneId, string targetTimeZoneId)
{
return TimeZoneInfo.ConvertTimeBySystemTimeZoneId(toConvert, sourceTimeZoneId, targetTimeZoneId);
}
And this is where the DateTimeKind comes in. If you:
pass the DateTime in with the Kind set to either UTC or Local; AND
the sourceTimeZone is neither of those,
then ConvertTimeBySystemTimeZoneId will throw an exception. So, when you are dealing with a "3rd timezone", Kind must be Unspecified. This tells the method to ignore the system clock, to not assume that it is UTC and to go by whatever is passed in as the sourceTimeZone.
It's not as good as the DateTimeOffset version in another way. The returned DateTime has no information about the timezone and the Kind is set to Unspecified. This basically means that it is the responsibility of the calling code to know and track what timezone that date and time is valid in. Not ideal. So much so that I decided to "be opinionated" and get rid of that method. I'll force the calling code to convert the DateTime they may be working with to a DateTimeOffset and to consume one upon return.
Note 1: if Kind is set to Local and the sourceTimeZone matches your local timezone, it will work fine.
Note 2: if Kind is set to Utc and the sourceTimeZone is set to "Coordinated Universal Time", you may get the following TimeZoneNotFoundException:
The time zone ID 'Coordinated Universal Time' was not found on the local computer
I assume that this is because UTC is a standard and not a timezone, despite being returned by TimeZoneInfo.GetSystemTimeZones as a Timezone.
what should I use for the Kind property of that new DateTime? Unspecified feels a bit weird...
...but it's the correct value in this case. The documentation of the DateTimeKind enum is quite clear on this subject:
Local (2): The time represented is local time.
Unspecified (0): The time represented is not specified as either local time or Coordinated Universal Time (UTC).
Utc (1): The time represented is UTC.
Your time is neither local time nor UTC, so the only correct value is Unspecified.
I get the feeling that as soon as you use a Timezone which is not your local and not UTC, then you absolutely have to start using the DateTimeOffset struct.
You don't have to, but it can definitely make your life easier. As you have noticed, DateTime does not provide an option to store the time zone information along with the date. This is exactly what DateTimeOffset is for.

Difference between System.DateTime and System.DateTimeOffset

Can anyone explain the difference between System.DateTime and System.DateTimeOffset in C#.NET? Which is best suited for building web apps with users from different time zones?
A DateTime value defines a particular date and time, it includes a Kind property that provides limited information about the time zone to which that date and time belongs.
The DateTimeOffset structure represents a date and time value, together with an offset that indicates how much that value differs from UTC. Thus, the value always unambiguously identifies a single point in time.
DateTimeOffset should be considered the default date and time type for application development as the uses for DateTimeOffset values are much more common than those for DateTime values.
See more info, code examples at:
http://msdn.microsoft.com/en-us/library/bb384267.aspx
There are a couple of point here:
DateTime information should be stored in UTC format in your database:
https://web.archive.org/web/20201202215446/http://www.4guysfromrolla.com/articles/081507-1.aspx
When you use DateTime information in your Web Application you will need to convert it to LocalTime:
DateTime.UtcNow.ToLocalTime();
will convert it to the local time from the Web Server's perspective.
If you have a WebServer in one location, serving clients in multiple countries, then you will need to perform this operation in javascript on the Client itself:
myUTCDate.toLocaleTimeString();
http://www.java2s.com/Code/JavaScript/Date-Time/ConvertDatetoLocaleString.htm
DateTimeOffset represents the datetime as UTC datetime.
So
DateTimeOffset dtoNow = DateTimeOffset.Now;
is same as
DateTimeOffset dtoUTCNow = DateTimeOffset.UTCNow;
Here dtoNow will be equal to dtoUTCNow even though one was initialized to DateTimeOffset.Now and the other was initialize to DateTimeOffset.UTCNow;
So DatetimeOffset is good for storing the difference or Offset w.r.t UTC.
For more details refer to MSDN.

DateTime.kind property

Have a small doubt with the DateTime.kind property. Documentation says that kind property have three fields Unspecified, Local, and Utc to show how the datetime object is represented.
DateTime dt1 = DateTime.Now;
Console.WriteLine(dt1.Kind);
Which shows "Local" but in some microsoft documentation I red that system date and time that Windows maintains is UTC rather than local time.
If that is the case then the above WriteLine should output it as UTC rather than Local?
Any idea?
--Rahul
DateTime.Now is meant to retrieve the current local time. DateTime.UtcNow retrieves the current UTC time.
Note that this is unrelated to how Windows itself stores the time. I believe it stores the current time in UTC, but also keeps track of the current time zone, so it can display the appropriate local time. I believe this is what DateTime.Now does as well.

Datetime nightmare, any thorough module or control in C# to help ease the pain?

once again I have to create a date module, and once again i live the horror of perfecting it, is it me or are date and time the filthiest animals in programming profession, its the beast lurking behind the door that I wish I never have to deal with :(
does anyone know of a great source I can learn from that deals with dates in the following aspects:
user enters datetime and time zone
system translates to universal time and saves in data source
system retrieves universal time converted to local time chosen by developer (not by server or client location which may not be the right zone to display)
system should consider daylight time saving differences
cannot rely on "DateTime" parsing as it parses bohemiangly with respect to local server time
must give ability to developer to deal in both shapes: datetime and string objects
i looked at blogengine.net to see how they deal with but its too nieve, they save the time difference in hours in the settings datasource, it is absoluteley inaccurate... any sources to help?
i already went far in creating the necessary methods that use CultureInfo, TimeZoneInfo, DateTimeOffset ... yet when i put it to the test, it failed! appreciate the help
EDIT:
After squeezing some more, i narrowed it down to this:
public string PrettyDate(DateTime s, string format)
{
// this one parses to local then returns according to timezone as a string
s = TimeZoneInfo.ConvertTimeBySystemTimeZoneId(s, "AUS Eastern Standard Time");
CultureInfo Culture = CultureInfo.CreateSpecificCulture("en-au");
return s.ToString(format , Culture);
}
problem is, I know the passed date is UTC time because im using
DateTimeOffset.Parse(s, _dtfi).UtcDateTime;
// where dtfi has "yyyy-MM-ddTHH:mmzzz" as its FullDateTimePattern
when i call the function on my datetime, like this:
AuDate.Instance.PrettyDate(el.EventDate,"yyyy-MM-dd HH:mm zzz");
on my machine i get:
2009-11-26 15:01 +11:00
on server I get:
2009-11-26 15:01 -08:00
I find this very peculiar! why is the timezone incorrect? everything else is in place! have i missed something?
My comments for your pointers.
user enters datetime and time zone
# OK no issue
system translates to universal time and saves in data source
# OK no issue
system retrieves universal time converted to local time chosen by developer (not by server or client location which may not be the right zone to display)
# Is this s requirement? Why not just retrieve as universal time
system should consider daylight time saving differences
# Can be handled by DaylightTime Class, TimeZone Class etc
cannot rely on "DateTime" parsing as it parses bohemiangly with respect to local server time
# Then do not rely on DateTime Parsing
must give ability to developer to deal in both shapes: datetime and string objects
# DateTime Class as the basis should be good enough, use TimeZone / TimeZoneInfo / DaylightTime / DateTimeOffset etc to augment it
I feel your pain - which is why I'm part of the Noda Time project to bring a fully-featured date and time API to .NET. However, that's just getting off the ground. If you're still stuck in a year's time, hopefully Noda Time will be the answer :)
The normal .NET situation is better than it was now that we've got DateTimeOffset and TimeZoneInfo, but it's still somewhat lacking.
So long as you use TimeZoneInfo correctly twice, however, it should be fine. I'm not sure that DateTime parsing should be too bad - I think it should parse it as DateTimeKind.Unspecified unless you specify anything else in the data. You can then convert it to UTC using TimeZoneInfo.
Could you provide a short but complete program which shows the problems you're having?
Actually, I find the .NET date/time functionality to be quite nice. I'm puzzled by your troubles with it.
What exactly are you trying to do that DateTimeOffset and TimeZoneInfo can't do for you?
"User enters datetime and timezone" -- Check! Either DateTime or DateTimeOffset would work here.
"System translates to universal time and saves in data source" -- Check! Again, either DateTime or DateTimeOffset would work for you, although most database backends will need some special handling if you want to store timezone offsets. If you're already converting it to UTC, just store it as a datetime field in SQL Server or the equivalent in another RDBMS and don't worry about storing the fact that it's UTC.
"System retrieves universal time converted to local time chosen by the developer" -- Check! Just construct a TimeZoneInfo for your desired local time, and then call TimeZoneInfo.ConvertTime.
"System should consider daylight time saving differences" -- Check! That's what TimeZoneInfo.AdjustmentRule is for.
"Cannot rely on "DateTime" parsing as it parses bohemiangly with respect to local server time" -- ??? First off, "bohemiangly" isn't even a word. And you can customize how the datetime gets parsed with DateTime.ParseExact.
"Must give ability to developer to deal in both shapes: datetime and string objects" -- Why? What's wrong with just keeping one internal representation and then transforming only on input and output? I can't think of any operation on date/time values that would be made easier by doing it against a string.
In short, I think you're just griping about the complexities of handling date/time data in general.
Thanks to Jon Skeet who put me on the right track, i never knew this before but now I know, DateTime object does not hold time zone information in it AT ALL! so whenever i use it i am already losing the datetime offset information, the DateTimeOffset object however, retains the time zone bit, so all my objects should use that, i really thought datetimeoffset object to be a bit limiting, i wanted to post a question about what is different between datetime and datetimeoffset, i should have done that!
now Im using the following code to retrieve the right zone:
string s = "2009-11-26T04:01:00.0000000Z";
DateTimeOffset d = DateTimeOffset.Parse(s);
TimeZoneInfo LocalTimeZoneInfo = TimeZoneInfo.FindSystemTimeZoneById("AUS Eastern Standard Time");
DateTimeOffset newdate = TimeZoneInfo.ConvertTime(d, LocalTimeZoneInfo);
return newdate.ToString("yyyy-MM-dd HH:mm zzz");
thank you all for your input

Convert UTC/GMT time to local time

We are developing a C# application for a web-service client. This will run on Windows XP PC's.
One of the fields returned by the web service is a DateTime field. The server returns a field in GMT format i.e. with a "Z" at the end.
However, we found that .NET seems to do some kind of implicit conversion and the time was always 12 hours out.
The following code sample resolves this to some extent in that the 12 hour difference has gone but it makes no allowance for NZ daylight saving.
CultureInfo ci = new CultureInfo("en-NZ");
string date = "Web service date".ToString("R", ci);
DateTime convertedDate = DateTime.Parse(date);
As per this date site:
UTC/GMT Offset
Standard time zone: UTC/GMT +12 hours
Daylight saving time: +1 hour
Current time zone offset: UTC/GMT +13 hours
How do we adjust for the extra hour? Can this be done programmatically or is this some kind of setting on the PC's?
For strings such as 2012-09-19 01:27:30.000, DateTime.Parse cannot tell what time zone the date and time are from.
DateTime has a Kind property, which can have one of three time zone options:
Unspecified
Local
Utc
NOTE If you are wishing to represent a date/time other than UTC or your local time zone, then you should use DateTimeOffset.
So for the code in your question:
DateTime convertedDate = DateTime.Parse(dateStr);
var kind = convertedDate.Kind; // will equal DateTimeKind.Unspecified
You say you know what kind it is, so tell it.
DateTime convertedDate = DateTime.SpecifyKind(
DateTime.Parse(dateStr),
DateTimeKind.Utc);
var kind = convertedDate.Kind; // will equal DateTimeKind.Utc
Now, once the system knows its in UTC time, you can just call ToLocalTime:
DateTime dt = convertedDate.ToLocalTime();
This will give you the result you require.
I'd look into using the System.TimeZoneInfo class if you are in .NET 3.5. See http://msdn.microsoft.com/en-us/library/system.timezoneinfo.aspx. This should take into account the daylight savings changes correctly.
// Coordinated Universal Time string from
// DateTime.Now.ToUniversalTime().ToString("u");
string date = "2009-02-25 16:13:00Z";
// Local .NET timeZone.
DateTime localDateTime = DateTime.Parse(date);
DateTime utcDateTime = localDateTime.ToUniversalTime();
// ID from:
// "HKEY_LOCAL_MACHINE\Software\Microsoft\Windows NT\CurrentVersion\Time Zone"
// See http://msdn.microsoft.com/en-us/library/system.timezoneinfo.id.aspx
string nzTimeZoneKey = "New Zealand Standard Time";
TimeZoneInfo nzTimeZone = TimeZoneInfo.FindSystemTimeZoneById(nzTimeZoneKey);
DateTime nzDateTime = TimeZoneInfo.ConvertTimeFromUtc(utcDateTime, nzTimeZone);
TimeZone.CurrentTimeZone.ToLocalTime(date);
DateTime objects have the Kind of Unspecified by default, which for the purposes of ToLocalTime is assumed to be UTC.
To get the local time of an Unspecified DateTime object, you therefore just need to do this:
convertedDate.ToLocalTime();
The step of changing the Kind of the DateTime from Unspecified to UTC is unnecessary. Unspecified is assumed to be UTC for the purposes of ToLocalTime: http://msdn.microsoft.com/en-us/library/system.datetime.tolocaltime.aspx
I know this is an older question, but I ran into a similar situation, and I wanted to share what I had found for future searchers, possibly including myself :).
DateTime.Parse() can be tricky -- see here for example.
If the DateTime is coming from a Web service or some other source with a known format, you might want to consider something like
DateTime.ParseExact(dateString,
"MM/dd/yyyy HH:mm:ss",
CultureInfo.InvariantCulture,
DateTimeStyles.AssumeUniversal | DateTimeStyles.AdjustToUniversal)
or, even better,
DateTime.TryParseExact(...)
The AssumeUniversal flag tells the parser that the date/time is already UTC; the combination of AssumeUniversal and AdjustToUniversal tells it not to convert the result to "local" time, which it will try to do by default. (I personally try to deal exclusively with UTC in the business / application / service layer(s) anyway. But bypassing the conversion to local time also speeds things up -- by 50% or more in my tests, see below.)
Here's what we were doing before:
DateTime.Parse(dateString, new CultureInfo("en-US"))
We had profiled the app and found that the DateTime.Parse represented a significant percentage of CPU usage. (Incidentally, the CultureInfo constructor was not a significant contributor to CPU usage.)
So I set up a console app to parse a date/time string 10000 times in a variety of ways. Bottom line:
Parse() 10 sec
ParseExact() (converting to local) 20-45 ms
ParseExact() (not converting to local) 10-15 ms
... and yes, the results for Parse() are in seconds, whereas the others are in milliseconds.
I'd just like to add a general note of caution.
If all you are doing is getting the current time from the computer's internal clock to put a date/time on the display or a report, then all is well. But if you are saving the date/time information for later reference or are computing date/times, beware!
Let's say you determine that a cruise ship arrived in Honolulu on 20 Dec 2007 at 15:00 UTC. And you want to know what local time that was.
1. There are probably at least three 'locals' involved. Local may mean Honolulu, or it may mean where your computer is located, or it may mean the location where your customer is located.
2. If you use the built-in functions to do the conversion, it will probably be wrong. This is because daylight savings time is (probably) currently in effect on your computer, but was NOT in effect in December. But Windows does not know this... all it has is one flag to determine if daylight savings time is currently in effect. And if it is currently in effect, then it will happily add an hour even to a date in December.
3. Daylight savings time is implemented differently (or not at all) in various political subdivisions. Don't think that just because your country changes on a specific date, that other countries will too.
#TimeZoneInfo.ConvertTimeFromUtc(timeUtc, TimeZoneInfo.Local)
Don't forget if you already have a DateTime object and are not sure if it's UTC or Local, it's easy enough to use the methods on the object directly:
DateTime convertedDate = DateTime.Parse(date);
DateTime localDate = convertedDate.ToLocalTime();
How do we adjust for the extra hour?
Unless specified .net will use the local pc settings. I'd have a read of: http://msdn.microsoft.com/en-us/library/system.globalization.daylighttime.aspx
By the looks the code might look something like:
DaylightTime daylight = TimeZone.CurrentTimeZone.GetDaylightChanges( year );
And as mentioned above double check what timezone setting your server is on. There are articles on the net for how to safely affect the changes in IIS.
In answer to Dana's suggestion:
The code sample now looks like:
string date = "Web service date"..ToString("R", ci);
DateTime convertedDate = DateTime.Parse(date);
DateTime dt = TimeZone.CurrentTimeZone.ToLocalTime(convertedDate);
The original date was 20/08/08; the kind was UTC.
Both "convertedDate" and "dt" are the same:
21/08/08 10:00:26; the kind was local
I had the problem with it being in a data set being pushed across the wire (webservice to client) that it would automatically change because the DataColumn's DateType field was set to local. Make sure you check what the DateType is if your pushing DataSets across.
If you don't want it to change, set it to Unspecified
I came across this question as I was having a problem with the UTC dates you get back through the twitter API (created_at field on a status); I need to convert them to DateTime. None of the answers/ code samples in the answers on this page were sufficient to stop me getting a "String was not recognized as a valid DateTime" error (but it's the closest I have got to finding the correct answer on SO)
Posting this link here in case this helps someone else - the answer I needed was found on this blog post: http://www.wduffy.co.uk/blog/parsing-dates-when-aspnets-datetimeparse-doesnt-work/ - basically use DateTime.ParseExact with a format string instead of DateTime.Parse
This code block uses universal time to convert current DateTime object then converts it back to local DateTime. Works perfect for me I hope it helps!
CreatedDate.ToUniversalTime().ToLocalTime();

Categories