Parse date with time zone, skip timezone - c#

I try to parse date from string which contains time zone information. Input string is 2014-12-17T08:05:39+00:00.
I use DateTime.Parse() method which return me 2014-12-17 09:05:39 (one hour was added). I live in UTC+1:00 (Warsaw), so .NET adopt this date to my local time.
My question is how to use the parse method while skipping time zone, for example for 2014-12-17T08:05:39+00:00 I want to get 2014-12-17 08:05:39.

I would recommend parsing it as a DateTimeOffset instead of as a DateTime. You can then get the DateTime out of that, but it separates the "parsing the data you've been given" step from the "only using the bits I want from that" step.
It's possible that there are ways to make DateTime.Parse behave the way you want using DateTimeStyles - and I'm surprised it's converting to a "local" kind automatically anyway - but using DateTimeOffset will make it clearer.
(Of course I'd really recommend using Noda Time instead, parsing to an OffsetDateTime and then getting the LocalDateTime out of that, but that's a different matter...)

If you remove the part specifying time zone in input string then it parses directly without adjusting to local time. The date.Kind is then Unspecified.
var input = "2014-12-17T08:05:39";
var date = DateTime.Parse(fixedInput);
Although this works you might want to have a look on NodaTime as well.

You should try using DateTimeOffset instead of the DateTime
DateTimeOffset result = DateTimeOffset.Parse("2014-12-17T08:05:39+00:00", CultureInfo.InvariantCulture);
it gives you : 12/17/2014 8:05:39 AM +00:00

Related

How to strip timezone from DateTime in .NET Core

I have a use case that I'm not sure how to solve in a nice way.
I'm currently developing a .Net Core WebApi that is receiving data from various current systems, from a cross the whole world. Which I then process and lastly I commit it to SAP through oData endpoint.
The problem I'm having is on of parameters I'm receiving in the body payload, is a DateTime. Previous I have not have any issues. But not long ago I started getting data from a other system which deliverers it in a slightly differently way.
Previously this was the format I got: 2020-09-16T16:30:00 not problem with it. But the new system looks like this: 2020-09-16T16:00:00 -05:00 Could also end in +08:00.
The problem I'm facing is that SAP needs to get in local time. But in the my code it converts this: 2020-09-16T16:00:00 -05:00 to 2020-09-16T23:00:00 when I see the incoming payload in the controller.
I have searched quite a bit to find a solution. But 99% only suggest using UTC time, which is not a option for me.
Another option is to use DateTimeOffset, which I have tried but can't the time conversion to use localTime.
My question is. Are it not possible to custom convert to strip the timezone before it hits the controller?
Generarally when you're working with datetime data that includes offsets for time zone the DateTimeOffset type is a good place to start. The sample string 2020-09-16T16:00:00 -05:00 can be passed to DateTimeOffset.Parse() to get a correct DTO value with timezone information attached. From there you can get the local time, UTC time or a DateTime value with the timezone stripped.
string source = "2020-09-16T16:00:00 -05:00";
string fmt = #"yyyy-MM-dd\THH:mm:ss zzz"
// Same as input
Console.WriteLine(DateTimeOffset.Parse(source).ToString(fmt));
// Adjusted to your local timezone
Console.WriteLine(DateTimeOffset.Parse(source).ToLocalTime().ToString(fmt));
// DateTime portion of the source, timezone offset ignored
Console.WriteLine(DateTimeOffset.Parse(source).DateTime.ToString());
Getting the UTC time is simple too via the UtcDateTime property.
It sounds like what you want is the last one - just the date and time from the inputt string with the timezone offset stripped. If you just want the corresponding local time then DateTime.Parse should give that to you directly.
The JsonSerializer class doesn't support this format for DateTimeOffset so you might have some trouble getting it converted before hitting your controller. In that case you'd need to accept a string and do the conversion by hand in your code. You also might need to investigate the TryParseExact method.
Use DateTime.Parse() , for example
string timeInString1 = "2020-09-16T16:00:00 -05:00";
DateTime moment1 = DateTime.Parse(timeInString1);
string timeInString2 = "2020-09-16T16:00:00 +08:00";
DateTime moment2 = DateTime.Parse(timeInString2);
string timeInString3 = "2020-09-16T16:30:00";
DateTime moment3 = DateTime.Parse(timeInString3);
but momen1, momen2, or moment3 is non-timezone awareness value.

Is there functionality to convert from UTC time to local time using country name? [duplicate]

