Correct approach to getting the universal time zone - c#

In my project I want to get the universal time zone. I used two different kinds of approaches but I don't know which one is the best practice.
First approach is
public static DateTime GetUniversalTime(DateTime localDateTime)
{
TimeZone zone = TimeZone.CurrentTimeZone;
DateTime universal = zone.ToUniversalTime(localDateTime);
return universal;
}
then I want revert to local time I used the below method:
public static DateTime GetLocalTime(DateTime universalDateTime)
{
TimeZone zone = TimeZone.CurrentTimeZone;
DateTime local = zone.ToLocalTime(universalDateTime);
return local;
}
and second approach is get universal time zone DateTime.UtcNow;
then I want to revert to local time I used the above GetLocalTime method.
Can one explain what is the different between the above two approaches?
Which one is the best practice ?

Since you are asking about best practices:
Do not use the TimeZone class. If you need time zone conversions, use the TimeZoneInfo class instead. This is very clear in the MSDN documentation:
Whenever possible, avoid any use of "local" time. It is local to the system where the code is running. In the vast majority of real-world use cases, it is likely that it is not the local time zone of your user. This is especially true in a web application.
That means you should not be calling any of the following:
DateTime.Now
TimeZone.CurrentTimeZone
TimeZoneInfo.Local
DateTime.ToLocalTime()
DateTime.ToUniversalTime()
Any other method that involves the server's local time zone.
Instead, your application should allow the user to select a time zone, then you can convert to and from the local time in that zone using the TimeZoneInfo.Convert... methods.
If you need the current universal time, use DateTime.UtcNow or DateTimeOffset.UtcNow.
If you need the current local time zone of your server, ONLY use DateTimeOffset.Now.
If you need the current local time in a known time zone, such as US Eastern Time:
DateTime easternNow = TimeZoneInfo.ConvertTimeBySystemTimeZoneId(
DateTime.UtcNow, "Eastern Standard Time");
If you want to convert between a known time zone and UTC, then use the TimeZoneInfo.ConvertTimeToUtc and TimeZoneInfo.ConvertTimeFromUtc methods, and be sure to pass in the time zone you are converting to/from:
// get the local time zone of your user, not of the server!
TimeZoneInfo tzi = TimeZoneInfo.FindSystemTimeZoneById("Eastern Standard Time");
// use this to convert from UTC to local
DateTime local = TimeZoneInfo.ConvertTimeFromUtc(yourUtcDateTime, tzi);
// use this to convert from local to UTC
DateTime utc = TimeZoneInfo.ConvertTimeToUtc(yourLocalDateTime, tzi);
Be aware that when you convert from local to UTC, you might encounter ambiguities during daylight saving time transitions. Read more in the DST tag wiki.
Additional reading: The Case Against DateTime.Now

For Universal Time.
DateTime.Now.ToUniversalTime()
For Local Time
DateTime.UtcNow.ToLocalTime()
Universal To Local
var nowUtc = DateTime.Now.ToUniversalTime();
var nowLocal = nowUtc.ToLocalTime();

Related

Check a date (datetime) if it is Daylight Saving Time with unknown region - c#

With what I understood from other questions I've used below code for checking a date if it is Daylight saving time and altering as required. I do not know which region would the application be used hence I am using Utc. However it is not working as expected.
DateTime dateValWithOffset = dateVal;
TimeZoneInfo timeZoneInfo = TimeZoneInfo.Utc;
if(timeZoneInfo.IsDaylightSavingTime(dateValWithOffset))
{
dateValWithOffset = dateValWithOffset.AddMinutes(60);
}
Example: for sample date (06-JUL-21 06.16.34.547000000 AM) above code should be showing dateValWithOffset as 07/06/2021 02:16:34.547 AM but it returns 07/06/2021 01:16:34.547 AM . If someone can point out where am I going wrong please.
Datetime values should always be in UTC. To format a datetime in the machine or user's local timezone, you should convert to a DateTimeOffset. Knowing the local time and knowing if that time is in daylight saving time are two different things.
// machine local
var timeZoneInfo = TimeZoneInfo.Local;
// or by name
var timeZoneInfo = TimeZoneInfo.FindSystemTimeZoneById(name);
var localTime = new DateTimeOffset(dateVal, timeZoneInfo.GetUtcOffset(dateVal));
var isDst = timeZoneInfo.IsDaylightSavingTime(localTime)
IMHO DateTime is a terrible type, designed before the age of cloud computing. All DateTimeKind values other than Utc encourage programmers to continue to handle dates incorrectly and should be deprecated.
As jason.kaisersmith said in comments, "UTC is universal, so there is no daylight saving."
To elaborate, UTC does not have any daylight saving time. Instead, daylight saving time is observed differently at each time zone across the world. Some time zones don't use it at all. Some time zones start and stop DST at different dates or times than other time zones. There's even one time zone that shifts for DST by 30 minutes instead of the usual 1 hour. Without a time zone reference, the concept of DST is meaningless.
For clarity and reference, here's an overview of anticipated DST dates for 2022 by country, and a detailed list of dates and times for the first half and second half of 2022.

