c# Converting UTC time to Central including timezone in DateTime object - c#

I'm converting the UTC time, taken from my local Server time to Central standard time. I have this running on a server in Germany.
Converting the time and date works, but when a library i have converts it to a string it has a wrong Timezone offset.
It comes out as 2019-05-11T14:44:09+02:00
when i need it to be 2019-05-11T14:44:09-06:00
TimeZoneInfo CRtimezone = TimeZoneInfo.FindSystemTimeZoneById("Central Standard Time");
TimeZoneInfo.ConvertTimeFromUtc(DateTime.UtcNow, CRtimezone);
The +02:00 is the UTCoffset for Germany, which i don't want, even the the time and date are correctly in Central Time.
Is there a way to pass or include the offset in the DateTime object?

Is there a way to pass or include the offset in the DateTime object?
No, DateTime structure does not have UTC Offset but DateTimeOffset has. If you really wanna keep your UTC Offset value in your code, I suggest you to work with DateTimeOffset instead of DateTime.
Since it doesn't keep UTC Offset value, when you get it's textual (aka string) representation, you still get the offset value of your server in Germany (includes K, z, zz and zzz specifiers by the way). TimeZoneInfo.ConvertTimeFromUtc method returns a DateTime instance, the offset value you might wanna represent depends on how you want to show it.
One option might be that you might wanna concatenate The Sortable ("s") Format Specifier representation of your DateTime and your TimeZoneInfo.BaseUtcOffset value.
TimeZoneInfo CRtimezone = TimeZoneInfo.FindSystemTimeZoneById("Central Standard Time");
$"{TimeZoneInfo.ConvertTimeFromUtc(DateTime.UtcNow, CRtimezone).ToString("s")}{CRtimezone.BaseUtcOffset}".Dump();

Related

DateTimeKind is Unspecified Even Though I Set it

When I check optionDate's DateTime property's DateTimeKind value, I see Unspecified, even though I set dt's DateTimeKind as UTC in below code. I expect optionDate has a DateTime which has a DateTimeKind property set to UTC. Where am I wrong here?
var dt = new DateTime(Convert.ToInt32(optionDateInfo.dateTime.year),
Convert.ToInt32(optionDateInfo.dateTime.month), Convert.ToInt32(optionDateInfo.dateTime.day),
Convert.ToInt32(optionDateInfo.dateTime.hour), Convert.ToInt32(optionDateInfo.dateTime.minutes),
0, DateTimeKind.Utc);
var optionDate = new DateTimeOffset(dt);
This is documented:
DateTimeOffset.DateTime
The value of the DateTime.Kind property of the returned DateTime object is DateTimeKind.Unspecified.
Note that a DateTimeOffset does not have a "kind". It has a date, time, and offset. When you pass your DateTime with kind Utc, to it, it sets its offset to 0, and its date & time to the DateTime given. At this point, your DateTimeKind is "lost".
An offset of 0 does not necessarily mean that its kind is DateTimeKind.Utc. It could be the local time in London, or somewhere in Africa too. So it can't give you a DateTime with kind Utc just because its offset is 0 either.
In addition, DateTime being able to represent 3 kinds of things is already a questionable design, and if the DateTime property can now return 3 different kinds of DateTime depending on whether offset matches the local time, is UTC, or something else, that's just even worse.
Instead, it is designed to have 3 properties that give you DateTimes with different kinds.
DateTime gives you the date & time part of the DateTimeOffset, with kind Unspecified
LocalDateTime converts the date & time part of the DateTimeOffset to the current timezone, and gives you a DateTime with kind Local.
UtcDateTime converts the date & time part of the DateTimeOffset to UTC, and gives you a DateTime with kind Utc.
If you want a DateTime with kind Utc, you should use that last one.
Use the SpecifyKind
var myUtcZeroOffset = DateTime.SpecifyKind(DateTime.UtcNow, DateTimeKind.Utc)
//If constructing a datetime offset to be not utc you can supply the offset instead
var myOffSetExplicitLocal = new DateTimeOffset(DateTime.Now, new TimeSpan(1, 0, 0));
var localDateTime = myOffSetExplicitLocal.DateTime;
var utcZeroOffSetDateTime = myOffSetExplicitLocal.UtcDateTime;
To make matters worse of cause it is a criticisable implementation from Microsoft, because Universally Coordinated Time is not a timezone but a notation, as per ISO 8601, so in fact toUTC as a concept is flawed because '2021-11-02T10:16:25.12345+01:00' is completely valid in the UTC format and UTC Zero offset, popularily called Zulu being the '2021-11-02T09:16:25.12345Z' equivalent which then gets datetimekind UTC is actually just in coordinated time the zero line around GMT latitude, but what makes it coordinated is the + part which in +00:00 can be abbreviated to Z, so lots of stuff is done to mitigate the inherent conflict and with build servers and cloud providers the .Local is especially dubious, so I would recommend always to persist in ISO 8601 strings instead, unless you actually need to use them in with date operations in Your DB, in said case to name fields appropriate like DateTimeCreatedUtcZero column e.g.
just my five cents of reason on the topic in general, hope it helps.

How to get datetime based on timezone offset in c#?

