My database is located in e.g. california.
My user table has all the user's timezone e.g. -0700 UTC
How can I adjust the time from my database server whenever I display a date to the user who lives in e.g. new york? UTC/GMT -4 hours
You should store your data in UTC format and showing it in local timezone format.
DateTime.ToUniversalTime() -> server;
DateTime.ToLocalTime() -> client
You can adjust date/time using AddXXX methods group, but it can be error prone. .NET has support for time zones in System.TimeZoneInfo class.
If you use .Net, you can use TimeZoneInfo. Since you tagged the question with 'c#', I'll assume you do.
The first step is getting the TimeZoneInfo for the time zone in want to convert to. In your example, NY's time zone. Here's a way you can do it:
//This will get EST time zone
TimeZoneInfo clientTimeZone
= TimeZoneInfo.FindSystemTimeZoneById("Eastern Standard Time");
//This will get the local time zone, might be useful
// if your application is a fat client
TimeZoneInfo clientTimeZone = TimeZoneInfo.Local;
Then, after you read a DateTime from your DB, you need to make sure its Kind is correctly set. Supposing the DateTime's in the DB are in UTC (by the way, that's usually recommended), you can prepare it to be converted like this:
DateTime aDateTime = dataBaseSource.ReadADateTime();
DateTime utcDateTime = DateTime.SpecifyKind(aDateTime, DateTimeKind.Utc);
Finally, in order to convert to a different time zone, simply do this:
DateTime clientTime = TimeZoneInfo.ConvertTime(utcDateTime, clientTimeZone);
Some extra remarks:
TimeZoneInfo can be stored in static fields, if you are only interested in a few specific time zones;
TimeZoneInfo store information about daylight saving. So, you wouldn't have to worry about that;
If your application is web, finding out in which time zone your client is in might be hard. One way is explained here: http://kohari.org/2009/06/15/automagic-time-localization/
I hope this helps. :)
You could use a combination of TimeZoneInfo.GetSystemTimeZones() and then use the TimeZoneInfo.BaseUtcOffset property to offset the time in the database based on the offset difference
Info on System.TimeZoneInfo here
Up until .NET 3.5 (VS 2008), .NET does not have any built-in support for timezones, apart from converting to and from UTC.
If the time difference is always exactly 3 hours all year long (summer and winter), simply use yourDate.AddHours(3) to change it one way, and yourDate.AddHours(-3) to change it back. Be sure to factor this out into a function explaining the reason for adding/substracting these 3 hours.
You know, this is a good question. This year I've done my first DB application and as my input data related to time is an Int64 value, that is what I stored off in the DB. My client applications retrieve it and do DateTime.FromUTC() or FromFileTimeUTC() on that value and do a .LocalTime() to show things in their local time. I've wondered whether this was good/bad/terrible but it has worked well enough for my needs thus far. Of course the work ends up being done by a data access layer library I wrote and not in the DB itself.
Seems to work well enough, but I trust others who have more experience with this sort of thing could point out where this is not the best approach.
Good Luck!
Related
Our application was designed to handle user from different Geographic location.
We are unable to detect what is the current end user local time and
time zone operate on it. They select different culture like sv-se,
en-us, ta-In even they access from Europe/London timezone..
We hosted it in a hosting server in US, application users are from Norway/Denmark/Sweden/UK/USA/India
The problem is we used DateTime.Now to store the record created/updated date, etc.
Since the Server runs in USA all user data are saved as US time :(
After researching in SO, we decided to stored all history dates in DB as DateTime.UtcNow
PROBLEM:
There is a record created on 29 Dec 2013, 3:15 P.M Swedish time.
public ActionResult Save(BookingViewModel model)
{
Booking booking = new Booking();
booking.BookingDateTime = model.BookingDateTime; //10 Jan 2014 2:00 P.M
booking.Name = model.Name;
booking.CurrentUserId = (User)Session["currentUser"].UserId;
//USA Server runs in Pacific Time Zone, UTC-08:00
booking.CreatedDateTime = DateTime.UtcNow; //29 Dec 2013, 6:15 A.M
BookingRepository.Save(booking);
return View("Index");
}
We want to show the same history time to the user who logged in in India/Sweden/USA.
As of now we are using current culture user logged in and choose the timezone from a config file and using for conversion with TimeZoneInfo class
<appSettings>
<add key="sv-se" value="W. Europe Standard Time" />
<add key="ta-IN" value="India Standard Time" />
</appSettings>
private DateTime ConvertUTCBasedOnCulture(DateTime utcTime)
{
//utcTime is 29 Dec 2013, 6:15 A.M
string TimezoneId =
System.Configuration.ConfigurationManager.AppSettings
[System.Threading.Thread.CurrentThread.CurrentCulture.Name];
// if the user changes culture from sv-se to ta-IN, different date is shown
TimeZoneInfo tZone = TimeZoneInfo.FindSystemTimeZoneById(TimezoneId);
return TimeZoneInfo.ConvertTimeFromUtc(utcTime, tZone);
}
public ActionResult ViewHistory()
{
List<Booking> bookings = new List<Booking>();
bookings=BookingRepository.GetBookingHistory();
List<BookingViewModel> viewModel = new List<BookingViewModel>();
foreach (Booking b in bookings)
{
BookingViewModel model = new BookingViewModel();
model.CreatedTime = ConvertUTCBasedOnCulture(b.CreatedDateTime);
viewModel.Add(model);
}
return View(viewModel);
}
View Code
#Model.CreatedTime.ToString("dd-MMM-yyyy - HH':'mm")
NOTE: The user can change the culture/language before they login. Its a localization based application, running in US server.
I have seen NODATIME, but I could not understand how it can help with multi culture web application hosted in different location.
Question
How can I show a same record creation date 29 Dec 2013, 3:15 P.M for the users logged in INDIA/USA/Anywhere`?
As of now my logic in ConvertUTCBasedOnCulture is based user logged in culture. This should be irrespective of culture, since user can login using any culture from India/USA
DATABASE COLUMN
CreatedTime: SMALLDATETIME
UPDATE: ATTEMPTED SOLUTION:
DATABASE COLUMN TYPE: DATETIMEOFFSET
UI
Finally I am sending the current user's local time using the below Momento.js code in each request
$.ajaxSetup({
beforeSend: function (jqXHR, settings) {
try {
//moment.format gives current user date like 2014-01-04T18:27:59+01:00
jqXHR.setRequestHeader('BrowserLocalTime', moment().format());
}
catch (e) {
}
}
});
APPLICATION
public static DateTimeOffset GetCurrentUserLocalTime()
{
try
{
return
DateTimeOffset.Parse(HttpContext.Current.Request.Headers["BrowserLocalTime"]);
}
catch
{
return DateTimeOffset.Now;
}
}
then called in
model.AddedDateTime = WebAppHelper.GetCurrentUserLocalTime();
In View
#Model.AddedDateTime.Value.LocalDateTime.ToString("dd-MMM-yyyy - HH':'mm")
In view it shows the local time to user, however I want to see like dd-MMM-yyyy CET/PST (2 hours ago).
This 2 hours ago should calculate from end user's local time. Exactly same as stack overflow question created/edited time with Timezone display and local user calculation.
Example: answered Jan 25 '13 at 17:49 CST (6 hours/days/month ago) So the other viewing from USA/INDIA user can really understand this record was created exactly 6 hours from INDIA/USA current time
Almost I think I achieved everything, except the display format & calculation. How can i do this?
It sounds like you need to store a DateTimeOffset instead of a DateTime. You could just store the local DateTime to the user creating the value, but that means you can't perform any ordering operations etc. You can't just use DateTime.UtcNow, as that won't store anything to indicate the local date/time of the user when the record was created.
Alternatively, you could store an instant in time along with the user's time zone - that's harder to achieve, but would give you more information as then you'd be able to say things like "What is the user's local time one hour later?"
The hosting of the server should be irrelevant - you should never use the server's time zone. However, you will need to know the appropriate UTC offset (or time zone) for the user. This cannot be done based on just the culture - you'll want to use Javascript on the user's machine to determine the UTC offset at the time you're interested in (not necessarily "now").
Once you've worked out how to store the value, retrieving it is simple - if you've already stored the UTC instant and an offset, you just apply that offset and you'll get back to the original user's local time. You haven't said how you're converting values to text, but it should just drop out simply - just format the value, and you should get the original local time.
If you decide to use Noda Time, you'd just use OffsetDateTime instead of DateTimeOffset.
Standard approach is to always store any time data as UTC if particular moment in time is important. That time is not impacted by time zone changes and cultures.
Most common approach to showing time with time zone is to store time as UTC and convert to current user's culture/time zone combination when you display the value. This approach only requires single date time filed in the storage.
Note that for Web cases (like ASP.Net) you may need to figure out user's culture/time zone first and send it to server (as this information is not necessary available on GET requests) or do formatting of time in the browser.
Depending what "show the same history time" you may need to store additional information like current culture and/or current offset. If you need to show time exactly as original user seen it you may also save string representation (because formats/translations can change later and value will look different, also it is unusual).
Note: culture and time zone are not tied together, so you'll need to decide how you need to handle cases like IN-IN culture in US PST time zone.
I'm a little confused by the phrasing of your question, but it appears that you would like to determine the time zone of your user.
Have you tried asking them? Many applications have the user pick their time zone in user settings.
You could pick from a drop-down list, or a pair of lists (country, then time zone within the country), or from a map-based time zone picker control.
You could take a guess and use that as the default unless your user changes it.
If you go down that route, you will need to be able to use IANA/Olson time zones, which is where Noda Time comes into play. You can access them from DateTimeZoneProviders.Tzdb.
The hosting location is irrelevant if you are using UTC. That's a good thing.
Also, if you're using Noda Time, then you probably should use SystemClock.Instance.Now instead of DateTime.UtcNow.
See also here and here.
Also - an alternative solution would be just to pass the UTC time to the browser and load it into a JavaScript Date object. The browser can convert that to the user's local time. You could also use a library like moment.js to make this easier.
Update
Regarding your approach of mapping culture codes to time zones:
<appSettings>
<add key="sv-se" value="W. Europe Standard Time" />
<add key="ta-IN" value="India Standard Time" />
</appSettings>
That will not work, for several reasons:
Many people use a different culture setting on their computer than the area that they are physically in. For example, I might be an a US-English speaker living in Germany, my culture code is likely still en-US, not de-DE.
A culture code containing a country is used to distinguish between dialects of a language. When you see es-MX, that means "Spanish, as spoken in Mexico". It does not mean that the user is actually in Mexico. It just means that user speaks that dialect of Spanish, as compared to es-ES which means "Spanish, as spoken in Spain".
Even if the country portion of the culture code could be reliable, there are many countries that have multiple time zones! For example, what would you put in your mapping list for en-US? You can't just assume that we are all on Eastern Standard Time.
Now, I've explained why your current approach won't work, I strongly suggest you take my original advice. Very simply:
Determine the time zone of the user, preferably by asking them, perhaps with some assistance by one of the utilities I linked to above.
You're storing UTC, so just convert to that time zone for display.
Using Microsoft Time Zones
TimeZoneInfo tz = TimeZoneInfo.FindSystemTimeZoneById("W. Europe Standard Time");
DateTime localDatetime = TimeZoneInfo.ConvertTimeFromUtc(yourUTCDateTime, tz);
Using IANA Time Zones and Noda Time
DateTimeZone tz = DateTimeZoneProviders.Tzdb["Europe/Stockholm"];
Instant theInstant = Instant.FromDateTimeUtc(yourUTCDateTime);
LocalDateTime localDateTime = theInstant.InZone(tz);
We faced a similar problem with an application I worked on recently. During development every one was in the same time zone and the issue wasn't noticed. And in any case there was a lot of legacy code that would have been a pain to change not to mention converting all the date time info that was already in the DB. So changing to DateTimeOffset was not an option. But we managed to get it all consistent by converting from server time to user time on the way out and converting from user time to server time on the way in. It was also important to do this with any date time comparisons that were a boundary. So if a user expected some thing to expire midnight their time then we would convert that time to server time and do all comparisons in server time. This sounds like a lot of work but was much less work then converting the entire application and DB to use DateTimeOffsets.
Hear is a thread that looks like has some good solutions to the time zone issue.
Determine a User's Timezone
If you want to show consistent date/time history to the user, regardless of the locale they are viewing the history from, then:
During Save, store not only UTC "creation" date/time, but also the detected locale
Use stored saved from locale to compute original date/time and emit a string to display (i.e. do not use current user locale when you're diplaying it)
If you don't have the ability to amend your storage, then perhaps you can change your submit to send the "current client time", store it literally (do not convert to UTC) and then display literally (do not convert to detected culture)
But as I say in my comment under your question, I am not certain I got your requirements right.
Hello!
I was confused in the problem of time zones. I am writing a web application that will contain some news with dates of publication, and I want the client to see the date of publication of the news in the form of corresponding local time. However, I do not know in which time zone the client is located.
I have three questions.
I have to ask just in case: does DateTimeOffset.UtcNow always returns the correct UTC date and time, regardless of whether the server is dependent on daylight savings time? For example, if the first time I get the value of this property for two minutes before daylight savings time (or before the transition from daylight saving time back) and the second time in 2 minutes after the transfer, whether the value of properties in all cases differ by only 4 minutes? Or here require any further logic? (Question #1)
Please see the following example and tell me what you think.
I posted the news on the site. I assume that DateTimeOffset.UtcNow takes into account the time zone of the server and the daylight savings time, and so I immediately get the correct UTC server time when pressing the button "Submit". I write this value to a MS SQL database in the field of type datetime2(0).
Then the user opens a page with news and no matter how long after publication. This may occur even after many years. I did not ask him to enter his time zone. Instead, I get the offset of his current local time from UTC using the javascript function following way:
function GetUserTimezoneOffset()
{
var offset = new Date().getTimezoneOffset();
return offset;
}
Next I make the calculation of the date and time of publication, which will show the user:
public static DateTime Get_Publication_Date_In_User_Local_DateTime(
DateTime Publication_Utc_Date_Time_From_DataBase,
int User_Time_Zone_Offset_Returned_by_Javascript)
{
int userTimezoneOffset = User_Time_Zone_Offset_Returned_by_Javascript; // For
// example Javascript returns a value equal to -300, which means the
// current user's time differs from UTC to 300 minutes. Ie offset
// is UTC +6. In this case, it may be the time zone UTC +5 which
// currently operates summer time or UTC +6 which currently operates the
// standard time.
// Right? (Question #2)
DateTimeOffset utcPublicationDateTime =
new DateTimeOffset(Publication_Utc_Date_Time_From_DataBase,
TimeSpan.Zero); // get an instance of type DateTimeOffset for the
// date and time of publication for further calculations
DateTimeOffset publication_DateTime_In_User_Local_DateTime =
utcPublicationDateTime.ToOffset(new TimeSpan(0, - userTimezoneOffset, 0));
return publication_DateTime_In_User_Local_DateTime.DateTime;// return to user
}
Is the value obtained correct? Is this the right approach to solving this problem? (Question #3)
UPDATED Oct 19 at 6:58 (I tried post it as a comment but it's too long by 668 characters)
Matt Johnson, Thank You for such a detailed answer despite that of the fact that you are doing this not the first time. Thank you for taking the time to explain this particular case, and not just provide links to other posts.
I have read the information that you have provided. Maybe I'm still not fully aware of all the details, but if I understand it right, for the right convertion of DateTime (which was written many years ago in the database) from UTC to the same user's moment, I need to know UTC offset which he had at that moment. And it is difficult taking into account that transfer rules for DST change constantly. And even now, though the platform ".NET" contains some TZDB that is used for the TimeZoneInfo type, I can't take advantage of it without the exact position of the user.
But what if I am only interested in the date and time of starting this year, and only in Russia, where DST was canceled in 2011? As I understand it, this means that if properly configured clock on user's computer, located in Russia, this approach will always give the correct result. And since 2011, the offset to UTC of user's clock should always be the same. Accordingly, the shift indicators in different browsers will not be different for the Russian user's.
Answer to Question 1
... does DateTimeOffset.UtcNow always returns the correct UTC date and time, regardless of whether the server is dependent on daylight savings time?
Yes. As long is your clock is set correctly, UtcNow always refers to the UTC time. The time zone settings of the server will not affect it. The value in your example will always be 4 minutes, regardless of DST.
Answer to Question 2
var offset = new Date().getTimezoneOffset();
Since new Date() returns the current date and time, this will return you the current offset. You then proceed to apply this current offset to some past value, which may or may not be the correct offset for that specific time. Please read the timezone tag wiki, especially the section titled "Time Zone != Offset".
Answer to Question 3
Is the value obtained correct? Is this the right approach to solving this problem?
No. This is not the correct approach. You have a few options:
First Option
Just pass the UTC value to JavaScript without modification.
Send it in ISO8601 format, such as 2013-10-18T12:34:56.000Z. You can get this in .Net easily using yourDateTime.ToString("o").
Be sure the DateTime you are starting with has .Kind == DateTimeKind.Utc, otherwise it won't get the Z on the end, which is essential.
If you are targeting older browsers that can't parse ISO8601, then you will need a library such as moment.js to parse it for you.
Alternatively, you could pass the number of milliseconds since 1/1/1970 UTC as a number and load that into a JavaScript Date instead of parsing.
Now you can just display the Date object using JavaScript. Let the browser convert it from UTC to the users local time.
Warning, with this approach, some conversions might be incorrect due to the problem I describe here.
Second Option
Like the first option, pass the UTC timestamp to JavaScript
Use that to get the offset for that timestamp.
Pass the offset back to the server in a postback or ajax call.
Apply the offset on the server
Output the local time zone
I don't particularly like this option because of the round trip. You might as well calculate it in JavaScript like the first option.
Third Option
Get the user's time zone. The best way is to ask them for it, usually on a user setting page.
Use it to convert from the UTC time to their local time completely on the server.
You can use Windows time zones and the TimeZoneInfo class to do the conversions.
Or you can use IANA/Olson time zones and the Noda Time library.
If you do this, you can optionally use a map-based timezone picker.
You can take a guess at the user's time zone with jsTimeZoneDetect.
This approach is more accurate, but requires more user interaction.
Also, please in future posts, ask just one question at a time. And please search before you post - I've written most of this in one form or another many times before.
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
If I store all my dates in SQL Server 2005 as GetUtcDate() what is the best way to search on these date fields. I'm using C# so should i convert the date submitted by the user to UTC using C# (passing to Stored Proc) to search my dates in SQL?
Also, since i'm using UTC do I need to worry about day light savings? When I want to display the date/time to the user/view do I simply just add/subtract the offset? Is there anything to look out for when converting my UTC date/time from the database to the user timezone for display?
Dealing with time zones is a major pain in the #$$. One thing to consider is that Windows only stores the current DST rules, not historic rules. So if you are relying on the rules to be able to accurately recreate the old values, you might find some discrepancies in your data. DST rules change all the time. Some countries don't even have set rules, they just announce the dates every year.
If you cannot afford discrepancies in your data, you might be better off storing the date as a string with the time zone information encoded in it. In .Net you can use DateTime.ToString("O"). This format is culture agnostic so you will always get the same format no matter what culture the code is running in.
var origDt = DateTime.Now;
var dtStr = origDt.ToString("O");
var newDt = DateTime.Parse(dtStr, null, System.Globalization.DateTimeStyles.RoundtripKind);
Console.WriteLine(dtStr);
if (newDt == origDt)
Console.WriteLine("Dates equal"); // should be true
else
Console.WriteLine("Dates not equal");
Check out the MSDN documentation for more information on this format style.
Of course this comes at a cost. It will be inefficient to search the database by date (it can be done, but the strings need to be converted to dates). Chances are the time zone differences won't matter too much anyway. It really depends on what you are doing with the data and how important accuracy is.
You might want to make sure that the project actually requires UTC and time zones before you go down this path. There is a decent chance that just storing the time from the local computer and ignoring time zones is good enough.
"should i convert the date submitted by the user to UTC using C# (passing to Stored Proc) to search my dates in SQL?" - Sounds like a good idea
"since i'm using UTC do I need to worry about day light savings?" - no, C# will take care of that when you're converting between local and UTC time.
Don't just add/subtract the offset, use the C# DateTime functions to convert between UTC and local time. That way it'll take care of DST.
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();