Get time zone with UTC conversion - c#

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.

Related

What timezone is the time part of the DateTime string along with an offset represents?

I have DateTime string as 2020-01-21T16:17:01.2202038-05:00, I would like to know 16:17:01.2202038 represents the local time or UTC time?
How can I preserve the local time in C#?
The offset is -05:00, which indicates that the date and time given (2020-01-21T16:17:01.2202038) are 5 hours behind UTC. In other words, it is the local time of some time zone that is UTC-5 at that point in time.
This is not necessarily the same as the local time of the computer where you are evaluating the code, nor is the offset guaranteed to be the same for other points in time for the same time zone.
In .NET, you're much better off representing such data with the DateTimeOffset type, rather than the DateTime type.
By the way, this format is defined as part of the ISO 8601 and RFC 3339 specifications.
A DateTime value does not have TZ offset data. It has a flag for “local” or “UTC” (or unspecified). See the DateTime.Kind property. Internally the actual value of the DateTime is an offset from UTC, stored independently of the Kind.
If a (non-0) TZ is displayed when a DateTime is converted to a string, the DateTime represents the local TZ offset and the TZ-local time.
This TZ offset is calculated on-the-fly depending on the actual DateTime value and current computer (really thread) settings. For example, it will change offsets “automatically” depending if the date is in Standard or Daylight time.* Since the calculation is done with limited data (ticks from UTC and a flag) the TZ is not necessarily “honest” across TZ shifts: the absolute time in UTC is correct, but the currently emitted TZ offset can change as it is computed on currently
active settings.
*Historical offsets can be inaccurate if these rules have changed multiple times, as implementations usually only store so much history.

C# How to convert UTC date time to Mexico date time

see my code which i used to convert Mexico date and time to UTC date and time.
string strDateTime = "25/01/2017 07:31:00 AM";
DateTime localDateTime = DateTime.Parse(strDateTime);
DateTime univDateTime = localDateTime.ToUniversalTime();
ToUniversalTime return UTC 25-01-2017 02:01:00
when again i try to convert the same UTC date and time UTC 25-01-2017 02:01:00 to Mexico local time then i got 24-01-2017 06:01:00
so see 07:31:00 AM becomes 06:01:00 which is not right. so tell me what is missing in my code for which i am getting wrong local time when i convert from utc to Mexico time using timezone info.
see my code which converting from utc to Mexico local time using timezone info.
string strDateTime = "25-01-2017 02:01:00";
DateTime utcDateTime = DateTime.Parse(strDateTime);
string nzTimeZoneKey = "Pacific Standard Time (Mexico)";
TimeZoneInfo nzTimeZone = TimeZoneInfo.FindSystemTimeZoneById(nzTimeZoneKey);
DateTime nzDateTime = TimeZoneInfo.ConvertTimeFromUtc(utcDateTime, nzTimeZone);
You current time zone (UTC+05:30) is different from the time zone you are converting into (UTC-8:00). So you get the difference. There is about 13 hours and 30 minutes difference from your original time zone to the targeted one. 5:30 - (-8) = 13:30.
Subtract 13 hours and 30 minutes from your original date, and then you get 18:01:00, which in 12-hour format is 6PM on the previous day.
Edit:
Instead of hard-coding Mexico time zone, you will need to have a method by which you can determine user's time zone no matter where they are coming from. This is best done using JavaScript as outlined in this answer.
Okay, I didn't know that you were located in India - which changes things a little bit:
You're going to want to utilize the TimeZoneInfo.ConvertTime() API for this one.. Maybe something like :
var dt = new DateTime(2017, 01, 25, 7, 31, 0).ToUniversalTime();
var nzTimeZone = TimeZoneInfo.FindSystemTimeZoneById("Pacific Standard Time (Mexico)");
//var ist = TimeZoneInfo.FindSystemTimeZoneById("India Standard Time");
DateTime nzDateTime = TimeZoneInfo.ConvertTime(dt, TimeZoneInfo.Utc, nzTimeZone);
Your problem is that the Parse is done without specifying the timezone it comes from - therefore the system will use whatever the default is of your computer. It appears that Your computer is NOT in PST. Rather somewhere in India.
Therefore after turning it into a DateTime object you need to convert it to UTC by specifying the PST timezone. There are a few ways to do this:
Specify the timezone offset as part of the string.
Call one of the TimeZoneInfo.ConvertTimeToUtc and specify the timezoneid
Maybe all you want to do is convert between two timezones by calling ConvertTime or ConvertTimeByTimeZoneId.
https://msdn.microsoft.com/en-us/library/bb382770(v=vs.110).aspx
https://msdn.microsoft.com/en-us/library/bb382058(v=vs.110).aspx
string pst = "Pacific Standard Time";
TimeZoneInfo.ConvertTimeBySystemTimeZoneId(currentTime, TimeZoneInfo.Local.Id, pst));
For example: 7:30AM PST should be 1:30 UTC - not 2:30. So that suggests a problem in the initial conversion. 2 AM UTC to PST is indeed 6 PM. Also I noticed your input was 7:31 and you claim it output 2:01 -- does Mexico do 30 minute timezones? I know India does.
I use Google to test conversions by literally searching for "2:01 UTC to PST" and it returns the answer for comparison.
See this other post which shows declaring the input timezone for Parsing. And as stated one does NOT need to convert for DST. Does ConvertTimeFromUtc() and ToUniversalTime() handle DST?
More info on MSDN for TimeZoneInfo: https://msdn.microsoft.com/en-us/library/bb495915(v=vs.110).aspx