In c#, I do this
DateTime.Now.ToString("yyyy-dd-M--HH-mm-ss")
but it gets me the server time. However I also have the offset in this format for example "-04:00". How can I combine the offset to get the local time?
Thanks
If you mean that you want to get the server's system local time including offset, then use the DateTimeOffset.Now property. Then format it as desired.
DateTimeOffset.Now.ToString("yyyy-MM-dd HH:mm:ss zzz")
The zzz specifier produces the offset as a string in the ISO 8601 extended format, that you asked for.
If what you mean is you have a UTC offset from elsewhere and you want to apply it to the current UTC time from the server, then do the following instead:
TimeSpan offset = TimeSpan.Parse("-04:00");
DateTimeOffset now = DateTimeOffset.UtcNow.ToOffset(offset);
string result = now.ToString("yyyy-MM-dd HH:mm:ss zzz");
This takes the current server time, and applies the ToOffset function to adjust to the offset you provided.
Do keep in mind though that an offset is not the same as a time zone. The offset you have might be the one for the current date and time, or it might be for some other date and time in that time zone. For example, US Eastern Time is UTC-4 during daylight saving time, but UTC-5 during standard time. See "Time Zone != Offset" in the timezone tag wiki.
This worked.
DateTime.UtcNow.AddHours(DateTimeOffset.Parse("01/01/0001 00:00:00 -04:00").Offset.TotalHours).ToString("yyyy-dd-M--HH-mm-ss")
This should work
DateTime.UtcNow.AddHours(DateTimeOffset.Parse("01/01/0001 00:00:00 -04:00").Offset.TotalHours).ToString("yyyy-dd-M--HH-mm-ss",CultureInfo. InvariantCulture);
Need to add the directive
using System.Globalization;

Parse String DateTime containing TimeZone Info

I am trying to convert a string value to a datetime value but am getting a System.FormatException error. This is because of the timezone info which is part of the date string. Is there any method which will be able to handle this conversion?
string date = "Wed, 04 Jan 2012 20:18:00 EST";
DateTime dt = Convert.ToDateTime(date);
Console.WriteLine(dt.ToString());
I don't believe there's any custom date and time format string which will parse or format a time zone abbreviation. You'll have to strip it out, parse the local part, work out which time zone is meant from the abbreviation (good luck with that - they're ambiguous) and then apply that time zone to the local time to get a UTC value (again, this can be ambiguous).
If you're in control of the format at all, I would try to avoid including time zone information if you can, or include an offset rather than a time zone if that's all that's important (an offset doesn't give the same information of course), or an unambiguous time zone identifier if you really need the time zone. Note that .NET uses the Windows system time zone identifiers; my own Noda Time project uses the more widespread Olson / zoneinfo / tz identifiers, if that's helpful to you.

C#/.NET Date: From local to UTC

I get date data from a user. That data is a date (e.g. 4/23/2011) and an hour (0 - 23), representing the time. This date/time that the user selects is a local time.
I need to convert this to a UTC DateTime. I have their GMTOffset for their location. How can I do this?
You should work with the DateTimeOffset structure, specifically, the constructor that takes the DateTime and the TimeSpan that represents the offset.
From there, conversions to/from UTC are a breeze, as the offset is embedded in the structure and not dependent on local system settings.
Note, even though not commonly adhered to, it is recommended to work with DateTimeOffset most of the time, as opposed to DateTime (see the note under the section titled "The DateTimeOffset Structure").
var utcDateTime =
new DateTimeOffset(userDateTime, TimeSpan.FromHours(userUtcOffset)).UtcDateTime;
Of course you can use TimeSpan differently if the GMT offset has minutes / fractions of an hour.
Just use the DateTime.ToUniversalTime in C#, will that do what you want?

Converting UK times (both BST and GMT) represented as strings to UTC (in C#)

I have to use some dates and times from a legacy database. They are represented as strings. Dates are dd/MM/yy. Times are HH:mm.
I'd like to convert these to UTC as soon as I pull them from the database. I'm working on US systems, so need a common time.
The problem I'm facing is how to convert them to UTC DateTime values. I can do the parsing, etc. The real problem I have concerns the timezone.
I'm trying to use the following approach:
DateTime ukTime = // Parse the strings in a DateTime value.
TimeZoneInfo timeZoneInformation = TimeZoneInfo.FindSystemTimeZoneById("GMT Standard Time");
DateTimeOffset utcTime = new DateTimeOffset(ukTime, timeZoneInformation.BaseUtcOffset);
However, this gives incorrect values if the date is in the British Summer Time period.
I can use "GMT Daylight Time" on those dates, but that requires me to know when the switchover is. I'm sure there must be a less laborious way.
As I'm not using a machine with UK time settings I can't rely on local time.
Basically, I need something like:
// Works for both GMT (UTC+0) and BST (UTC+1) regardless of the regional settings of the system it runs on.
DateTime ParseUkTimeAsUtcTime(string date, string time)
{
...
}
I've scoured the posts, but couldn't find anything that addressed this directly. Surely this is also an issue with EST, EDT, etc?
Try using the GetUtcOffset() method on your TimeZoneInfo instance, which takes "adjustment rules" into consideration.
Using this should work basically the same as your original example, but you'll use that method instead of the BaseUtcOffset property.
DateTime ukTime = // Parse the strings in a DateTime value.
TimeZoneInfo timeZoneInformation = TimeZoneInfo.FindSystemTimeZoneById("GMT Standard Time");
DateTimeOffset utcTime = new DateTimeOffset(ukTime, timeZoneInformation.GetUtcOffset(ukTime));
How about:
DateTime.Parse(dateTimeString).ToUniversalTime();
Assuming that the database server stores its datetimes in the same timezone as your application server.

Categories

Resources