Incorrect UTC Datetime Calculated based on TimeZoneInfo - c#

I have a timezoneinfo Central Europe Standard Time, which is showing UTC +01:00,
when i execute the code it shows 2 hrs before time instead of 1 hr.
Below is the sample code
static void Main(string[] args)
{
var strTimeZoneInfo = "Central Europe Standard Time";
var datetimeDST = Convert.ToDateTime("2019-07-18 18:17:00");
var timeZoneInfo = TimeZoneInfo.FindSystemTimeZoneById(strTimeZoneInfo);
var dtUTC= TimeZoneInfo.ConvertTimeToUtc(datetimeDST, timeZoneInfo);
Console.WriteLine(Convert.ToString(dtUTC));
Console.ReadKey();
}
So instead of 2019-07-18 17:17:00 i am getting 2019-07-18 16:17:00.
Can someone explain how to resolve this without using Noda or other external library.
Referred Below links but not clear how to resolve this problem.
UTC converted to Central Europe Standard Time is 2 hours in front not 1
Is there a generic TimeZoneInfo For Central Europe?
Also referred this link's answer but it's not working.

Even though "Central Europe Standard Time" is the Id property for that TimeZoneInfo, but it actually handles both Standard and Daylight time within that time zone depending on the date you're talking about. I understand it is confusing because that TimeZoneInfo includes "UTC+01:00" in the Display Name, even though it's currently in Daylight Savings Time.
But in this case, the date you're giving it is during a Daylight Savings Time period, so the offset should be +02:00, not +01:00. The library is producing the correct results.
var strTimeZoneInfo = "Central Europe Standard Time";
var datetimeDST = Convert.ToDateTime("2019-07-18 18:17:00");
var timeZoneInfo = TimeZoneInfo.FindSystemTimeZoneById(strTimeZoneInfo);
Console.WriteLine(timeZoneInfo.DisplayName);
Console.WriteLine(timeZoneInfo.StandardName);
Console.WriteLine(timeZoneInfo.DaylightName);
Console.WriteLine(timeZoneInfo.IsDaylightSavingTime(datetimeDST));
Console.WriteLine(timeZoneInfo.GetUtcOffset(datetimeDST));
var dtUTC = TimeZoneInfo.ConvertTimeToUtc(datetimeDST, timeZoneInfo);
Console.WriteLine(dtUTC.ToString(CultureInfo.InvariantCulture));
Output:
(UTC+01:00) Belgrade, Bratislava, Budapest, Ljubljana, Prague
Central Europe Standard Time
Central Europe Daylight Time
True
02:00:00
07/18/2019 16:17:00

Related

Incorrect result when using TimeZoneInfo.ConvertTime() to get a localised datetime

