I am trying to calculate the time from UTC to a specific timezone. I am using ConvertTimeFromUtc method for this by passing it the specified UTC time and the TimeZoneInfo of the specified timezone display name. This works for multiple timezones however for -7 it is calculating 0 using the following (simplified) parameters:
TimeZoneInfo timeZoneInfo = TimeZoneInfo.FindSystemTimeZoneById("US Mountain Standard Time");
TimeZoneInfo.ConvertTimeFromUtc(DateTime.Parse("01/01/0001 05:02:00"), timeZoneInfo)
However after doing the calculation, it comes out as {01/01/0001 00:00:00} which is strange as it works for other timezones such as Minsk etc
Am I missing something?
hum you have UTC-7 so from 01/01/0001 05:02:00 you are in 31/12/0000 22:02:00
(or 12/31/0000 following the US Format)
TimeZoneInfo.ConvertTimeFromUtc(DateTime.Parse("01/01/0001 05:02:00"), timeZoneInfo);
and msdn says:
The DateTime value type represents dates and times with values ranging from 00:00:00 (midnight), January 1, 0001 Anno Domini (Common Era) through 11:59:59 P.M., December 31, 9999 A.D. (C.E.) in the Gregorian calendar.
so 01/01/0001 00:00:00 is the first date available..
you have not missing anything, its just a limit of DateTime
sorry for my english
Related
This seems like a simple problem, but looks to be harder than it seems:
How do I convert Midnight of a specified timezone and convert it to Utc time (regardless of the timezone of the local computer)?
One example: Today Midnight CET is 11pm (the date before) in UTC.
I tried the following:
DateTime midnight = TimeZoneInfo.ConvertTime(DateTime.UtcNow, specifiedTimeZoneInfo).Date;
DateTime utcTime = midnight.ToUniversalTime();
The problem is that this code only works if the timezone of the local computer running the code is the same timezone as used in the TimeZoneInfo.ConvertTime.
How can one do this regardless of the timezone of the local computer?
Consider the following code:
var cestZone = TimeZoneInfo.FindSystemTimeZoneById("Central European Standard Time");
var cestNow = TimeZoneInfo.ConvertTimeFromUtc(DateTime.UtcNow, cestZone);
var cestMidnight = cestNow.Date;
var cestMidnightInUTC = TimeZoneInfo.ConvertTimeToUtc(cestMidnight, cestZone);
When DateTime.UtcNow is 12/29/2018 - 11:30:00 PM Will result in:
If you live in CEST and look at clock
cestNow: 12/30/2018 - 12:30:00 AM
If you live in CEST and had a look at clock at midnight (start of today, 30 minutes ago)
cestMidnight: 12/30/2018 - 12:00:00 AM
At your midnight, UTC was
cestMidnightInUTC: 12/29/2018 - 11:00:00 PM
Note: 12:00:00 AM is start of the day. So for example if utc now is 12/29/2018 - 11:30:00 PM, midnight was 23:30 hours ago at 12/29/2018 - 12:00:00 AM utc.
I am facing issue while converting datetime to UTC.
User enters date in mydate in the webform, which we need to convert in UTC and store it in DB.
User also selects timezone from the list which is stored in selectedTimeZone variable. So we have to convert mydate from selectedTimeZone to UTC.
TimeZoneInfo.ConvertTimeToUtc(mydate, selectedTimeZone);
Example#1 :
If mydate = 05/02/2016 09:00 AM and selectedTimeZone = EST (-5:00) then
TimeZoneInfo.ConvertTimeToUtc(mydate, selectedTimeZone) returns
05/02/2016 13:00
which is off by one hour
Example#2
If mydate = 05/02/2016 09:00 AM and selectedTimeZone = IST (indian
standard time) (+5:30) then TimeZoneInfo.ConvertTimeToUtc(mydate,
selectedTimeZone) returns 05/02/2016 03:30
which is correct
There are multiple examples like this.
What is the issue?
Edit:
I don't need to convert user input to DateTime as .net does it, we are getting mydate in mvc action method parameter.
I tried it by setting local timezone of a machine to UTC, London, IST..... but it makes no difference to the output.
It seems adjustment rules for given timezone play their role here. Take the following code:
var mydate = new DateTime(2016, 05, 02, 9, 0, 0);
var selectedTimeZone = TimeZoneInfo.FindSystemTimeZoneById("Eastern Standard Time");
var dstRule = selectedTimeZone.GetAdjustmentRules().FirstOrDefault(c => c.DateStart < mydate && c.DateEnd > mydate);
There is just one adjustment rule for EST timezone which is active at given time (it is active starting at 2007 year), and this rule works from second Sunday of March to first Sunday of November every year, adjusting time by one hour during that period. That is why you observe that behaviour. If you try to convert date outside of period for this rule (say, in February) - you will get what you would expect.
So to clarify: EST timezone has base offset of UTC-5, but because of daylight savings becomes UTC-4 during summer, and because your time is "summer" - .NET actually correctly converts that to UTC, it's not "off by one hour".
I have one situation where date is "3/13/2016 2:41:00 AM". When I convert date by time-zone, I get an error.
DateTime dt = DateTime.Parse("3/13/2016 2:41:00 AM");
DateTime Date_Time = TimeZoneInfo.ConvertTimeBySystemTimeZoneId(dt, "Eastern Standard Time",
"GMT Standard Time");
Response.Write(dt);
after execution, I get this error:
The supplied DateTime represents an invalid time. For example, when
the clock is adjusted forward, any time in the period that is skipped
is invalid. Parameter name: dateTime
Try to check if the time is ambiguous or a valid time. Due to the daylight change the time you mentioned i.e, 2:41:00 AM doesn not exist since the clock was moved 1 hour ahead and hence the date is invalid or ambiguous.
2016 Sun, 13 Mar, 02:00 CST → CDT +1 hour (DST start) UTC-5h
Sun, 6 Nov, 02:00 CDT → CST -1 hour (DST end) UTC-6h
You can also refer to this blog: System.TimeZoneInfo: Working with Ambiguous and Invalid Points in Time
System.TimeZoneInfo (currently available as part of .NET Framework 3.5
Beta 1) contains methods for checking if a DateTime instance
represents an ambiguous or invalid time in a specific time zone. These
methods are particularly useful for validating user-supplied points in
time.
Background Information
Time zones that adjust their time for Daylight Saving Time (in most
cases by moving the clock time back or forward by 1 hour) have gaps
and repeats in the timeline — wherever the clock time was moved
forward or back by the adjustment. Let’s use Pacific Standard Time as
an example. In 2007 Pacific Standard Time (PST) changes to Pacific
Daylight Time (PDT) at 02:00AM (“spring forward”) on the second Sunday
in March and then returns at 02:00AM (“fall back”) on the first Sunday
in November
To check if the time is valid you can use:
TimeZoneInfo.IsInvalidTime
In my case, I was trying to convert a UTC date (thus, it was valid, as UTC dates don't skip any periods of time with DST).
The problem was that I was loading the date from Entity Framework and the DateKind was set to Unspecified. In that case, ConvertTimeBySystemTimeZoneId assumes it is a local time and may find it invalid.
The solution is to properly set the DateKind to UTC before converting:
var date = DateTime.ParseExact("2019-03-31T03:06:55.7856471", "O", CultureInfo.InvariantCulture);
// Here date.Kind == DateTimeKind.Unspecified
date = DateTime.SpecifyKind(date, DateTimeKind.Utc);
// Now date.Kind == DateTimeKind.Utc
// Now the conversion should work
TimeZoneInfo.ConvertTimeBySystemTimeZoneId(date, "Central Standard Time");
I am trying to convert EST( Eastern Standard Time) to IST (Indian Standard Time) but the conversion is showing incorrect results.
Can anyone help me on that??
I searched on net and found that using Noda time we can solve that.
But I want to solve it using conventional DateTime class.
Here is my code and its output:
DateTime time= new DateTime(1899,12,30, 23, 30 ,0); //some random date and 11:30 PM in EST
TimeZoneInfo estZone = TimeZoneInfo.FindSystemTimeZoneById("Eastern Standard Time"); // Eastern Time Zone
TimeZoneInfo istZone = TimeZoneInfo.FindSystemTimeZoneById("India Standard Time"); // Indian Time Zone
DateTime localTime = TimeZoneInfo.ConvertTime(time, estZone, istZone); // result is 10:00 am while it should be 09:00 am.
A few things:
The TimeZoneInfo identifier "Eastern Standard Time" refers to the North American Eastern Time zone, covering both Eastern Standard Time and Eastern Daylight Time. EST is UTC-5, while EDT is UTC-4. In general, you should not infer too much from the names of these identifiers. See more examples in the timezone tag wiki.
The TimeZoneInfo.ConvertTime method will use whichever offset is appropriate for the supplied date and time, correctly taking the daylight saving time rules into account.
The underlying time zone data from Windows does not go back to 1899. There are actually no sources of data that guarantee historical dates from that time period. Even the IANA time zone database used with Noda Time makes an educated guess. See History of DST in the United States.
Windows will just use the earliest data it has, which for this zone uses the daylight saving time rules that were in effect from 1986 to 2007. These are not the current rules, so it would make better sense to use a modern year, such as DateTime.Today.Year.
Even if you supplied a modern year, the correct converted time would indeed be 10:00 for a date in December. If you want 9:00, try a date in the summer.
I want to specify a time in GMT timezone, and then convert it to the local TimeZone which is EST.
This appears to do what I want, but seems a long way to get there!
Is there a simpler way to achieve this:
public static TimeZoneInfo edtZone = TimeZoneInfo.FindSystemTimeZoneById("Eastern Standard Time");
public static TimeZoneInfo gmtZone = TimeZoneInfo.FindSystemTimeZoneById("GMT Standard Time");
public static CultureInfo ci = CultureInfo.InvariantCulture;
DateTime edtStartDT = TimeZoneInfo.ConvertTime(DateTime.SpecifyKind(DateTime.Now.Date.Add(new TimeSpan(18, 00, 00)), DateTimeKind.Unspecified), gmtZone, edtZone);
This is probably what you are looking for:
// A timespan isn't really a time-of-day, but we'll let that slide for now.
TimeSpan time = new TimeSpan(18, 00, 00);
// Use the current utc date, at that time.
DateTime utcDateTime = DateTime.UtcNow.Date.Add(time);
// Convert to the US Eastern time zone.
TimeZoneInfo tz = TimeZoneInfo.FindSystemTimeZoneById("Eastern Standard Time");
DateTime easternDateTime = TimeZoneInfo.ConvertTimeFromUtc(utcDateTime, tz);
Note that we're pairing the current UTC date with the time you provided. Since US Eastern time is either 5 or 4 hours behind UTC, with 18:00 you will always get the same date. But if you were using a different time, such as 00:00, you would find that the resulting Eastern time was on the prior day. This is normal.
A couple of notes about your previous code:
The Windows Time Zone ID "Eastern Standard Time" refers to both EST and EDT. It really should have been called "Eastern Time". Don't let the name confuse the issue.
GMT and UTC are mostly the same for all modern usage. Unless you are referring to the time zone used in London, you should prefer the term UTC.
The Windows Time Zone ID "GMT Standard Time" is not actually for GMT/UTC. It is specifically the time zone used in London, which alternates between GMT (UTC+00:00) and BST (UTC+01:00). If you want a TimeZoneInfo representing UTC, the ID is just "UTC". (However, you don't really need that in this case.)
Your original code assumed used DateTime.Now.Date, which would assume the date in the computer's local time zone - which might not be either UTC or Eastern.
If you find yourself using DateTime.SpecifyKind, in most situations, you're probably doing something wrong. (The exception would be when loading or deserializing.)
Regarding my note about a TimeSpan not being a true time-of-day, this is how .NET would have you handle that:
DateTime time = DateTime.Parse("18:00:00", CultureInfo.InvariantCulture);
DateTime utcDateTime = DateTime.UtcNow.Date.Add(time.TimeOfDay);
Or even uglier in one line:
DateTime utcDateTime = DateTime.Parse("18:00:00", CultureInfo.InvariantCulture,
DateTimeStyles.AssumeUniversal | DateTimeStyles.AdjustToUniversal);
Personally, I would rather use Noda Time, which has a separate LocalTime type explicitly for a time-of-day that's not bound to a specific date. I'm also working to get System.TimeOfDate and System.Date types added to the CoreCLR.