How ParseExact know my local TimeZone?

I use this code to convert my UTC string Time with format "yyyy-MM-ddTHH:mm:ssZ" to date time . for example :
string PurchaseDate == "2017-12-12T14:29:26Z";
datetime dt = DateTime.ParseExact(PurchaseDate , "yyyy-MM-ddTHH:mm:ssZ", null);
i know that PurchaseDate time is UTC time (because of "Z"). dt return {12/12/2017 5:59:26 PM} that it is my local Time(client time zone). in other word DateTime.ParseExact convert PurchaseDate to my client time zone! my question is how this method know my client TimeZone ? is it recommend to use this for global application and show user time zone at all ??
Update My question:
sometime for implement timezone management in my global website i google it for possible souloution and I find this Use ful link :
How to display dates and times in clients timezone
after month i found we can use TimeZoneInfo.Local for finding cliend TimeZone !
so should i say that link is useless? I want to know if there is a simple way to find client time zone in dotNet BackEnd code so why this complex way is Used ??
... how this method know my client TimeZone?
It doesn't understand anything about a "client". It just has the local time of wherever the code is running. If the code is running on a user's desktop computer or mobile device, then it's the time zone of that device.
If the code is running on a server, then it uses the time zone of the server. You should avoid this in general, as the server's time zone is usually irrelevant to your application or users. This applies to TimeZoneInfo.Local as well.
If you want to parse your string as UTC DateTime, then you'll need to pass an argument that tells the parser not to convert to local time:
string PurchaseDate = "2017-12-12T14:29:26Z";
DateTime dt = DateTime.ParseExact(PurchaseDate, "yyyy-MM-ddTHH:mm:ssK",
CultureInfo.InvariantCulture, DateTimeStyles.RoundtripKind);
TimeZoneInfo tz = TimeZoneInfo.FindSystemTimeZoneById("...you'll need to decide...");
DateTime clientDateTime = TimeZoneInfo.ConvertTimeFromUtc(dt, tz);
In the above, I use DateTimeStyles.RoundtripKind, which says to evaluate the string for it's offset (Z in this case) and decide whether to use Utc, Local, or Unspecified kind on the resulting DateTime. Also note that you should use K in the format string, not Z.
A better approach would be to use DateTimeOffset instead of DateTime, in which case the Z will automatically set an offset of +00:00.
You'll still need to figure out what time zone to convert to, regardless of which approach you take. If you happen to be writing code that runs on the user's device, then you get the benefit of having TimeZoneInfo.Local predetermined for you. Otherwise you do not.

What would be the simplest string value to set DateTime