What is the correct way to convert this to a date time in C#?

I have an asp.net-mvc site that is reading a string field from a sharepoint site and i get a string
var stringDate = "3/11/2016 12:05:00 AM"
I was told the time is in Eastern Standard Time. I try to convert to a date using:
var date = DateTime.Parse(stringDate);
and I think display it using this format:
<%= Model.Date.ToString("MMM dd HH:mm")
When I run this on a machine in the US, I get
Mar 14 00:05 (which is what i want to display)
but when i run the same code on a machine in London, I get:
Mar 14 05:05 (which is NOT what i want to display)
What is the right way to show the date in Eastern Standard Time regardless of where the server is hosted?
The question was changed after my first answer was provided so here's a different answer to the changed question.
The way to keep datetime straight globally is to always capture and persist datetime values in UTC and then translate to the context time zone for use/display.
In this case adding 5 hours to the provided, parsed value gives us UTC if Daylight Savings Time is ignored. Any variations in offset due to Daylight Savings Time must be taken account and the offset adjusted accordingly when determining UTC.
DateTime dtInUTC = DateTime.ParseExact("3/11/2016 12:05:00 AM", "M/d/yyyy hh:mm:ss tt",
CultureInfo.InvariantCulture).AddHours(5); // the source string is expressed in ET
Console.WriteLine(ToLocalTime(dtInUTC, "Eastern Standard Time")); // for ET
Console.WriteLine(ToLocalTime(dtInUTC, "GMT Standard Time")); // for GMT
This is what I use to convert timezone for context:
private static DateTime ToLocalTime(DateTime utcDateTime, string tzId) {
TimeZoneInfo tz = TimeZoneInfo.FindSystemTimeZoneById(tzId);
return TimeZoneInfo.ConvertTimeFromUtc(utcDateTime, tz);
}
Normally I'd keep the user time zone with a given user's profile, not hardcode it, but you get the idea.
Since you know it's in Eastern Time it's important to retain that truth in the parsed value. I'd append the -5 offset and parse the provided string. Once you parse it as ET explicitly the following
DateTime t = DateTime.ParseExact("3/11/2016 12:05:00 AM -05:00",
"M/d/yyyy hh:mm:ss tt zzz", CultureInfo.InvariantCulture);
Console.WriteLine(t.ToUniversalTime());
...results in this:
3/11/2016 5:05:00 AM
I suspect the "flexible" behavior you describe in your question is the result of the following value apparently being the default in the Parse method: AssumeLocal
Here is an excerpt of the relevant DateTime.ParseExact doc, here.
AssumeLocal: Specifies that if s lacks any time zone information, it is assumed to represent a local time. Unless the
DateTimeStyles.AdjustToUniversal flag is present, the Kind property of
the returned DateTime value is set to DateTimeKind.Local.
AssumeUniversal: Specifies that if s lacks any time zone information,
it is assumed to represent UTC. Unless the
DateTimeStyles.AdjustToUniversal flag is present, the method converts
the returned DateTime value from UTC to local time and sets its Kind
property to DateTimeKind.Local.
Daylight Savings Time is a problem, but not if you capture the current offset and append it appropriately in the parsing instead of just hardcoding -05:00.
The answer depends on how the time string was generated on the remote server. For example, if the string represents the local time on that remote server, then you can try to ParseExact() and ToUniversalTime() to get GMT (Greenwich Mean Time, aka UTC), then subtract 5 hours to get EST (this operation should be performed on the remote server):
DateTime _ny =
DateTime.ParseExact("3/11/2016 12:05:00 AM",
"mm/dd/yyyy HH:mm:ss UTC",
CultureInfo.InvariantCulture).ToUniversalTime().AddHours(-5);
Note: Time in NY City is EST (UTC-05:00, or GMT-05:00).
The solution could be further extended by using TimeZoneInfo class to calculate the offset (re: https://msdn.microsoft.com/en-us/library/system.timezoneinfo(v=vs.110).aspx). Pertinent to your question, US Eastern Standard Time ID is 720 (UTC-05:00) (re: https://msdn.microsoft.com/en-us/library/gg154758.aspx).
Also, be aware that if you read the data from remote server, then you have to adjust the solution pertinent to that server time zone. Once I was facing similar problem, caused by my real-time web app residing at remote Azure cloud server, so I used the similar solution (re: Listing 10, http://www.codeproject.com/Articles/884183/enRoute-Real-time-NY-City-Bus-Tracking-Web-App)
/// <summary>
/// Get the accurate NY Time value
/// </summary>
/// <returns>DateTime</returns>
protected DateTime GetTimeNYC()
{
try { return DateTime.Now.ToUniversalTime().AddHours(_offsetHour); }
catch { throw; }
}
Hope this may help.
Try it:
DateTime _dt = DateTime.ParseExact(dateString, "your format",CultureInfo.InvariantCulture);
I hope it help.
You should use DateTimeOffset for this as it has been built to deal with timezones properly.
Then you can do this:
var stringDate = "3/11/2016 12:05:00 AM";
var value =
DateTimeOffset
.ParseExact(
stringDate + "-05:00",
"M/dd/yyyy hh:mm:ss ttzzz",
System.Globalization.CultureInfo.GetCultureInfo("en-us"));
This will always parse your input in EST ("-05:00") time.
When I write the value to the console you get this:
2016/03/11 00:05:00 -05:00
It just knows about the time zone. There's no confusion here.

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");

Get eastern time in c# without converting local time

I know there are bunch of solutions on converting timezone to timezone, but what I'd like to know whether we can get eastern time without making conversion from our local time.
Well yes and no, if you represent using GMT always then you don't need to convert until you need to show locality.
Time is always in GMT and services should run under the GMT Timezone because of this reason among others.
Receiving and Storing a time in anything other than GMT / UTC requires conversions.
Please note the Timezone of the server should also be set to GMT for things to work as I indicated.
When you set things up like this it thus becomes much easier to reference and compare times and dates in different calendar date formats also.
This is the reason why DateTime offset made its way into the framework and sql server. if not careful when the Timezone on a server changes so does all stored and loaded dates in local format.
A date comparison is a date comparison. DateTime just wraps a memory structure which is defined in ticks and makes methods to access commonly used parts of the memory e.g. day or year or Time or TimeOfDay etc.
Furthermore conversion is only possible if you know both the source and destination offsets and then the calculation is always as given is given by -1 * (sourceOffset - destOffset)
Where the part in parenthesis represents the time zone difference.
Where the DateTime you want to convert is in UTC and called theDate
DateTime eastern = TimeZoneInfo
.ConvertTimeFromUtc(
theDate,
TimeZoneInfo.FindSystemTimeZoneById("Eastern Standard Time"))
If theDate has a Kind of Local this will throw, only accepting Kind values of Utc or Unspecified. Of course, moving from local to UTC is easy and we could even check and do this conversion when required, but since you say you want this conversion "without making conversion from our local time" I'm assuming you have your times in UTC and hence having the exception would be better as it would warn you that times that should be UTC are being treat as local and a bug could pop up elsewhere.
This will use Eastern Daylight Time when theDate is a time when EDT is in effect, as that is the normal rule for EST. To use EST even when it is the summer you can create your own TimeZoneInfo:
TimeZoneInfo
.ConvertTimeFromUtc(
theDate,
TimeZoneInfo.CreateCustomTimeZone(
"Eastern Standard Time No Daylight Savings",
new TimeSpan(-5, 0, 0),
"Eastern Standard Time No Daylight Savings",
"Eastern Standard Time No Daylight Savings"))

Categories