I have a very simple task and TimeZoneInfo.ConvertTime() is giving an incorrect result. I simply want to find the current datetime in the "Cen. Australia Standard Time" zone:
string timeZone = "Cen. Australia Standard Time";
TimeZoneInfo zoneID = TimeZoneInfo.FindSystemTimeZoneById(timeZone);
DateTime nowAtTimeZone = TimeZoneInfo.ConvertTime(DateTime.UtcNow, zoneID);
// result: 24/10/2018 7:43:29 PM
// actual ACST time: 24/10/2018 6:43:29 PM (this is what I want)
// actual ACDT time: 24/10/2018 7:43:29 PM (this is not what I want)
I got the actual ACST time from here: https://www.timeanddate.com/time/zones/acst
And the actual ACDT time from here: https://www.timeanddate.com/time/zones/acdt
Note that replacing TimeZoneInfo.ConvertTime() with TimeZoneInfo.ConvertTimeFromUtc() gives identical results.
Note that the timezone is entered by the customer and this is all the information I have available. They do not record the city.
The result from TimeZoneInfo.ConvertTime() appears to be giving ACDT time, even though I have specified ACST.
The problem could be that TimeZoneInfo.ConvertTime() is applying daylight savings to ACST, when it should not be? If so how can I prevent it from doing that?
Time zones in Australia are complex as they are in many parts if the world. Wikipedia's page on this subject is a good overview.
As you can see, there are two major areas that use Australia Central Standard Time. One uses DST, the other does not.
For .NET on Windows with the TimeZoneInfo class:
Use "Cen. Australia Standard Time" for the ID of the south central Australian time zone that uses daylight saving time. Locations include Adelaide, and others.
Use "AUS Central Standard Time" for the ID of the north central Australian time zone that does not use daylight saving time. Locations include Darwin, and others.
The TimeZoneInfo class is doing the correct thing, based on the time zone it is given.
As far as picking the correct zone, use TimeZoneInfo.GetSystemTimeZones() to return all of the available time zones, the use the Id and DisplayName properties to create a drop-down list. The user should only have to choose from the display names, and you only need to use the ID in your code.
You need to call TimeZoneInfo.ConvertTimeFromUtc(datetime, timezoneInfo). Check this
string timeZone = "Cen. Australia Standard Time";
TimeZoneInfo zoneID = TimeZoneInfo.FindSystemTimeZoneById(timeZone);
DateTime nowAtTimeZone = TimeZoneInfo.ConvertTimeFromUtc(DateTime.UtcNow, zoneID);

TimeZoneInfo.ConvertTime from PST to UTC to AEST - off by one hour

I convert a string that represents a time in Pacific Time Zone that I am using to create a DateTime object:
var pacificDateTime = new DateTime(2016, 11, 16, 15, 0, 0) // 11/16/2016 3:00:00 PM
Using that, I create a DateTimeOffset because ultimately it becomes a bit easier to work with.
var pacificTimeZoneInfo = TimeZoneInfo.FindSystemTimeZoneById("Pacific Standard Time");
var dateTimeNoKind = new DateTime(pacificDateTime.Ticks, DateTimeKind.Unspecified)
var DateTimeOffsetValue = TimeZoneInfo.ConverTimeToUtc(dateTimeNoKind, pacificTimeZoneInfo) // 11/16/2016 11:00:00 PM
So far so good. The difference between UTC and Pacific is that UTC is ahead by 8 hours (the given time is within daylight savings).
Then I want to convert from UTC to AEST—but this is where the problem appears:
var australianEasternTimeZoneInfo = TimeZoneInfo.FindSystemTimeZoneById("AUS Eastern Standard Time");
TimeZoneInfo.ConvertTime(DateTimeOffsetValue, australianEasternTimeZoneInfo) // 11/17/2016 10:00:00 AM
AEST is ahead of UTC by 10 hours. I had expected the value to be 11/17/2016 09:00:00 AM but instead I am getting an extra hour added to my result.
As a test, when I convert to PST or GMT or EST from the UTC time, they appear to convert back correctly.
I feel like I am missing something obvious or overlooking something simple?
From Wikipedia's Time in Australia article:
Australia has two eastern time zones. In the northeast, UTC+10 applies all year. In the southeast, UTC+10 applies during standard time, and UTC+11 applies during daylight time (aka summer time).
The northeast region (Queensland) uses the IANA time zone identifier "Australia/Brisbane", while the southeast region (New South Wales) uses "Australia/Sydney". These correspond to the Windows time zone identifiers: "E. Australia Standard Time" and "AUS Eastern Standard Time" respectively.
If you are converting for Queensland, use "E. Australia Standard Time".
If you are converting for New South Wales, use "AUS Eastern Standard Time".
As to the confusing nature of these identifiers, see the section about Windows time zones in the timezone tag wiki.
If you want to use the standard IANA identifiers instead, use Noda Time.

Converting EST to IST gives error in C#

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.

Does "GMT Standard Time" imply BST?