We are developing a C# application for a web-service client. This will run on Windows XP PC's.
One of the fields returned by the web service is a DateTime field. The server returns a field in GMT format i.e. with a "Z" at the end.
However, we found that .NET seems to do some kind of implicit conversion and the time was always 12 hours out.
The following code sample resolves this to some extent in that the 12 hour difference has gone but it makes no allowance for NZ daylight saving.
CultureInfo ci = new CultureInfo("en-NZ");
string date = "Web service date".ToString("R", ci);
DateTime convertedDate = DateTime.Parse(date);
As per this date site:
UTC/GMT Offset
Standard time zone: UTC/GMT +12 hours
Daylight saving time: +1 hour
Current time zone offset: UTC/GMT +13 hours
How do we adjust for the extra hour? Can this be done programmatically or is this some kind of setting on the PC's?
For strings such as 2012-09-19 01:27:30.000, DateTime.Parse cannot tell what time zone the date and time are from.
DateTime has a Kind property, which can have one of three time zone options:
Unspecified
Local
Utc
NOTE If you are wishing to represent a date/time other than UTC or your local time zone, then you should use DateTimeOffset.
So for the code in your question:
DateTime convertedDate = DateTime.Parse(dateStr);
var kind = convertedDate.Kind; // will equal DateTimeKind.Unspecified
You say you know what kind it is, so tell it.
DateTime convertedDate = DateTime.SpecifyKind(
DateTime.Parse(dateStr),
DateTimeKind.Utc);
var kind = convertedDate.Kind; // will equal DateTimeKind.Utc
Now, once the system knows its in UTC time, you can just call ToLocalTime:
DateTime dt = convertedDate.ToLocalTime();
This will give you the result you require.
I'd look into using the System.TimeZoneInfo class if you are in .NET 3.5. See http://msdn.microsoft.com/en-us/library/system.timezoneinfo.aspx. This should take into account the daylight savings changes correctly.
// Coordinated Universal Time string from
// DateTime.Now.ToUniversalTime().ToString("u");
string date = "2009-02-25 16:13:00Z";
// Local .NET timeZone.
DateTime localDateTime = DateTime.Parse(date);
DateTime utcDateTime = localDateTime.ToUniversalTime();
// ID from:
// "HKEY_LOCAL_MACHINE\Software\Microsoft\Windows NT\CurrentVersion\Time Zone"
// See http://msdn.microsoft.com/en-us/library/system.timezoneinfo.id.aspx
string nzTimeZoneKey = "New Zealand Standard Time";
TimeZoneInfo nzTimeZone = TimeZoneInfo.FindSystemTimeZoneById(nzTimeZoneKey);
DateTime nzDateTime = TimeZoneInfo.ConvertTimeFromUtc(utcDateTime, nzTimeZone);
TimeZone.CurrentTimeZone.ToLocalTime(date);
DateTime objects have the Kind of Unspecified by default, which for the purposes of ToLocalTime is assumed to be UTC.
To get the local time of an Unspecified DateTime object, you therefore just need to do this:
convertedDate.ToLocalTime();
The step of changing the Kind of the DateTime from Unspecified to UTC is unnecessary. Unspecified is assumed to be UTC for the purposes of ToLocalTime: http://msdn.microsoft.com/en-us/library/system.datetime.tolocaltime.aspx
I know this is an older question, but I ran into a similar situation, and I wanted to share what I had found for future searchers, possibly including myself :).
DateTime.Parse() can be tricky -- see here for example.
If the DateTime is coming from a Web service or some other source with a known format, you might want to consider something like
DateTime.ParseExact(dateString,
"MM/dd/yyyy HH:mm:ss",
CultureInfo.InvariantCulture,
DateTimeStyles.AssumeUniversal | DateTimeStyles.AdjustToUniversal)
or, even better,
DateTime.TryParseExact(...)
The AssumeUniversal flag tells the parser that the date/time is already UTC; the combination of AssumeUniversal and AdjustToUniversal tells it not to convert the result to "local" time, which it will try to do by default. (I personally try to deal exclusively with UTC in the business / application / service layer(s) anyway. But bypassing the conversion to local time also speeds things up -- by 50% or more in my tests, see below.)
Here's what we were doing before:
DateTime.Parse(dateString, new CultureInfo("en-US"))
We had profiled the app and found that the DateTime.Parse represented a significant percentage of CPU usage. (Incidentally, the CultureInfo constructor was not a significant contributor to CPU usage.)
So I set up a console app to parse a date/time string 10000 times in a variety of ways. Bottom line:
Parse() 10 sec
ParseExact() (converting to local) 20-45 ms
ParseExact() (not converting to local) 10-15 ms
... and yes, the results for Parse() are in seconds, whereas the others are in milliseconds.
I'd just like to add a general note of caution.
If all you are doing is getting the current time from the computer's internal clock to put a date/time on the display or a report, then all is well. But if you are saving the date/time information for later reference or are computing date/times, beware!
Let's say you determine that a cruise ship arrived in Honolulu on 20 Dec 2007 at 15:00 UTC. And you want to know what local time that was.
1. There are probably at least three 'locals' involved. Local may mean Honolulu, or it may mean where your computer is located, or it may mean the location where your customer is located.
2. If you use the built-in functions to do the conversion, it will probably be wrong. This is because daylight savings time is (probably) currently in effect on your computer, but was NOT in effect in December. But Windows does not know this... all it has is one flag to determine if daylight savings time is currently in effect. And if it is currently in effect, then it will happily add an hour even to a date in December.
3. Daylight savings time is implemented differently (or not at all) in various political subdivisions. Don't think that just because your country changes on a specific date, that other countries will too.
#TimeZoneInfo.ConvertTimeFromUtc(timeUtc, TimeZoneInfo.Local)
Don't forget if you already have a DateTime object and are not sure if it's UTC or Local, it's easy enough to use the methods on the object directly:
DateTime convertedDate = DateTime.Parse(date);
DateTime localDate = convertedDate.ToLocalTime();
How do we adjust for the extra hour?
Unless specified .net will use the local pc settings. I'd have a read of: http://msdn.microsoft.com/en-us/library/system.globalization.daylighttime.aspx
By the looks the code might look something like:
DaylightTime daylight = TimeZone.CurrentTimeZone.GetDaylightChanges( year );
And as mentioned above double check what timezone setting your server is on. There are articles on the net for how to safely affect the changes in IIS.
In answer to Dana's suggestion:
The code sample now looks like:
string date = "Web service date"..ToString("R", ci);
DateTime convertedDate = DateTime.Parse(date);
DateTime dt = TimeZone.CurrentTimeZone.ToLocalTime(convertedDate);
The original date was 20/08/08; the kind was UTC.
Both "convertedDate" and "dt" are the same:
21/08/08 10:00:26; the kind was local
I had the problem with it being in a data set being pushed across the wire (webservice to client) that it would automatically change because the DataColumn's DateType field was set to local. Make sure you check what the DateType is if your pushing DataSets across.
If you don't want it to change, set it to Unspecified
I came across this question as I was having a problem with the UTC dates you get back through the twitter API (created_at field on a status); I need to convert them to DateTime. None of the answers/ code samples in the answers on this page were sufficient to stop me getting a "String was not recognized as a valid DateTime" error (but it's the closest I have got to finding the correct answer on SO)
Posting this link here in case this helps someone else - the answer I needed was found on this blog post: http://www.wduffy.co.uk/blog/parsing-dates-when-aspnets-datetimeparse-doesnt-work/ - basically use DateTime.ParseExact with a format string instead of DateTime.Parse
This code block uses universal time to convert current DateTime object then converts it back to local DateTime. Works perfect for me I hope it helps!
CreatedDate.ToUniversalTime().ToLocalTime();

getting hour part and time-zone part from datetime

I had a string in config file, defining date time with time zone.
I am not able to get this value, while reading values from config file.
In config file:
Setting name="abcdefgh" value="2012-08-10T22:00:00-08:00"
In C#, I am reading this as follows:
DateTime StartDate;
StartDate = DateTime.ParseExact(RoleEnvironment.GetConfigurationSettingValue("abcdefgh"), "yyyy-MM-dd HH:mm:ss", null);
Configuration.Instance.abcdefgh= StartDate;
In start date, i am getting 11 Aug, 2012 11:30:00, with no time zone.
I want to read it as it is. also tell, if my format of writing datetime in config file is correct
MSDN link to DateTimeOffset.
Use DateTimeOffset whenever you are referring to an exact point in
time. For example, use it to calculate "now", transaction times, file
change times, logging event times, etc. If the time zone is not
known, use it with UTC. These uses are much more common than the
scenarios where DateTime is preferred, so this should be considered
the default.
var date = DateTimeOffset.Parse("2012-08-10T22:00:00-08:00");
date.Offset // -08:00:00, offset from Coordinated Universal Time (UTC)
date.DateTime // 10/08/2012 22:00:00,
DateTime doesn't keep information about timezone. To parse the string and keep information about timezone - you should use DateTimeOffset structure.
Use the DateTimeOffset structure (and DateTimeOffset.ParseExact) if you want to store timezone information.
Your ParseExact format also doesn't quite match the setting value: it should have a zz at the end for the timezone information. You can also use DateTimeOffset.Parse since your setting string is in a standard format.
It's a standard format, so the ParseExact isn't needed, try:
StartDate = DateTime.Parse(RoleEnvironment.GetConfigurationSettingValue("abcdefgh"));
I substituted the hard-coded value you provided and got the correct result for my timezone (GMT-4) as
8/11/2012 2:00 AM
Note: as others mentioned, the timezone is not retained, so you will get the correct localized time corresponding to whatever timezone information was in the string, but you won't be able to find out what timezone that was. The DateTime.Kind property will reflect that it's a local time.

How to convert Datetimes into UTC based timing values to compare timings- C#

I've string (variable is fileDate) with Date values in the following format:
2/12/2011 11:58 AM
Now I want to convert this to a date and then to UTC time based as I've problems in comparing dates in different machines, so *I always want to convert all strings (which are getting compared) to Utc_date values.*
I tried this code below but it did not work as I'm not able to convert the above string to Datetime based (as it does not have seconds).
DateTime date = Convert.ToDateTime(fileDate);
date = DateTime.SpecifyKind(date, DateTimeKind.Utc);
fileDate = date.ToString("MM/dd/yyyy hh:mm tt");
Above did not work showing FormatException.
Can you pl help?
To start with, I'd suggest using DateTime.ParseExact or TryParseExact - it's not clear to me whether your sample is meant to be December 2nd or February 12th. Specifying the format may well remove your FormatException.
The next problem is working out which time zone you want to convert it with - are you saying that 11:58 is a local time in some time zone, or it's already a UTC time?
If it's a local time in the time zone of the code which is running this, you can use DateTimeStyles.AssumeLocal | DateTimeStyles.AdjustToUniversal to do it as part of parsing.
If it's already a universal time, use DateTimeStyles.AssumeUniversal
If it's a local time in a different time zone, you'll need to use TimeZoneInfo to perform the conversion.
Also, if it's a local time you'll need to consider two corner cases (assuming you're using a time zone which observes daylight saving time):
A local time may be skipped due to DST transitions, when the clocks go forward. So if the clocks skip from 1am to 2am, then 1:30am doesn't exist at all.
A local time may be ambiguous due to DST transitions, when the clocks go back. So if the clocks go back from 2am to 1am, then 1:30am occurs twice at different UTC times - which occurrence are you interested in?
You should decide how you want to handle these cases, and make sure they're covered in your unit tests.
Another option is to use my date and time library, Noda Time, which separates the concepts of "local date/time" and "date/time in a particular time zone" (and others) more explicitly.
you should be using DateTime.ParseExact to get the value into a proper DateTime instance, and then you can use .ToUniversalTime() to get the UTC time (this would be with respect to the difference of time as in your server machine)
you can use :
DateTime.Now.ToUniversalTime();
i don't mean to say to you should use "DateTime.Now" but you get the point that as a part of the DateTime object you have a method to transform it to Universal time
http://msdn.microsoft.com/en-us/library/system.datetime.touniversaltime.aspx

Change date to Universal Time Format changes my date wrongly I can't get error

I am trying to simply change the date format from the datatable to universal time format but it formats it wrongly as if I have date for August 7 it changed it to August 8 after formatting it to universal date time. My code for formatting date is,
DateVar[runs] = DateTime.Parse(Convert.ToString(output.Tables[0].Rows[runs][0])).ToUniversalTime().ToString();
Don't get in to code its correct and its a part of loop so "run" is loop and output is data set having one table I have first data in table is "Sunday, August 07, 2011 10:52 PM" and it was converted to "8/8/2011 5:52:00 AM" after implementing universal time format.
Hopes for your suggestions
Universal time isn't a format - it's a time zone, effectively. It's not clear what you're trying to do, but converting a "local" DateTime to "universal" DateTime will usually change the time. If you don't want that to happen, don't call ToUniversalTime.
It's a pity that the .NET date/time API isn't as clear as it could be - the DateTime type itself has some horrible ambiguities about it. I'm trying to improve the situation with my Noda Time project, but you will need to understand what time zones are about etc.
Personally I would suggest not using simply DateTime.Parse or just calling ToString unless you're absolutely sure that the default format is what you want. I usually call DateTime.ParseExact and specify the expected format (and usually CultureInfo.InvariantCulture unless it's a user-entered string) - and likewise I provide a format string to the ToString call.
In your code you're simply converting a string to a string - what are you attempting to accomplish? If you're just trying to change the format (e.g. to dd/MM/yyyyTHH:mm:ss) then you don't need to call ToUniversalTime but you do need to provide the format string.
I suggest you split your code out into several statements to help you debug this (and for general code clarity):
Fetch the string from the DataTable, if you really need to (if it's already a DateTime, there's no point in converting it to a string and then back again)
Parse the string (again, assuming you need to)
Perform any conversions you need to
Format the DateTime with an explicit format string
Now if any single operation is causing a problem, you can isolate it more easily.
If I run ToUniversalTime() from Greenwich it will give same time but if i do it while I live some where else it will get an offset date time object of + or - hours depending on position.

Categories

Resources