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

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

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.

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.

Is there a way to instantiate a datetime object in a timezone other than local?

I've been racking my brain all afternoon trying to figure this one out. Essentially, the problem itself seems simple. I'm given a date/time that is representative of a date and time in another time zone (not local). I want to convert this value to a UTC value to store in the database. However, all of the methods I find online seem to point to you either starting with UTC or starting with a local time zone. You can convert TO other time zones from these, but you can't start with anything other than those. As a result, it appears that I'll have to do some kind of convoluted offset math to do what I want. Here is an example of the problem:
var dateString = "8/20/2014 6:00:00 AM";
DateTime date1 = DateTime.Parse(dateString,
System.Globalization.CultureInfo.InvariantCulture);
var currentTimeZone = TimeZoneInfo.FindSystemTimeZoneById("Pacific Standard Time");
// Now the server is set to Central Standard Time, so any automated offset calculation that it runs will come from that point of view:
var utcDate = date1.ToUniversalTime; // This is wrong
// Similarly, if I try to reverse-calculate it, it doesn't work either
var convertedDate = TimeZoneInfo.ConvertTime(date1, currentTimeZone);
utcDate = convertedDate.ToUniversalTime; // This is also wrong
In essence, I want to somehow tell the system that the datetime object I'm currently working with is from that time zone other than local, so that I know the conversion will be correct. I know that I'll eventually need to figure Daylight Savings Time in there, but that is a problem for another day.
Would this method be of any use to you ?
The TimeZoneInfo.ConvertTime method converts a time from one time zone
to another.
Alternatively, you could use the ConvertTimeToUtc method to simply convert any date (specifying the source time zone) to UTC.
var dateString = "8/20/2014 6:00:00 AM";
DateTime date1 = DateTime.Parse(dateString,
System.Globalization.CultureInfo.InvariantCulture);
var currentTimeZone = TimeZoneInfo.FindSystemTimeZoneById("Pacific Standard Time");
var utcDate = TimeZoneInfo.ConvertTimeToUtc(date1, currentTimeZone);
The System.DateTime struct only has two bits for storing the "kind" information. That is why you can only have "local" or "universal" or "unknown" (or "magicl local").
Take a look at the System.DateTimeOffset struct. It is like a DateTime, but it also keeps the time zone (offset from (plus or minus) UTC).

Convert same time to different time zone

I am trying to convert times to different time zones, but not the way you're thinking. I need to convert a DateTime that is 9am EST to 9am CST on the UTC for example. The timezones are variable so just adding/subtracting hours doesn't seem correct way to do it with NodaTime
Fri, 21 Feb 2014 21:00:00 EST = 1393034400 Epoch Timestamp
convert to
Fri, 21 Feb 2014 21:00:00 CST = 1393030800 Epoch Timestamp
If I understand the question correctly, it sounds like you're trying to convert a date/time in one time zone to another one that has the same local time and a different time zone; that is, a different point in time.
You can do this with Noda Time by combining the LocalDateTime with the new zone. For example, given something like the following:
Instant now = SystemClock.Instance.Now;
DateTimeZone eastern = DateTimeZoneProviders.Tzdb["America/New_York"];
ZonedDateTime nowEastern = now.InZone(eastern);
nowEastern is the time now in the America/New_York time zone. If we print nowEastern directly to the console, we'll see something like 2014-02-22T05:18:50 America/New_York (-05).
As an aside, "EST" and "CST" aren't time zones: they're non-unique abbreviations for a particular offset within a time zone; America/New_York and America/Chicago are probably representative of what we think of as "Eastern" and "Central", though (or you could use something like UTC-05:00 if you really wanted EST even when daylight savings time was in effect).
Given a ZonedDateTime in any time zone, we can convert it to a ZonedDateTime with the same local time and a specified time zone as follows:
DateTimeZone central = DateTimeZoneProviders.Tzdb["America/Chicago"];
ZonedDateTime sameLocalTimeCentral = nowEastern.LocalDateTime.InZoneStrictly(central);
This gives us a ZonedDateTime with the same local time, but a different time zone. With the input above, the result would be 2014-02-22T05:18:50 America/Chicago (-06).
Note that I'm using InZoneStrictly. This will throw an exception if the local time is ambiguous or invalid (for example, during daylight savings transitions). If that's unacceptable, you could use InZoneLeniently, which picks the earliest valid ZonedDateTime on or after the given local time, or InZone, which allows you to specify your own rules in those cases.
On Msdn website you can find all you need.
Small example:
DateTime dateNow = DateTime.Now;
Console.WriteLine("The date and time are {0} UTC.",
TimeZoneInfo.ConvertTimeToUtc(dateNow));
Go to the link for more details on what you want, I can't give you more with that small description

Using TimeZoneInfo to convert between UTC/Specified TimeZone not working

All of our date/time data in our database is stored in UTC time. I'm trying to write a function to convert that UTC time into the user's preferred time zone (they can select their timezone in their profile so it has NOTHING to do with local settings on their computer and everything to do with which timezone they have selected from a dropdown of available choices.
This function is in the context of a DevExpress AspxGridView event (the third party control is not relevant to the question but I thought I'd mention it):
DateTimeOffset utcTime = (DateTimeOffset)e.Value;
TimeZoneInfo destTimeZone = Helper.GetTimeZoneInfo();
DateTime modifiedDate = TimeZoneInfo
.ConvertTimeFromUtc(utcTime.DateTime, destTimeZone);
e.DisplayText = String.Format("{0} {1}",
modifiedDate.ToString("g"),
destTimeZone.Abbreviation());
Helper.GetTimeZoneInfo() simply returns a TimeZoneInfo class that corresponds to the one the user selected, or defaults to "Pacific Standard Time" if they have not chosen one.
This generally works fine until I switch my system clock (which this server is running on) from today (which is Oct. 14, a DST date) to something like January 11, which is NOT DST.
The time seems to always be displayed in DST (i.e. always a 7 hour offset). No matter what I do with my system clock, I can't get the time to adjust for the extra hour.
For example, when I have my timezone set to Pacific Standard Time, for UTC time 10-10-2011 20:00:00, it is always displaying this time:
10-10-2011 13:00:00 (the DST time, offset of -7).
During non-Daylight Savings dates (standard), the time should be:
10-10-2011 12:00:00 (offset of -8).
What am I missing?
The converted local time of a UTC time is always based on the time zone info for that UTC time... not for whatever the current time happens to be.
That is, the PST offset on Oct 10, 2011 UTC is always -7. It doesn't matter what date you are doing the conversion on.
...Or am I misunderstanding what you are asking?
You might have a look at the e.Value.
Is the DateTimeKind for it set to DateTimeKind.Utc or is it DateTimeKind.Unspecified
If it is Unspecified, the conversion will not work correctly.
One cannot set the Kind directly. The best I have come up with is something along the lines of
// the value off the DB, but Kind is unspecified
var fromDb = new DateTime(1999,31,12)
// convert it to a Utc version of the same date
var fromDbInUtc = new DateTime(fromDb.Ticks, DateTimeKind.Utc)
var destTimeZone = Helper.GetTimeZoneInfo();
var local = TimeZoneInfo.ConvertFromUtc(fromDbInUtc, destTimeZone);
Hope this helps,
Alan.

Categories