I'm trying to get the difference between an application running on Windows Embedded 7 and UTC time. To do that I have the following piece of code:
TimeZoneInfo utcTimeZone = TimeZoneInfo.FindSystemTimeZoneById("GMT Standard Time");
DateTime localTime = DateTime.Now;
DateTime utcTime = TimeZoneInfo.ConvertTime(localTime, TimeZoneInfo.Local, utcTimeZone);
TimeSpan utcOffset = localTime - utcTime;
This runs fine on my own development PC, running Windows 7. However, when I install my application on a device running Windows Embedded 7, no matter what timezone I set it to, when I run my application,
The value for TimeZoneInfo.Local.BaseUtcOffset is always 00:00.
The BaseUtcOffset value in the object returned by TimeZoneInfo.FindSystemTimeZoneById("GMT Standard Time") is also 00:00 (though this is to be expected).
The ConvertTime() function above always returns the current time less one hour. (Kind of not surprised since the TimeZoneInfo.Local.SupportsDaylightSavingsTime value is always false.)
Should I be using another way that TimeZoneInfo.Local to get the offset between UTC and the current time zone? I need to include Daylight Savings in this.
A few things:
The time zone with the ID "GMT Standard Time" is not UTC - it's UK Time. Its display name matches "Dublin, Edinburgh, Lisbon, London". It uses UTC+0 in the winter, and UTC+1 in the summer for daylight saving time.
The UTC time zone ID is simply "UTC" - though you'll rarely need that.
If TimeZoneInfo.Local.BaseUtcOffset is zero, then that means the computer's time zone setting is one that has UTC+0 as its standard offset. There are four of those currently defined in Windows. This property does not reflect daylight saving time.
Recognize that offsets will change depending on what time of the year that you are running the code. A time zone is not the same as a time zone offset.
Since you said you got zero in your above code, I'd guess that your local time zone is either the previously mentioned UK Time, or Casablanca, Morocco. This is because you are subtracting a UTC+1 local time with the time from another time zone that is also UTC+1 presently. 1 - 1 = 0
The correct way to do this does not involve subtraction at all. Simply use the GetUtcOffset method:
TimeSpan offset = TimeZoneInfo.Local.GetUtcOffset(DateTime.Now);
Again, note that this returns the current offset. Running it at different times of the year, or by passing a different value instead of DateTime.Now could return a different result.
Related
With what I understood from other questions I've used below code for checking a date if it is Daylight saving time and altering as required. I do not know which region would the application be used hence I am using Utc. However it is not working as expected.
DateTime dateValWithOffset = dateVal;
TimeZoneInfo timeZoneInfo = TimeZoneInfo.Utc;
if(timeZoneInfo.IsDaylightSavingTime(dateValWithOffset))
{
dateValWithOffset = dateValWithOffset.AddMinutes(60);
}
Example: for sample date (06-JUL-21 06.16.34.547000000 AM) above code should be showing dateValWithOffset as 07/06/2021 02:16:34.547 AM but it returns 07/06/2021 01:16:34.547 AM . If someone can point out where am I going wrong please.
Datetime values should always be in UTC. To format a datetime in the machine or user's local timezone, you should convert to a DateTimeOffset. Knowing the local time and knowing if that time is in daylight saving time are two different things.
// machine local
var timeZoneInfo = TimeZoneInfo.Local;
// or by name
var timeZoneInfo = TimeZoneInfo.FindSystemTimeZoneById(name);
var localTime = new DateTimeOffset(dateVal, timeZoneInfo.GetUtcOffset(dateVal));
var isDst = timeZoneInfo.IsDaylightSavingTime(localTime)
IMHO DateTime is a terrible type, designed before the age of cloud computing. All DateTimeKind values other than Utc encourage programmers to continue to handle dates incorrectly and should be deprecated.
As jason.kaisersmith said in comments, "UTC is universal, so there is no daylight saving."
To elaborate, UTC does not have any daylight saving time. Instead, daylight saving time is observed differently at each time zone across the world. Some time zones don't use it at all. Some time zones start and stop DST at different dates or times than other time zones. There's even one time zone that shifts for DST by 30 minutes instead of the usual 1 hour. Without a time zone reference, the concept of DST is meaningless.
For clarity and reference, here's an overview of anticipated DST dates for 2022 by country, and a detailed list of dates and times for the first half and second half of 2022.
I have an application that converts local time to UTC and stores it in the database. I encountered this problem while I was testing the conversion during a particular date - 1st November, 2015(the date on which the Daylight savings time ends(the clock goes back to 1.00AM on reaching 2.00AM)).
My local system timezone is (UTC-08:00) Pacific Time (US & Canada)
I converted the time 2015-10-31 01:49:00.000 to UTC, the output was 2015-10-31 08:49:00.000.
but
when I tried to convert 2015-11-01 01:49:00.000 to UTC, the output was 2015-10-31 09:49:00.000.
Isn't this wrong? why did the converted time increase by an hour on 1st November?
This is my method,
DateTime universalFormatDateTime = localDateTime.Value.GetUniversalFormatDateTime();
utcDateTime = TimeZoneInfo.ConvertTimeToUtc(universalFormatDateTime, _timeZoneInfo);
Isn't this wrong? why did the converted time increase by an hour on 1st November?
Because that's when the clocks change, as you say.
The problem is that "2015-11-01 01:49:00.000" is ambiguous in Pacific Time - it occurs twice, once at 2015-11-01T08:49:00Z and once at 2015-11-01T09:49:00Z.
A DateTime can remember which of those you mean, but it depends on how you came up with the value. If you've just parsed this from text somewhere, you basically don't have enough information - it doesn't specify a single instant in time.
If you were to use my Noda Time library instead, then when converting from LocalDateTime to ZonedDateTime you'd be able to specify how you wanted ambiguity to be handled - so that may be an option for you... but it depends on where the value came from, and whether you know that it was always the second occurrence or always the first.
If you still want to use TimeZoneInfo, you can use TimeZoneInfo.IsAmbiguousTime and TimeZoneInfo.IsInvalidTime to detect local times which occur twice or zero times due to time zone shifts, and then handle those appropriately in your app.
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
I try to verify if some machines are synchronized. For that I read the hrSystemTime OID of a remote machine in a string, convert it to DateTime and compare it with the time of the local machine. I do this once a day at 1:50 AM. In November 3rd, at 1:50 AM, diff showed an hour difference, while diff2 showed no difference. This 1 hour diff pop up if I verify only on this day between 1:00 AM and 2:00 AM. (2:00 AM is the time when DST is changing the hour to 1:00 AM for winter).
DateTime localTime;
DateTime remoteTime;
TimeSpan diff, diff2;
localTime = DateTime.Now;
remoteTime = Convert.ToDateTime("11/03/2013 1:50:00 AM");
diff = localTime.ToUniversalTime() - remoteTime.ToUniversalTime();
diff2 = localTime.ToLongTimeString() - remoteTime.ToLongTimeString();
These are the printed values:
localTime.ToUniversalTime() = 11/03/2013 1:50:00 AM
remoteTime.ToUniversalTime() = 11/03/2013 1:50:00 AM
localTime.ToLongTimeString() = 11/02/2013 8:50:00 PM
remoteTime.ToLongTimeString() = 11/02/2013 9:50:00 PM
You should probably just use DateTime.UtcNow on both systems and compare those. That eliminates issues of local time zones and DST affecting the comparison.
You should probably also use an ISO8601 formatted string when comparing between two systems, in case those systems have different date formats due to regional settings. You can get that with yourDateTime.ToString("o").
But also consider, you are probably not taking into account network transmittal delay time in your comparison. For that, you should use NTP rather than writing your own code in C#.
When you say you run this every day at 1:50 AM, do you read dateTime.Now().
It looks like your DateTime.Now has changed from or to DST correctly, resulting in a different Universal time, but you are, in Universal time, running the job at a different time by the looks of it.
If you make sure you retrieve the local and remote time including the time zone information, it will include a DST-aware UTC-offset so that even when one side switches DST it should not affect your comparison.
Do be aware that the clock that governs your job scheduling should be aware of a DST change.
This should be fairly simple but I am worst when it comes to time zones. I am getting values from a web service for events generated as following,
Eastern Turkey: 2012-05-04T19:36:30.5+00:00
Southern Greece: 2012-05-04T19:33:32.6+00:00
Poland: 2012-05-04T19:09:36.3+00:00
Do above values represent date time in UTC? (I started with Eastern Turkey but that is +2:00 offset from UTC/GMT and that is making me confused).
My exact problem is that I need to convert above date time to local time zone on WP7 device so is the code below the right approach to do so?
//Convert first To UTC Date Time
DateTime convertedDate = DateTime.SpecifyKind( DateTime.Parse(elementTimeValue.Value),
DateTimeKind.Utc);
//Now to local time
convertedDate.ToLocalTime(); << Will this return me with time adjusted to that of operating device (WP7)
That's what I am getting for each one of these (while device is in Pakistan),
5/4/2012 7:36:30 PM < Eastern Turkey
5/4/2012 12:33:32 PM < Southern Greece
5/4/2012 12:9:36 PM < Poland
Are these correct? If no, what do I need to do?
These are not UTC times because they have timezone specification even though it's 00:00. Example of UTC time would be 2012-11-05T13:15:30Z (not the Z at the end). Look here for more details.
UTC is time zone independant. You just have a date and time stamp, that's it. You would then convert this time stamp to the relevant time zones. So for example to convert it to Eastern Turkey time you would need to add two hours to your time stamp using your operating system's date library.
UTC time zones end in a 'Z' for the offset. The ones you have posted are in Greenwich Mean Time (+00:00). This is similar to UTC in that it has zero offset but not technically the same thing.
Edit: The following web site is really helpful fo confirming if your time zone conversions/date arithmetic is correct (check out the time zone calculators): http://www.timeanddate.com/
For your issue you would need to get the time zone from the user's computer/mobile using TimeZone.CurrentTimeZone so that you know what you're trying to convert in to. I think you would be able to do the conversion using TimeZoneInfo.ConvertTime().
If you're going to the local timezone, by far the easiest approach should be using DateTimeOffset's Parse and then either just access the LocalDateTime Property (if you only need a DateTime) or convert it with ToLocalTime.
Here's an example using one of your strings
C:\Users\James » [datetimeoffset]::parse('2012-05-04T19:36:30.5+00:00').tostring()
5/4/2012 7:36:30 PM +00:00
C:\Users\James » [datetimeoffset]::parse('2012-05-04T19:36:30.5+00:00').tolocaltime().tostring()
5/4/2012 3:36:30 PM -04:00
C:\Users\James »