ParseExact string to DateTime - c#

I try to parse my string to datetime, but I get a FormatException.
string date = "27.02.2017 13:03:16 Uhr";
action.Date =
DateTime.ParseExact(date, "dd.MM.yyyy HH:mm:ss",CultureInfo.InvariantCulture);
Does somebody has any idea?

You have to escape Uhr suffix:
string date = "27.02.2017 13:03:16 Uhr";
action.Date = DateTime.ParseExact(date, "dd.MM.yyyy HH:mm:ss 'Uhr'",
CultureInfo.InvariantCulture);

The problem is the "Uhr" at the end of the input. If you specify your format like this, the input must match the format.
After some people add "Uhr" and some people don't, I recommend to extract the relevant part using a regex.
using System.Text.RegularExpressions;
Match m = Regex.Match( #"/([\d]{2}\.[\d]{2}\.[\d]{4} +[\d]{2}\:[\d]{2}\:[\d]{2})/", date);
if (m != null)
date = m.Groups[0].Value;
else
// Something wrong with the input here
And then (unless m is null) you can use this string as a valid input for your ParseExact-part in most cases. But be aware that the regex does not perform any range-checks, so an input like Montag, 99.99.9999 99:99:99 Uhr would lead to the date string 99.99.9999 99:99:99 which matches the regex, but is not a valid DateTime anyway.

Related

Dateformat is right but getting String was not recognized as a valid DateTime

My dateformat is dd/MM/yyyy.
I have a date column in my file with values like 1/08/2019 to 31/08/2019.
But I'm getting the following error when processing that file:
System.FormatException: String was not recognized as a valid DateTime.
at System.DateTimeParse.ParseExact(String s, String format, DateTimeFormatInfo dtfi, DateTimeStyles style)
You've specified in your format string that the days and months must be double digits, but it appears that your input can be single digits.
In order to solve this, you need to specify a single digit in the format string by using a single d for the day portion (and a single M for the month, too).
It's also safe to use a single digit in the format string, since it will handle both single and double digits.
So your format string should look like: "d/M/yyyy"
For example, these all work:
var a = DateTime.ParseExact("1/8/2019", "d/M/yyyy", CultureInfo.CurrentCulture);
var b = DateTime.ParseExact("1/08/2019", "d/M/yyyy", CultureInfo.CurrentCulture);
var c = DateTime.ParseExact("01/8/2019", "d/M/yyyy", CultureInfo.CurrentCulture);
var d = DateTime.ParseExact("01/08/2019", "d/M/yyyy", CultureInfo.CurrentCulture);
difficult to say as you show the error but not the actual code, as you have dates in your file of differennt format, like d/MM/yyyy and dd/MM/yyyy try to use TryParse instead of ParseExact and if the TryParse fails with one format ( d/MM/yyyy ), then do another TryParse with the second format ( dd/MM/yyyy ) that way you should be able to cover both cases.
Again, without seeing the code it is difficult to give more detailed feedback.
also you could use an approach with TryParseExact and multiple format strings, like shown here:
var formatStrings = new string[] { "MM/dd/yyyy hh:mm:ss tt", "yyyy-MM-dd hh:mm:ss" };
if (DateTime.TryParseExact(dt, formatStrings, enUS, DateTimeStyles.None, out dateValue))
return dateValue;
see this SO answer: https://stackoverflow.com/a/17859959/559144

DateTime TryParseExact and padding

I'm calling TryParse on a string that I want to parse as a DateTime. Simple stuff. And it all works when the format is as I'd expect. But when each component/some of the components of the date are a single figure, the parse fails.
Example:
var dateFormat = "yyyy-dd-MM hh:mm:ss";
var dateString = "2006-4-1 2:3:5";
DateTime.TryParseExact(dateString, dateFormat,
CultureInfo.InvariantCulture, DateTimeStyles.None, out result)
If I change my dateString to "2006-04-01 02:03:05", it parses fine.
Question
How can I tell the parser to interpret 2 as 02 so that the above parses successfully?
What I've Tried
Manually padding each part of the date time to ensure it fits the format. This works, but it doesn't feel very elegant. Is this the only way?
I've also tried, with no success, to use a format like m instead of mm.
Just use
// please note single letters (d, M, h, m, s) whenever you allow single digits
var dateFormat = "yyyy-d-M h:m:s";
And you'll get it:
var dateString = "2006-4-1 2:3:5";
DateTime.TryParseExact(dateString, dateFormat,
CultureInfo.InvariantCulture, DateTimeStyles.None, out result)
With regular expression:
int[] n = new Regex("[^0-9]+").Split("2006-4-1 2:3:5").Select(int.Parse).ToArray();
var datetime = new DateTime(n[0], n[1], n[2], n[3], n[4], n[5]);

Converting string to valid DateTime

I know there are allot of questions regarding this, but I've been trying all day to get this conversion to work and have had no luck when applying the answers to the same question posted here. Every time I try to Parse the string to a DateTime, I get a "String was not recognized as a valid DateTime" exception. If I use Convert.ToDateTime, I can get a Date back from my string, but I need the hh:ss as well.
Here is my simplified code that is ruining my day:
var test = "2015-05-08T05:00Z";
DateTime testTime = new DateTime();
//testTime = Convert.ToDateTime(test);
testTime = DateTime.ParseExact(test, "mm/DD/yyyy HH:ss",
System.Globalization.CultureInfo.InvariantCulture);
Console.WriteLine(testTime);
Why is this string not recognized as a valid DateTime when trying to convert?
All help is appreciated
Try this...
var test = "2015-05-08T05:00Z";
DateTime testTime = new DateTime();
testTime = DateTime.Parse(test, null, System.Globalization.DateTimeStyles.RoundtripKind);
Console.WriteLine(testTime);
Console.ReadLine();
Or even with DateTime.ParseExact()
var test = "2015-05-08T05:00Z";
DateTime testTime = new DateTime();
testTime = DateTime.ParseExact(test, "yyyy-MM-ddTHH:ssZ", System.Globalization.CultureInfo.InvariantCulture, DateTimeStyles.RoundtripKind);
Console.WriteLine(testTime);
Console.ReadLine();
Results:
The format string you are using ("mm/DD/yyyy HH:ss") doesn't match your input in any way.
Have you looked at the DateTime.ParseExact documentation? You could try something like this:
testTime = DateTime.ParseExact(test, "yyyy-MM-ddTHH:ssZ",
System.Globalization.CultureInfo.InvariantCulture,
System.Globalization.DateTimeStyles.AssumeUniversal);
A couple of notes:
There is no point in setting testTime = new DateTime() if you are going to parse it on the next line. Just drop that line entirely and use var testTime = DateTime.ParseExact(...);
Are you sure that HH:ss is what you want? That seems like a very strange way to write a time. HH:mm or mm:ss would make more sense.
You should fix your expected pattern and take the time zone into account.
If your need a DateTime of DateTimeKind.Local:
var date = DateTime.ParseExact("2015-05-08T05:00Z", "yyyy-MM-dd'T'HH:mm'Z'",
CultureInfo.InvariantCulture);
If your need a DateTime of DateTimeKind.Utc:
var date = DateTime.ParseExact("2015-05-08T05:00Z", "yyyy-MM-dd'T'HH:mm'Z'",
CultureInfo.InvariantCulture,
DateTimeStyles.AssumeUniversal
| DateTimeStyles.AdjustToUniversal);
You are doing an exact parse, which means that the parse format string must match exactly with your date literal string. But your parse format string in ParseExact
uses / instead of - in the test literal string.
has a space instead of the T in the test literal string
does not match Z at the end of your test literal string.
Further it is not in yyyy-MM-dd order of your test literal string.
#Shar1er80' s solution is nice and frees you from having to specify a correct parse format string for ParseExact. I'd recommend going with that.
However, if you want to use ParseExact, you need to do this:
testTime = DateTime.ParseExact(test, "yyyy-MM-ddTHH:ssZ",
System.Globalization.CultureInfo.InvariantCulture, System.Globalization.DateTimeStyles.AdjustToUniversal);
Note that I added a DateTimeStyle of AdjustToUniversal to ensure that your time is interpreted as UTC. The Z in the parse format string is just there to consume a Z. See https://stackoverflow.com/a/833143/49251 for more info on the issue of Z not actually being a part of the format string per se.

Convert unusual string to DateTime w/out foreach

Update My Solution:
var rowsToAdd = (from t in dtEntry.AsEnumerable().Cast<DataRow>()
let startDate = (
t.Field<string>("StartDate").Length > 0)
? DateTime.Parse(t.Field<string>("StartDate").Split(new Char [] {'('})[0], CultureInfo.InvariantCulture)
: DateTime.Today.AddMonths(-3)
where startDate > filterDate
select t);
Original Question:
I get a DateTime string from an external API that looks like this:
10/14/2014 8:30 AM (America/Los Angeles)
I have all the data in a datatable called dtEntry which I'm using below.
None of the built-in c# DateTime conversion functions seem to work. They all result in format exeptions. Does anyone know how I could do this? The other catch is that I'm using LINQ (see below).
DataRow[] rows = (from t in dtEntry.AsEnumerable().Cast<DataRow>()
let startDate = (
t.Field<string>("StartDate").Length > 0)
? DateTime.Parse(t.Field<string>("StartDate"))
: DateTime.Today.AddMonths(-3)
where startDate > filterDate
select t).ToArray();
Any ideas? I've got the ternary operator in there because I need to handle empty strings as well.
You can split your string based on space and then Take(3) elements from the result array, Join them back using string.Join and then use DateTime.ParseExact or DateTime.TryParseExact like:
string str = "10/14/2014 8:30 AM (America/Los Angeles)";
string newStr = string.Join(" ", str.Split().Take(3));
DateTime parsingDateTime;
if (!DateTime.TryParseExact(newStr, "M/d/yyyy h:mm tt", CultureInfo.InvariantCulture, DateTimeStyles.None,
out parsingDateTime))
{
//invalid datetime
}
EDIT: You have to ignore (America/Los Angeles) part of string, otherwise there is no way for parsing using such string. You can find TimeZone for Region and then create DateTime for that parameter. See this: Get timezone by Country and Region
The accepted answer does not take into account the time zone part. My assumption here is the time zone is a standard time zone identifier which can be translated from the Unicode.org site. And based off this other SO Answer (.NET TimeZoneInfo from Olson time zone) which provides a helper method from the Unicode.org site, you can then parse the api time to your time:
string apiTime = "10/14/2014 8:30 AM (America/Los Angeles)";
int timeZoneStart = apiTime.IndexOf('(');
string timeZonePart = apiTime.Substring(timeZoneStart)
.Replace("(", string.Empty) // remove parenthesis
.Replace(")", string.Empty) // remove parenthesis
.Trim() // clear any other whitespace
.Replace(" ", "_"); // standard tz uses underscores for spaces
// (America/Los Angeles) will become America/Los_Angeles
string datePart = apiTime.Substring(0, timeZoneStart).Trim();
DateTime apiDate = DateTime.Parse(datePart);
TimeZoneInfo tzi = OlsonTimeZoneToTimeZoneInfo(timeZonePart);
DateTime apiDateTimeConverted = TimeZoneInfo.ConvertTime(apiDate, tzi);
The method above, OlsonTimeZoneToTimeZoneInfo, is from the SO answer linked above.

Regular expression for matching short date pattern in any culture

I need a custom regex to math short date pattern(etc. "M/dd/yyyy", "dd/mm/yyyy", "yyyy/mm/dd",...depend on culture..) then I can get day,month,year to parse that format like this:
string input = "03/24/2013";
Match m = Regex.Match(input, #"^(?<day>\d{1,2})/(?<month>\d{1,2})/(?<year>\d{4})$");
if( m.Success )
{
DateTime d = new DateTime(int.Parse(m.Groups["year"].Value),
int.Parse(m.Groups["month"].Value),
int.Parse(m.Groups["day"].Value));
}
but! this expression not support all various formats so
require :
Accept only '/' as separators.
Valid all short date pattern(Date only,also Time would be great) in various cultures (etc, en-US, th-TH, jp-JP,...). Is this possible, actually I just need to know which part is year, month or day but I couldn't find it anywhere. Please help me...
Valid common range: day [1-31]{1-2}, month [1-12]{1-2}, year[1600-9999]{4}
As Jim and I suggested, you can just iterate over all cultures:
foreach (var culture in CultureInfo.GetCultures(CultureTypes.SpecificCultures))
{
DateTime result;
if (DateTime.TryParseExact(text, "d", culture, DateTimeStyles.None,
out result))
{
// Valid - return, or whatever
}
}
Note that "d" is the standard format string for a short date pattern. Alternatively, you could use culture.DateTimeFormat.ShortDatePattern.

Categories