I am trying to figure out the best way of letting the users set the internal DateTime value of the Portable Class Library based on some string parameter they provide. The string parameter has to be a simple format.
So, now I have some considerations.
Is specifying UTC Offset enough for getting the right DateTime
public static DateTime FromUtcOffset(string value)
{
var utcDateTime = DateTime.UtcNow;
var offSet = TimeSpan.Parse(value);
return utcDateTime + offSet;
}
Or is specifying the TimeZone has some advantage over UTC Offset
TimeZoneInfo someTimeZone = TimeZoneInfo.FindSystemTimeZoneById("Pacific Standard Time");
DateTime convertTimeFromUtc = TimeZoneInfo.ConvertTimeFromUtc(utcDateTime, someTimeZone);
My question is: What would be the right string parameter that can be taken from the user to let him decide what the value of DateTime would be?
Utc Offset
TimeZone
Or any other alternative that's less verbose.
Actually, it depends:
Do you work with network hosts, located in different time zones
Do you store time values for using them in future
Does your library work locally (hence, knows user's timezone)
1+2 basically mean if your time offset might change. If it not (the library is intended for local use only), get local time and don't care about the time offset. However, if the offset might change, usually storing "absolute" time in UTC format should be enough. To do this, you can:
Ask user for UTC time, not their local time
or
Ask for local time + offset (or get the offset from the local time zone, if possible)
Convert it to UTC time and store/process in UTC time
Provide output using local time (using the offset from 1. if it didn't change)
In 1 and 3 you will need a timezone to figure out the time offset. You don't need to know timezone if you already know the offset. Moreover, DateTime itself can store time offset information. It also can tell you if it stores local or UTC time (see DateTime.Kind Property).

Metro Apps TimeZoneInfo alternative

I would like to make a simple calculation but not sure how to approach this using c# for metro apps since TimeZoneInfo does not have most of the functionality it used to for other type of applications not metro.
How can I convert my current machine time to UTC time? It is probably something simple that was now made complicated and I do not understand.
Was trying to use
TimeZoneInfo time = TimeZoneInfo.FindSystemTimeZoneById("Central Standard Time");
Which is where the server is, and then trying to convert my machine time to that, but no luck since I do not have that functionality. I checked out those WINRT something libraries, but I do not really like those. Is there an easier way? (keep in mind the current machine time could be in Australia, Europe, United States.
Maybe I can get the offset of utc from local (but how to I get the time in central?) and then the utc offset of central. I am not sure it is confusing.
You can get the local timezone with TimeZoneInfo.Local . What you can't get is arbitrary other timezones: only local and Utc.
TimeZoneInfo.BaseUtcOffset will give the time difference between the current time zone and UTC.
TimeZoneInfo local = TimeZoneInfo.Local;
TimeZoneInfo utc = TimeZoneInfo.Utc;
Debug.WriteLine("Local TimeZone is {0} offset from UTC:{2}", local,utc,local.BaseUtcOffset);
DateTime localTime = DateTime.Now;
DateTime utcTime = DateTime.UtcNow;
Debug.WriteLine("It is now {0} (UTC: {1})", localTime, utcTime);
Results:
Local TimeZone is (UTC-08:00) Pacific Time (US & Canada) offset from UTC:-08:00:00
It is now 10/09/2014 14:59:07 (UTC: 10/09/2014 21:59:07)

Does ConvertTimeFromUtc() and ToUniversalTime() handle DST?

If daylight saving time is in effect, and a date object has been saved into the database (UTC format) which you retrieve to show it in the view (for example the view in asp.net-mvc).
And you do that by using this method:
public static DateTime ConvertToLocalTimeFromUtcTime(DateTime utcDate, string timeZoneId)
{
TimeZoneInfo localZone = TimeZoneInfo.FindSystemTimeZoneById(timeZoneId);
DateTime localTime = TimeZoneInfo.ConvertTimeFromUtc(utcDate, localZone);
if (localZone.IsDaylightSavingTime(localTime))
localTime = localTime.AddHours(1); // is this needed !?
return localTime;
}
The question is, does TimeZoneInfo.ConvertTimeFromUtc() handle DST's or do you have to check that yourself and either add or subtract X hour(s) to the date object?
Same question for when persisting a date object to the database by converting it to UTC format with ToUniversalTime().
Yes. ConvertTimeFromUtc will automatically handle daylight saving time adjustments, as long as the time zone that you are targeting uses daylight saving time.
From the MSDN documentation:
When performing the conversion, the ConvertTimeFromUtc method applies any adjustment rules in effect in the destinationTimeZone time zone.
You should not try to add an additional hour in your conversion. That will give you an incorrect translation.
Regarding DateTime.ToUniversalTime, it does take DST into account, but be careful with this method. It assumes that the input value is in the computer's local time zone. If you just need to mark it with DateTimeKind.Utc, then use DateTime.SpecifyKind instead.

Categories

Resources