Probably a super simple solution but I'm clearly missing something.
I have a string object with value "2020/07/29 13:30:00".
How can I parse that into a DateTimeOffset object and make the assumption that the time zone of that parsed time is "GMT Standard Time" for example, or any TimeZoneInfo I wish to specify preferably?
How can I then take that DateTimeOffset, and return its Utc time but to any specified time zone of my choice?
Many thanks
The easiest I could find is something like this.
I couldn't find any methods to parse a DateTimeOffset in a particular given timezone, but you can parse your string as a DateTime (with a Kind of Unspecified, which just acts as a container for the bits of information in the string, without trying to apply timezone knowledge to it).
Then you can ask a TimeZoneInfo for the UTC offset in a given timezone at the given local time, and apply this to the DateTime to create a DateTimeOffset.
Once you've got your DateTimeOffset, you can work with it using its ToOffset method, and TimeZoneInfo.ConvertTime.
string input = "2020/07/29 13:30:00";
var timezone = TimeZoneInfo.FindSystemTimeZoneById("GMT Standard Time");
// DateTime.Parse creates a DateTime with Kind == Unspecified
var dateTime = DateTime.Parse(input);
Console.WriteLine(dateTime); // 7/29/2020 1:30:00 PM
// Since Kind == Unspecified, timezone.GetUtcOffset will give us the UTC offset in effect at
// the given local time in timezone
var dateTimeOffset = new DateTimeOffset(dateTime, timezone.GetUtcOffset(dateTime));
Console.WriteLine(dateTimeOffset); // 7/29/2020 1:30:00 PM +01:00
// Convert to UTC
Console.WriteLine(dateTimeOffset.UtcDateTime); // 7/29/2020 12:30:00 PM
Console.WriteLine(dateTimeOffset.ToOffset(TimeSpan.Zero)); // 7/29/2020 12:30:00 PM +00:00
// Convert to another timezone
var cst = TimeZoneInfo.FindSystemTimeZoneById("Central America Standard Time");
Console.WriteLine(TimeZoneInfo.ConvertTime(dateTimeOffset, cst)); // 7/29/2020 6:30:00 AM -06:00
Try the DateTimeOffset.ParseExact overload that accepts a DateTimeStyles parameter.
This code:
var dt=DateTimeOffset.ParseExact("2020/07/29 13:30:00","yyyy/MM/dd HH:mm:ss",
CultureInfo.InvariantCulture,DateTimeStyles.AssumeUniversal);
Returns 2020-07-29T13:30:00.0000000+00:00
There's no GMT Standard Time, that's a very unfortunate name used in Windows that somehow manages to mix up British and UTC time to the point that no-one knows what it means without looking at the docs. This was thoroughly discussed and explained in this question: Difference between UTC and GMT Standard Time in .NET. As one of the answers explains :
The names GMT Standard Time and GMT Daylight Time are unknown outside of Redmond. They are mythical animals that appear only in the bestiary called the Windows Registry.
If you wanted to assume British time and your machine uses a British timezone, you can use DateTimeStyles.AssumeLocal
This function should convert your date time string (with assumption this is GMT Standard Time) to any other timezone:
public static DateTime? ToUTCTimeZone(string sDate, string timeZone)
{
DateTime utcDate = DateTime.Parse(sDate);
DateTimeOffset localServerTime = DateTimeOffset.Now;
utcDate = DateTime.SpecifyKind(utcDate, DateTimeKind.Utc);
TimeZoneInfo cstZone = TimeZoneInfo.FindSystemTimeZoneById(timeZone);
if (cstZone == null)
return null;
return TimeZoneInfo.ConvertTimeFromUtc(utcDate, cstZone);
}//ToUTCTimeZone
Related
Hi i receice some random datetimeoffset utc my point is
1 - turn it into chicago time
2- Define the chicago startOfDay
3-finaly convert chicago startOfDay back to an utc datetimeOffset.
(this process is needed to query an utc api)
i writed this that seem do what i want but realy not sure it will always do the job with day saving light etc..
someone can tell or improve the code?
var UTCDate = DateTimeOffset.UtcNow; //<----------Some random utc dateTimeOffset
TimeZoneInfo zone = TimeZoneInfo.FindSystemTimeZoneById("Central Standard Time");
DateTimeOffset CSTDate = GetZoneDatetimeOffset(UTCDate, zone);
Console.WriteLine("Utc : {0} Chicago: {1} local : {2}", UTCDate, CSTDate, UTCDate.ToLocalTime());
Console.WriteLine(" Chicago StartOfDay: {0} Chicago StartOfDay To UTC : {1}", CSTDate.Date, CSTDate.Date.ToUniversalTime());
public DateTimeOffset GetZoneDatetimeOffset(DateTimeOffset someUTCDate , TimeZoneInfo destZone)
{
DateTimeOffset ZoneDateTimeOffset = TimeZoneInfo.ConvertTimeBySystemTimeZoneId(someUTCDate.DateTime , TimeZoneInfo.Utc.Id, destZone.Id);
return ZoneDateTimeOffset;
}
You have a few bugs in your code:
You call TimeZoneInfo.ConvertTimeBySystemTimeZoneId and pass a DateTime value. The result will thus also be a DateTime. The Kind of that result will be Unspecified. Assigning it to a DateTimeOffset thus will perform an implicit cast operation from DateTime to DateTimeOffset, which will use the computer's local time zone - not the time zone you are working with.
Both DateTimeOffset.Date and DateTimeOffset.DateTime also return a DateTime whose Kind is Unspecified. Thus when you call ToLocalTime or ToUniversalTime, you are again using your the computer's local time zone.
Determining the start of the day in a specific time zone can be tricky. Though it doesn't happen in Chicago (or anywhere in the USA), some time zones of the world have DST transitions that occur immediately at the start of the day. Thus 00:00 might not be the first moment of the day, or it might occur twice. Your code doesn't account for that.
A good example is Cuba, where DST next starts on 2022-03-13 at midnight, and thus the start of that day in Cuba is 2022-03-13T01:00.
You can use the GetStartOfDay method I already provided in this answer to handle these edge cases.
Putting it all together:
// Input values
DateTimeOffset utc = DateTimeOffset.UtcNow;
TimeZoneInfo zone = TimeZoneInfo.FindSystemTimeZoneById("Central Standard Time");
// Convert with full fidelity using only DateTimeOffset values
DateTimeOffset converted = TimeZoneInfo.ConvertTime(utc, zone);
// Get the start of day using the method from https://stackoverflow.com/a/49988688
DateTimeOffset startOfDay = GetStartOfDay(converted.DateTime, zone);
// Output the results
Console.WriteLine("Original values:");
Console.WriteLine("Chicago: {0:o} UTC: {1:o} Local: {2:o}", converted, utc, utc.ToLocalTime());
Console.WriteLine();
Console.WriteLine("At start of day in Chicago:");
Console.WriteLine("Chicago: {0:o} UTC: {1:o} Local: {2:o}", startOfDay, startOfDay.ToUniversalTime(), startOfDay.ToLocalTime());
Example output (local time zone is US Pacific Time in this example):
Original values:
Chicago: 2022-03-10T10:58:47.8164830-06:00 UTC: 2022-03-10T16:58:47.8164830+00:00 Local: 2022-03-10T08:58:47.8164830-08:00
At start of day in Chicago:
Chicago: 2022-03-10T00:00:00.0000000-06:00 UTC: 2022-03-10T06:00:00.0000000+00:00 Local: 2022-03-09T22:00:00.0000000-08:00
See also the working .NET Fiddle here.
I am trying to get a timestamp for "Local midnight in UTC" using .NET Core.
I wrote this code:
var utcTimeStartLocalDay =
TimeZoneInfo.ConvertTimeToUtc(convertToLocalTimezone(DateTime.UtcNow).Date);
where
public DateTime ConvertToLocalTimezone(DateTime dateTime)
{
return TimeZoneInfo.ConvertTime(dateTime, TimeZoneInfo.Utc,TimeZoneInfo.FindSystemTimeZoneById("FLE Standard Time"));
}
So, the idea is to get Utc timestamp, convert it to local TZ, then take Date (that is, discard time part and effectively make a midnight timestamp) and convert back to Utc - that should have given me local time.
However, it did not happen, as the result of the first expression is Utc midnight when printed.
Fiddle: https://dotnetfiddle.net/wJIXve
What do I need to correct here to get as the answer the local midnight for the day expressed as UTC (something like 22:00 UTC previous day)?
Edit: just to clarify an unclearness in the question: by "local" TZ I meant known local timezone (found in the code)
To ensure that you are definitely using local time, I would use this code:
DateTime localMidnight = DateTime.SpecifyKind(DateTime.Now.Date, DateTimeKind.Local);
Then simply use .ToUniversalTime() to get the UTC date:
DateTime localMidnightUtc = localMidnight.ToUniversalTime();
Here's a working example:
static async Task Main(string[] args)
{
DateTime localMidnight = DateTime.SpecifyKind(DateTime.Now.Date, DateTimeKind.Local);
DateTime localMidnightUtc = localMidnight.ToUniversalTime();
Console.WriteLine($"localMidnight: {localMidnight}");
Console.WriteLine($"localMidnightUTC: {localMidnightUtc}");
}
// Output:
// localMidnight: 29.01.2020 00:00:00
// localMidnightUTC: 28.01.2020 23:00:00
(And now you know which timezone I'm in ;)
This should work.
var result = DateTime.Now.Date.ToUniversalTime();
This one-liner is the same as .NET Framework:
DateTime.Today.ToUniversalTime();
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.
I want to parse the string to time.
string inputDate = "1970-01-01T00:00:00+0000";
var dt = DateTime.Parse(inputDate, CultureInfo.InvariantCulture);
Console.WriteLine("Date==> " + dt);
It is working fine in india time(UTC +5.30).
But when I change the time zone to UTC -5 in settings in emulator, the out put is showing
12/31/1969 7:00:00 PM
The date should be same when ever i change the time zone in settings. Please help me to resolve my problem.
Let me explain what is going on here..
Usually, DateTime.Parse method returned DateTime's Kind property will be Unspecified.
But since your string has time zone information and you using DateTime.Parse method without DateTimeStyles overload (it uses DateTimeStyles.None by default), your DateTime's Kind property will be Local.
That's why when you use your code in UTC +05.30 time zone system, it will be generate a result like;
01/01/1970 05:00:00 AM
and when you use in UTC -05.00 time zone system, it will generate;
12/31/1969 7:00:00 PM // which is equal 12/31/1969 19:00:00 AM representation
which is too normal.
The date should be same when ever i change the time zone in settings.
Makind your DateTime as UTC is the best choice in such a case. Using ToUniversalTime() method is one way to do that in a Local time.
From documentation;
The Coordinated Universal Time (UTC) is equal to the local time minus
the UTC offset.
Since your code generates Local time, your ToUniversalTime() generated datetime's will be the same in both time zone.
Another way to do it, using DateTimeStyles.AdjustToUniversal as a third parameter in DateTime.Parse method.
From documentation;
Date and time are returned as a Coordinated Universal Time (UTC). If
the input string denotes a local time, through a time zone specifier
or AssumeLocal, the date and time are converted from the local time to
UTC. If the input string denotes a UTC time, through a time zone
specifier or AssumeUniversal, no conversion occurs. If the input
string does not denote a local or UTC time, no conversion occurs and
the resulting Kind property is Unspecified.
string inputDate = "1970-01-01T00:00:00+0000";
var dt = DateTime.Parse(inputDate,
CultureInfo.InvariantCulture,
DateTimeStyles.AdjustToUniversal);
That will generate 01/01/1970 00:00:00 which Kind is Utc.
Final Solution
string givenDate = ("1970-01-01T00:00:00+0000");
DateTime d = DateTime.Parse(givenDate, System.Globalization.CultureInfo.InvariantCulture);
string ouputDate = d.ToUniversalTime().ToString("MMM d, yyyy h:m:s tt", System.Globalization.CultureInfo.InvariantCulture);
How do I convert a DateTime from EST/EDT to GMT but I don't know where the code will be ran (unknown local time zone) and also account for time savings...
You want TimeZoneInfo.ConvertTimeToUtc(), which allows you to pass the source time zone info as a parameter. For example:
TimeZoneInfo est = TimeZoneInfo.FindSystemTimeZoneById("Eastern Standard Time");
DateTime someDateTimeInUtc = TimeZoneInfo.ConvertTimeToUtc(someDateTime, est);
I think this will automatically handle daylight-saving time, but you'll want to test it to be sure.
Take a look at the TimeZoneInfo class.