I am confused by "GMT Standard Time".
I have data which is stored as DATE only, but is actually 6PM BST.
I read it in and add 18 hours. I then try to convert to UTC. My initial understanding is that the conversion would NOT take into account Daylight time (as "GMT Standard Time" and UTC are both WITHOUT daylight time). I thought I would have to test for daylight time on the source and then make an adjustment.
However, ConvertTime appears to know about Daylight time in the source and makes the appropriate change.
That seems odd to me - is this the expected behaviour?
TimeZoneInfo gmtZone = TimeZoneInfo.FindSystemTimeZoneById("GMT Standard Time");
TimeZoneInfo utcZone = TimeZoneInfo.FindSystemTimeZoneById("UTC");
public static CultureInfo ci = CultureInfo.InvariantCulture;
string SomeDT = "27/01/2000"; //First BST day
var sourceDT = DateTime.ParseExact(SomeDT, "dd/MM/yyyy", ci).AddHours(18);
var utcDT = TimeZoneInfo.ConvertTime(sourceDT, gmtZone, utcZone);
// At this point utcDT has already been changed so test below is redundant.
// That Suggest "GMT Standard Time" is actually "Daylight Time" i.e.BST
if (gmtZone.IsDaylightSavingTime(sourceDT))
{
utcDT = utcDT.AddHours(-1);
}
else
{
Console.WriteLine("Not BST");
}
The problem is that the time zone IDs in Windows are confusing. Even though the ID is "GMT Standard Time", the time zone referred to by that ID is really "UK time"... like "Europe/London" in IANA. So yes, it will observe DST.
If you want genuine UTC, just use TimeZoneInfo.Utc.
(Alternatively, use Noda Time or something similar instead, and the more standard IANA time zones...)

how to get current UTC offset of different timezones?

Problem:
I Need to execute a task on a server that is on UTC at specific time in different time zones. Say for example I want to execute at 9:00AM Pacific Time, irrespective of Daylight Savings changes.
What do I have?
I checked the enumeration of time zones by doing
var infos = TimeZoneInfo.GetSystemTimeZones();
foreach (var info in infos)
{
Console.WriteLine(info.Id);
}
I could see only "Pacific Standard Time" for the pacific time for example and If I do the following,
TimeZoneInfo.FindSystemTimeZoneById("Pacific Standard Time").GetUtcOffset(DateTime.UtcNow)
I get -07:00:00 as output but as of now the offset is -08. That means it doesn't consider the daylight changes.
I was planing to to create a DateTime instance based on the offset I get above, which doesn't seem to work as I expected.
Also, I can't use frameworks like NodaTime
Any idea how I can get it working?
You've already got your answer, using TimeZoneInfo.GetUtcOffset and passing a DateTime with DateTimeKind.Utc will work.
I get -07:00:00 as output but as of now the offset is -08. That means it doesn't consider the daylight changes.
Actually, -7 is indeed the current offset, as Pacific time is currently using daylight saving time. In the winter, the offset reverts to -8, which is the standard offset. I think you just have them backwards.
Also, keep in mind that the Id property of a TimeZoneInfo object is the identifier for the entire time zone. Some of them are misleading, like "Pacific Standard Time" - which would make you believe that it only uses Pacific Standard Time (PST), but actually it represents the entire North American Pacific Time zone - including Pacific Standard Time and Pacific Daylight Time. It will switch offsets accordingly at the appropriate transitions.
You are probably looking for something like this:
var chinaTime = TimeZoneInfo.ConvertTimeFromUtc(DateTime.UtcNow, TimeZoneInfo.FindSystemTimeZoneById("China Standard Time"));
var pacificTime = TimeZoneInfo.ConvertTimeFromUtc(DateTime.UtcNow, TimeZoneInfo.FindSystemTimeZoneById("Pacific Standard Time"));
The string passed to FindSystemTimeZoneById is picked form TimeZoneInfo.GetSystemTimeZones()
Update: cleansed the code

Categories

Resources