.NET Get timezone offset by timezone name - c#

In database I store all date/times in UTC.
I know user's timezone name ("US Eastern Standard Time" for example).
In order to display correct time I was thinking that I need to add user's timezone offset to UTC date/time. But how would I get timezone offset by timezone name?
Thank You!

You can use TimeZoneInfo.FindSystemTimeZoneById to get the TimeZoneInfo object using the supplied Id, then TimeZoneInfo.GetUtcOffset from that:
TimeZoneInfo tzi = TimeZoneInfo.FindSystemTimeZoneById("US Eastern Standard Time");
TimeSpan offset = tzi.GetUtcOffset( myDateTime);

You can use the TimeZoneInfo class's GetSystemTimeZones() method to fetch the list of all timezones configured on your server and match it to the one from your client.
Though why do you have timezones in the format "US Eastern Standard Time"? Where did that come from?

Rather than doing some manual addition you should take advantage of the ConvertTime method of TimeZoneInfo which will handle converting your date based on the TimeZone you specify.
var localizedDateTime = TimeZoneInfo.ConvertTime(yourDateTime, localTimeZoneInfo);

Related

Get time zone with UTC conversion

I have the system date in BST . I want to convert it to UTC. So did the below:
string utcDate= TimeZoneInfo.ConvertTimeToUtc(dt).ToString("dd/MM/yyyy HH:mm:ss");
What I want is to get the zone along with the Date in UTC. Pls consider the daylight savings.
Example: 2019-07-08T23:59:00+01:00.
A few things:
The string format you gave the example of, 2019-07-08T23:59:00+01:00 is part of the ISO 8601 specification. To be precise, it is the "complete date and time of day representation" of the "ISO 8601 Extended Format". It also the format defined by RFC 3339.
In this format, the date and time portion represent the local time, as denoted by the time zone offset portion. In other words, the values are not in UTC, but already adjusted. In your example, 2019-07-08T23:59:00 is the local time and UTC+01:00 is in effect at that time. The corresponding UTC time would thus be an hour earlier, 2019-07-08T22:59:00Z.
You seem to be asking for the date in UTC but with an offset that includes daylight saving time. That is impossible, as UTC does not observe daylight saving time. The offset from UTC is always zero. You can read more about UTC here.
The offset of UTC itself is denoted with Z, but can also be represented with +00:00, which can be thought of as "zero offset from UTC". In other words, if you are referring to UTC time use the Z, and if you are referring to a local time that is aligned to UTC (such as GMT in London in the winter, or Iceland, etc.) use +00:00.
In your question, you say you want the system time in UTC with the offset. I will assume by "system time" you mean the current time of the clock on the system. That is provided by DateTime.UtcNow or DateTimeOffset.UtcNow. These return either a DateTime or DateTimeOffset structure - not a string. Since you wanted a string in a specific format, then you should first ask for the current time, and then format it as a string with ToString:
using System.Globalization;
...
string a = DateTime.UtcNow.ToString("yyyy-MM-dd'T'HH:mm:ssK", CultureInfo.InvariantCulture);
// output example: "2019-07-08T22:59:00Z"
string b = DateTimeOffset.UtcNow.ToString("yyyy-MM-dd'T'HH:mm:sszzz", CultureInfo.InvariantCulture);
// output example: "2019-07-08T22:59:00+00:00"
If what you actually wanted was the local time, such that the offset would be +00:00 in the winter and +01:00 in the summer (in the UK), then use Now instead of UtcNow. This gives the local time in the time zone of the computer where the code is running.
string c = DateTime.Now.ToString("yyyy-MM-dd'T'HH:mm:ssK", CultureInfo.InvariantCulture);
// output example: "2019-07-08T23:59:00+01:00"
string d = DateTimeOffset.Now.ToString("yyyy-MM-dd'T'HH:mm:sszzz", CultureInfo.InvariantCulture);
// output example: "2019-07-08T23:59:00+01:00"
If you actually wanted the time in the UK regardless of what the time zone of the local computer was on, then you'd have to first get the UTC time and then convert it to UK time before creating the string.
TimeZoneInfo tzi = TimeZoneInfo.FindSystemTimeZoneById("GMT Standard Time");
string e = TimeZoneInfo.ConvertTime(DateTime.UtcNow, tzi).ToString("yyyy-MM-dd'T'HH:mm:ssK", CultureInfo.InvariantCulture);
// output example: "2019-07-08T23:59:00"
string f = TimeZoneInfo.ConvertTime(DateTimeOffset.UtcNow, tzi).ToString("yyyy-MM-dd'T'HH:mm:sszzz", CultureInfo.InvariantCulture);
// output example: "2019-07-08T23:59:00+01:00"
In example e, note that a DateTime can't store an arbitrary offset as the result of time zone conversion, and thus you get DateTimeKind.Unspecified assigned to the Kind property, which results in no offset being in the string representation. Thus most of the time you should use a DateTimeOffset (example f) instead.
Also, note the time zone ID of "GMT Standard Time" is the correct ID to use for the UK on Windows platforms. It correctly switches between GMT and BST when appropriate. If you are running .NET Core on non-Windows platforms (Linux, OSX, etc.), then you should use "Europe/London" instead. Or if you are wanting to write code that is platform-neutral then you can use my TimeZoneConverter library, which allows you to provide either form and run on any platform.
In your code example, you didn't call any of the "now" functions, but gave a dt variable. Assuming this is a DateTime, the result of calling TimeZoneInfo.ConvertTimeToUtc will depend on the Kind property of that variable. If it's DateTimeKind.Utc, then no conversion is performed. If it's DateTimeKind.Local or DateTimeKind.Unspecified, then the value is converted from the computer's local time zone to UTC.
Lastly, keep in mind that when talking to an international audience, time zone abbreviations can be ambiguous. I could deduce by "BST" that you meant British Summer Time, but only because you showed a +01:00 offset in your question. "BST" can also stand for "Bangladesh Standard Time" (+06:00), or "Bougainville Standard Time" (+11:00).
I guess you can do something like this:
var dt = DateTime.Now;
string utcDate = dt.ToUniversalTime().ToString("dd/MM/yyyy HH:mm:ss") +
dt.ToString(" zzz");
Output: (I'm in EET)
14/07/2019 20:02:17 +02:00
But be aware that this could be confusing to people. The standard way is that the timezone follows the local date, not the universal date.

How to use Standard Time Only in TimezoneInfo.ConvertTime C#

I am having a Issue with the C# function of TimeZoneInfo.ConvertTime().
What i need to get is the Standard Time not the DST but i'm only getting DST is there a way to Tell the Function to only get the Result in Standard Time.
My local Timezone is UTC -6:00 Central America Standard Time, so if my time is 12:00 PM the Conversion i'm getting is throwing it at 2 PM Eastern Time but i need it to tell me it's 1:00 PM.
public static DateTime TimetoEst( DateTime timenow)
{
var currentTimeZone = TimeZone.CurrentTimeZone.GetUtcOffset(timenow).ToString();
var estzone = TimeZoneInfo.FindSystemTimeZoneById("Eastern Standard Time");
var conver = TimeZoneInfo.ConvertTime(timenow, estzone);
return conver;
}
Thanks
A couple of things:
The ID "Eastern Standard Time" represents both EST and EDT, with the appropriate transitions in place. It would more appropriately be called "Eastern Time", but alas this is the identifier and the convention used by Windows time zones.
The Eastern Time zone really does transition in and out of daylight saving time. If you were to always adjust to just Eastern Standard Time (UTC-5), you would be ignoring the reality of timekeeping in that region - that it is in Eastern Daylight Time (UTC-4) for dates in the summer months.
Your code will indeed return EST, but only for date values that are outside of the DST period.
Now, if you still think this is what you want to do - then you can do it without the TimeZoneInfo object at all. Simply adjust the result from the offset that applies to your source value, to the UTC-5 offset that applies to EST.
public static DateTime TimetoEst(DateTime timenow)
{
var dto = new DateTimeOffset(timenow); // will use .Kind to decide the offset
var converted = dto.ToOffset(TimeSpan.FromHours(-5));
return converted.DateTime;
}
This is what you asked, but for the record - I don't think this is the best plan. Besides the issues above - assuming that the input value should be interpreted based on the local time zone is not necessarily a good idea - and unless the input time has a .Kind of DateTimeKind.Utc, it will indeed use the computer's local time zone.
You did label the variable as timenow. If you are just after a DateTime which represents the current time in a fixed offset, then it's much safer just to get it like so:
DateTime dt = DateTimeOffset.UtcNow.ToOffset(TimeSpan.FromHours(-5)).DateTime;
And if you really want the current time in the Eastern Time zone, taking DST into account when appropriate, then:
DateTime dt = TimeZoneInfo.ConvertTimeBySystemTimeZoneId(DateTime.UtcNow,
"Eastern Standard Time");

Converting a DateTime to Utc given a timezone

I don't want to keep having to change the config everytime there is a daylight savings change. This is what I am currently doing which doesn't work as it uses "Standard" time.
TimeZoneInfo timeZone = TimeZoneInfo.FindSystemTimeZoneById("US Eastern Standard Time")
TimeZoneInfo.ConvertTimeToUtc(dateTime, timeZone); // This doesn't take into account that it's daylight savings...
Is there a one size fits all solution. So I can give it a datetime and a location like "US east coast" and it give me the time in Utc?
I've done it before by storing the timezone id in the database using a mapping table. i.e. A table containing the results of TimeZone.GetSystemTimeZones()
You don't actually need to use TimeZoneInfo.FindSystemTimeZoneById() though: you can do the conversion using one of the overloads of TimeZoneInfo.ConvertTimeBySystemTimeZoneId(). This method has some overloads which take DateTime values, and some that take DateTimeOffset values (which are preferable as they specify an unambiguous point in time).
e.g.
TimeZoneInfo.ConvertTimeBySystemTimeZoneId(DateTime.Now, "New Zealand Standard Time", "UTC")
The real benefit of using the system time zone id rather than an offset stored in the database is that daylight savings time is automatically handled for you by TimeZoneInfo.ConvertTimeBySystemTimeZoneId.
This msdn also might prove helpful to you>
http://msdn.microsoft.com/en-us/library/bb382058.aspx
You Can Pass DateTime and TimeZone of the Location and Convert the provided DateTime to UTC
Check this Example Here
string DisplayName = "custom standard name here";//custom Standard Name to display eg: Kathmandu
string StandardName = "custom standard name here"; // custom Standard Name eg: Asia/Kathamandu, Nepal
string YourDate="27-03-2019 20:24:56"; // this DateTime doesn't contain any timeZone
TimeSpan Offset = new TimeSpan(+5, 30, 00);// your TimeZone offset eg: timeZone of Nepal is +5:45
TimeZoneInfo TimeZone = TimeZoneInfo.CreateCustomTimeZone(StandardName, Offset, DisplayName, StandardName);
var RawDateTime = DateTime.SpecifyKind(DateTime.Parse(YourDate), DateTimeKind.Unspecified);// I all it RawDateTime Since it doesn't contain any TimeSpan
DateTime UTCDateTime = TimeZoneInfo.ConvertTimeToUtc(RawDateTime, TimeZone);
Console.WriteLine(UTCDateTime);

Get date/time for specific region?

How do I get DateTime.Now for specific region?
I'm trying to get the current date in a foreign country, I'm looking for an easy way to achieve this.
Note: I don't mind getting the value from an online server, I just don't want to spend too much dev-time for it.
If you know the timezone you want, you can use the TimeZoneInfo class. First get the TimeZoneInfo object for your desired timezone, then convert current time to that timezone:
var timezone = TimeZoneInfo.FindSystemTimeZoneById("Central America Standard Time");
var dateTime = TimeZoneInfo.ConvertTime(DateTime.Now, timezone);

Apply DateTime offset to US Eastern Timezone

I have a page that generates vCal and iCal files to import events into Outlook and iCal. These mail clients (Outlook & iCal) will take in the dates in UTC since they know the user's offset and will handle putting in the right times. Our client for which we're writing this code is based out of the USA Eastern time zone and so am I. Their host is in the Central time zone (1 hour behind Eastern). I'd like to make the code handle this without any hard-coded offsets. My code currently get's the DateTime from our CMS and converts to UTC for Outlook/iCal. That means the DateTime value from the CMS is relative to the hosting location:
// Start Date Time
sb.AppendFormat("DTSTART:{0}\n", thisEvent.StartDate.ToUniversalTime().ToString("yyyyMMddTHHmmssZ"));
When I run this on my local, it's all fine, because the DateTime in the CMS is based on our client's Eastern time zone and so am I, so the process is Eastern -> UTC -> into Outlook which then goes UTC -> Eastern, and everything is good. When I deploy to the server in Central, the DateTime from the CMS is an hour off from Eastern. How can I automatically get the offset from Eastern and add it in before I convert to UTC? I obviously need this to handle both standard time (EST) and daylight time (EDT). I'd like to do it programatically without hard-coded values so it always works correctly no matter what time zone you're in. I.e. if I deliver this code to someone for development in India, it should automatically handle their local server's offset and adjust accordingly.
I need to do something like this where I apply an offset to Eastern time before converting to UTC:
sb.AppendFormat("DTSTART:{0}\n", thisEvent.StartDate.ApplyEasternOffset().ToUniversalTime().ToString("yyyyMMddTHHmmssZ"));
Sorry if this is a topic that's been discussed before, I'm just not sure of the best terms to find a question like this. Thanks in advance.
Check out the TimeZoneInfo class. It has methods to get UTC offsets for any timezone.
http://msdn.microsoft.com/en-us/library/system.timezoneinfo.aspx
Also, check out this previous post: How to use TimeZoneInfo to get local time during Daylight Savings Time?
Here's an example showing a conversion from Pacfic to Eastern:
var eastern = TimeZoneInfo.FindSystemTimeZoneById("Eastern Standard Time");
var local = TimeZoneInfo.Local; // PDT for me
Console.WriteLine(DateTime.Now.Add(eastern.BaseUtcOffset - local.BaseUtcOffset));
Shows 4/4/2011 12:05:31 when my local clock shows 9:05:31.
You can use TimeZoneInfo Class.
Take a look at this sample:
TimeZoneInfo tzi = TimeZoneInfo.FindSystemTimeZoneById("US Eastern Standard Time");
TimeSpan offset = tzi.GetUtcOffset(DateTime.Now);
DateTime testDateTime = DateTime.Now.Add(offset);

Categories