Convert American datetime to EU datetime in computer located in EU? - c#

I get some datetime (ExactDate) from a db. These time are in US timezone, I need to convert them in EU TimeZone.
However if I use :
ExactDate = (DateTime)dr["CREATE_DATE"];
// change exact date to european time
TimeZoneInfo info;
info = TimeZoneInfo.FindSystemTimeZoneById("US Mountain Standard Time");
ExactDate = TimeZoneInfo.ConvertTime(ExactDate,info);
The dates are not converted properly because my computer is seeing the ExactDate as an European date.
Do you know how I can solve this ?

Try converting the date from the other TimeZone to UTC
like
ExactDate = TimeZoneInfo.ConvertTimeToUtc(ExactDate,info);
Once you have the corresponding UTC time you can get the European one later on using .ToLocal
Hope this is what you want.

Related

Parse String into DateTimeOffset While Assuming TimeZone

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

I want to specify a TimeZone as GMT but create a DateTime that is local (EST);

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.

Converting Local Time To UTC

I'm up against an issue storing datetimes as UTC and confused why this does not yield the same result when changing timezones:
var dt = DateTime.Parse("1/1/2013");
MessageBox.Show(TimeZoneInfo.ConvertTimeToUtc(dt, TimeZoneInfo.Local).ToString());
I am manually switching my local time zone on the machine between eastern and central.
Central yields 1/1/2013 6:00:00 AM, and Eastern yields 1/1/2013 5:00:00 AM. What am I missing here? They should be the same regardless of the time zone, correct?
Thanks so much in advance!
I think what you are missing is that the DateTime returned by your DateTime.Parse() statement doesn't come with a time zone. It's just a date and time that can be in any time zone. When you call TimeZoneInfo.ConvertTimeToUtc(dt, TimeZoneInfo.Local), you are telling it which time zone it starts in. So if you start in Central, you will get one answer, whereas if you start in Eastern, you will get an answer that is an hour earlier, UTC. Indeed, this is what your code shows.
There is a .ToUniversalTime() method for DateTime class
This is midnight
var dt = DateTime.Parse("1/1/2013");
Midnight in eastern and central is not the same absolute time.
That is the whole purpose of time zones.
You can use NodaTime :
static string LocalTimeToUTC(string timeZone, string localDateTime)
{
var pattern = LocalDateTimePattern.CreateWithInvariantCulture("dd/MM/yyyy HH:mm:ss");
LocalDateTime ldt = pattern.Parse(localDateTime).Value;
ZonedDateTime zdt = ldt.InZoneLeniently(DateTimeZoneProviders.Tzdb[timeZone]);
Instant instant = zdt.ToInstant();
ZonedDateTime utc = instant.InUtc();
string output = utc.ToString("dd/MM/yyyy HH:mm:ss", CultureInfo.InvariantCulture);
return output;
}
When you have trouble with converting to local time to UTC then just remove the last keyword of index and then convert to UtcDateTime
NewsDate = DateTimeOffset.Parse(data.NewsDate.Remove(data.NewsDate.LastIndexOf("IST"))).UtcDateTime;

How to convert string to local Date Time?

I am trying to convert a string of this format:
MM/dd/yyyy HH:mm
The input is from a US database, so, i.e.:
09/20/2010 14:30
I know that my string is always US time but when I display it, I need to translate that into the local time, so that string should be turned into:
09/20/2010 19:30 (for UK for instance)
I tried a few things but nothing seems to give me the correct solution when I run on a US machine vs a UK or Ge machine
I tried:
CompletedDttm = DateTime.ParseExact(value, "MM/dd/yyyy HH:mm", CultureInfo.CurrentCulture);
CompletedDttm = DateTime.ParseExact(value, "MM/dd/yyyy HH:mm", new CultureInfo("en-US"));
They all work locally (US machine) but they don't convert the time to local time on a European machine.
Thanks
Tony
Try this - it converts local time (input in US format) to GMT and then prints in GB/DE format.
var zones = TimeZoneInfo.GetSystemTimeZones(); // retrieve timezone info
string value = "09/20/2010 14:30";
DateTime CompletedDttm = DateTime.ParseExact(value, "MM/dd/yyyy HH:mm",
new CultureInfo("en-US"));
DateTime FinalDttm = TimeZoneInfo.ConvertTime(CompletedDttm,
TimeZoneInfo.FindSystemTimeZoneById("Eastern Standard Time"),
TimeZoneInfo.FindSystemTimeZoneById("GMT Standard Time"));
string output = FinalDttm.ToString(new CultureInfo("en-GB"));
FinalDttm = TimeZoneInfo.ConvertTime(CompletedDttm, TimeZoneInfo.Local,
TimeZoneInfo.FindSystemTimeZoneById("W. Europe Standard Time"));
output = FinalDttm.ToString(new CultureInfo("de-DE"));
Output is, in turn:
20/09/2010 19:30:00
20.09.2010 20:30:00
UPDATE: You have to know the timezone of the data (not just that it is "US") as well as the interpreting machine if you want to reliably convert it to anything else. You're not only looking at hours offset, but DST also which varies by location (not all locales abide by it). Eastern is either -4 or -5 depending on the time of year. And if the date is old enough you run into the issue that "summer" dates were changed recently.
Your best course is to ALWAYS store timestamps in UTC. Aside from that, you can just make guesses about the offset.
You should be working with UTC times (the new, slightly different, version of GMT) if you want to be converting to other time zones.
DateTime dt = new DateTime(DateTime.Parse('2010-10-06 19:40').Ticks, DateTimeKind.Local);
dt.AddHours(5);
dt.ToLocalTime();
You could also make use of TimeZoneInfo which will have DST information also.
Unless you specify otherwise, the parse will assume you mean to parse the string into your current timezone. US culture just means the expected format of the string, and has nothing to do with the timezone (for example, in the US it could be EST or it could be PST).
Your string contains no timezone information, so naturally you're going to get your value in whatever the local timezone is. You can either:
Add the timezone info
Change the timezone afterwards
I think it's a display problem, but need more info to be sure. Try displaying the dates in yyyy-MM-dd format in both cases to check if the problem is on parse or display. You can create a custom format info object if you know exactly what you want to accept or display:
public static DateTimeFormatInfo GetISOFormatInfo()
{
DateTimeFormatInfo dtFormat = new DateTimeFormatInfo();
dtFormat.DateSeparator = "-";
dtFormat.TimeSeparator = ":";
dtFormat.ShortDatePattern = "yyyy-MM-dd";
dtFormat.ShortTimePattern = "HH:mm:ss";
return dtFormat;
}
Using a Date without TimeZone information, you will not be able to know the UK time / Canada time etc... since you do not know who (which part of the world) instered that time. Since you specifically said that the time is US time, you can add the time difference for the different parts of the world to display the local time.
You could use string.Split. first with the '/' separator on the whole string. You will get "09" "20" and "2010 14:30" then apply the split 2 more times with ' ' and ':'

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