How to parse date from string? - c#

I want to parse the date from the string where date formate can be any of different format.
Now to match date we can use DateTime.TryParseExact and we can define format as we needed and date will be matched for any different format.
string[] formats = {"MMM dd yyyy"};
DateTime dateValue;
string dateString = "May 26 2008";
if (DateTime.TryParseExact(dateString, formats,
new CultureInfo("en-US"),
DateTimeStyles.None,
out dateValue))
MessageBox.Show(dateValue.ToString());
This matches with date.But this is not working for parse the date from the string that is it does not matched with the date which is in some string.
Like
if the date is "May 26 2008" then we can define format "MMM dd yyyy" and date will be matched.
But if date is in some string like "Abc May 26 2008" then date will not be matched.So for that can we use regular expression here ? If yes how ?
The string from I want to parse the date, is parsed from the html page and the string can be any different.
EDIT : I want to write the format like which matches any string in which there is a date using regex.

You could do a regular expression match on something like #"[A-Za-z]{3} \d{2} \d{4}" and feed whatever matches into DateTime.TryParseExact. It might break for alternate cultures however, I'm not sure if there are languages around that have month names only 2 letters short or something :)
Alternatively, you could extract the month names from cultureInfo.DateTimeFormat.AbbreviatedMonthNames and use that to build a slightly better targeted regular expression. It should also work for other cultures.
Edit - here's an example:
string text = "Apr 03 2010 foo May 27 2008 bar";
CultureInfo ci = new CultureInfo("en-US");
Regex regex = new Regex(#"(?<date>(" + String.Join("|",
ci.DateTimeFormat.AbbreviatedMonthNames, 0, 12) + #") \d{2} \d{4})");
// Builds this regex:
// (?<date>(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec) \d{2} \d{4})
var matches = regex.Matches(text);
foreach (Match match in matches)
{
string capturedText = match.Groups["date"].Value;
DateTime dt;
if (DateTime.TryParseExact(capturedText, "MMM dd yyyy", ci,
DateTimeStyles.None, out dt))
{
Console.WriteLine(capturedText + ": " + dt.ToLongDateString());
}
}
// Prints two parsed dates in long format

If it's English only and the format is "MMM dd yyyy" you can search where your string is [January|February|...|December] day year.
But you should first ask yourself why you're parsing any string. Can you not force the user to use a predefined format and validate that input?

You can customize the format according to your needs:
private const string DateTimeFormat = "dd-MMM-yy hh.mm.ss.ffffff tt";
public static bool TryParseToDateTime(this string stringValue, out DateTime result)
{
if (String.IsNullOrEmpty(stringValue))
{
result = DateTime.MinValue;
return false;
}
return DateTime.TryParseExact(stringValue, DateTimeFormat, CultureInfo.InvariantCulture, DateTimeStyles.None, out result);
}
UPDATE:
You probably should use regular expressions to find strings that match date in text. You have to decide what date format you expect and write (or choose) an appropriate regular expression. For example, for "dd MMM yyyy" format you can use the following regular expressions:
^\d{2}\s{1}(Jan|Feb|Mar|Apr|May|Jun|Jul|Apr|Sep|Oct|Nov|Dec)\s{1}\d{4}$
by Stephen Lam from http://regexlib.com/REDetails.aspx?regexp_id=325
Alternatively you can browse this site to find appropriate expression.

If you know your date will start with a month then you can use substring to get that part. (Find occurence of Jan/Feb/ etc)

I think something like \w{3,8} \d\d \d\d\d\d[\s$] would work most of the time if it's in US format, but I wouldn't trust it too much if the text you're parsing could be just anything.

Here is the link to parse the date from the string which is very good.There is set of regex to parse the date from the string.
http://www.codeproject.com/KB/datetime/date_time_parser_cs.aspx

Related

Parsing a DateTimeOffset string in C#

I need parse datetimeoffsets from strings of multiple formats. One of the strings that fail is:
08/12/1992 07.00.00 -05:00
Now when I try to parse this, I use:
DateTimeOffset.ParseExact("08/12/1992 07.00.00 -05:00", "dd/MM/yyyy HH:mm:ss zzz", CultureInfo.InvariantCulture)
Which gives a FormatException:
"String was not recognized as a valid DateTime."
I can also try to add delimiters in the separators:
DateTimeOffset.ParseExact("08/12/1992 07.00.00 -05:00", "dd'/'MM'/'yyyy HH':'mm':'ss zzz", CultureInfo.InvariantCulture)
...or other permutations of small/capital letter or separators, but I get the same error.
Can anyone tell me why the ParseExact lines above do not work, and how to correct them?
EDIT: I tried using a LINQ query to replace the colon with dots (: -> .). Apparently that did not work correctly - thanks for the replies.
Your actual date (actually time) string delimits the hours from the minutes from the seconds with a dot ., so your format must do the same:
DateTimeOffset.ParseExact("08/12/1992 07.00.00 -05:00",
"dd/MM/yyyy HH.mm.ss zzz", CultureInfo.InvariantCulture)
// ^ ^
// | |
If you have multiple string formats in your data, you can do something like this:
public static DateTimeOffset Parse(string str)
{
string[] formats =
{
"dd/MM/yyyy HH.mm.ss zzz",
"dd/MM/yyyy HH:mm:ss zzz"
// ... possibly more ...
};
var dto = new DateTimeOffset();
if (!formats.Any(f => DateTimeOffset.TryParseExact(str, f, CultureInfo.InvariantCulture, DateTimeStyles.None, out dto)))
{
throw new ArgumentException("Unrecognized date format");
}
return dto;
}
In the statement
DateTimeOffset.ParseExact("08/12/1992 07.00.00 -05:00",
"dd/MM/yyyy HH:mm:ss zzz",
CultureInfo.InvariantCulture)
the format string uses : as separator for the time parts, but the data argument uses . as separator.

C# regex replacement - not able to use matched variables

I am trying to use regex in C# to edit string format.
Previous format is 09/08/2015 or 9/08/2015 and pattern I tried is "([0-9]{1,}|[0-9]{2,})/[0-9]{2,}/[0-9]{4,}"
New format should be 2015 08 09
I am trying to use variables from match, but it shows only $1 and not $2 or $3
string pattern = "([0-9]{1,}|[0-9]{2,})/[0-9]{2,}/[0-9]{3,}";
string replacement = "$3 $2 $1";
Regex rgx = new Regex(pattern);
string result = rgx.Replace(text, replacement);
richTextBox1.Text = result;
Please, help me to edit proper pattern format.
EDIT:
I just forget to write, that at first I am loading data from .txt file and in that data I am replacing date format 31/03/2015 or 1/03/02 to 2015 03 31.
Instead of regex, how about parsing them to DateTime and get their string representation with specific format? (I assumed your 09 is day number)
string s = "9/08/2015";
DateTime dt;
if(DateTime.TryParseExact(s, "d/MM/yyyy", CultureInfo.InvariantCulture,
DateTimeStyles.None, out dt))
{
dt.ToString("yyyy MM dd").Dump(); // 2015 08 09
}
or
string s = "09/08/2015";
DateTime dt;
if(DateTime.TryParseExact(s, "dd/MM/yyyy", CultureInfo.InvariantCulture,
DateTimeStyles.None, out dt))
{
dt.ToString("yyyy MM dd").Dump(); // 2015 08 09
}
Or DateTime.TryParseExact has an overload that takes format part as a string array which you can supply multiple formats.
var formats = new[] {"d/MM/yyyy", "d/MM/yyyy"};
if(DateTime.TryParseExact(s, formats, CultureInfo.InvariantCulture,
DateTimeStyles.None, out dt))
{
dt.ToString("yyyy MM dd").Dump(); // 2015 08 09
}
Because your regex has only one matching group. A correct one would be ([0-9]{1,2})/([0-9]{2})/([0-9]{4}).
The parentheses are used to mark the groups and you only marked the first one with them. Also your regexp is a bit incorrect, since it would also match 832947928/8237549875923/9999, which probably is not what you need.
In this form, it wants one or two numbers, slash, two numbers, slash and four numbers and does the conversion.
Note that using [0-9]{1,2} will allow invalid dates also, so it's not suitable for validation. Only for this conversion.
Much easier approach is to use .NET's inbuilt parser for dates. This will also ensure that invalid inputs like "99/99/0001" will fail.
DateTime res;
if (DateTime.TryParseExact(input, new [] {"dd/MM/yyyy", "MM/dd/yyyy"}, applicableCultureInfo, DateTimeStyles.None, out res)) {
return res.ToString("yyyy MM dd");
} else {
throw InvalidArgumentException("Unsupported date format");
}

Convert string into mm/dd/yyyy format

I have following strings in different formats:
16/05/2014
21-Jun-2014
2014-05-16
16-05-2014
5/19/2014
14 May 2014
I need to convert all the above strings into mm/dd/yyyy format in c#.
I have tried used DateTime.ParseExact as DateTime dt = DateTime.ParseExact("16-05-2014", "mm/dd/yyyy hh:mm:ss tt", CultureInfo.InvariantCulture) in C# but i am getting the exception as "String was not recognized as a valid DateTime".
I have also tried to use to Convert.ToDateTime() but it is also not working.
Is there any method or function that we can write/available in C# that would convert the above string formats into a single date format i.e into "mm/dd/yyyy" format ??
Any help on this would be greatly appreciated.
It fails on the very first term of your format string, which is telling the function to treat the "16" as minutes and to look for hours, minutes, and seconds that don't exist in the input.
You have several different date formats, and so need the ParseExact() overload that accepts several different format strings:
string[] formats= {"dd/MM/yyyy", "dd-MMM-yyyy", "yyyy-MM-dd",
"dd-MM-yyyy", "M/d/yyyy", "dd MMM yyyy"};
string converted = DateTime.ParseExact("16-05-2014", formats, CultureInfo.InvariantCulture, DateTimeStyles.None).ToString("MM/dd/yyyy");
Also remember that lower case "m"s are for minutes. If you want months, you need an upper case "M". Full documentation on format strings is here:
http://msdn.microsoft.com/en-us/library/8kb3ddd4.aspx
Finally, I suspect you are getting ahead of yourself on formatting the output as a string. Keep these values as DateTime objects for as long as possible, and only format to a string at the last possible moment before showing them to the user. If you really do want a string, at least stick with the ISO 8601 standard format.
Your main problem is that your format string is wrong. A small m is for minute, a big M is for month.
Try to pass all your formats in an array. For example like this
DateTime.ParseExact("16-05-2014",
new[] {"dd/MM/yyyy", "dd-MMM-yyyy", "yyyy-MM-dd",
"dd-MM-yyyy", "M/d/yyyy", "dd MMM yyyy"},
CultureInfo.InvariantCulture, DateTimeStyles.None);
With this you can parse all your formats at once.
For more information about the format settings, see the official docs.
Few things:
Your input date 16/05/2014 doesn't match your format Month/Day/Year - how can there be a 16th month?
Secondly, you're using mm which represents Minutes, not Months. You should use MM.
Finally, your sample string 16-05-2014 doesn't match the format provided, you've used hyphens - instead of forward slashes /
Supply a collection of different formats matching your input:
string[] formats = new [] { "MM/dd/yyyy", "dd-MMM-yyyy",
"yyyy-MM-dd", "dd-MM-yyyy", "dd MMM yyyy" };
DateTime dt = DateTime.ParseExact("05-16-2014", formats, CultureInfo.InvariantCulture, DateTimeStyles.None);
You might find the following method useful to accept whatever date format you want and convert it to DateTime:
public DateTime? DTNullable(string DateTimestring, string CurrDateTimeFormat)
{
if (string.IsNullOrEmpty(DateTimestring)) return null;
else
{
DateTime datetimeNotNull;
DateTime.TryParseExact(DateTimestring, CurrDateTimeFormat, null, System.Globalization.DateTimeStyles.None, out datetimeNotNull);
return datetimeNotNull;
}
}
Pass in your desired string to be converted to DateTime along with it's current date time format and this would return you a nullable DateTime. If you're certain that whatever string you're passing in won't be null then you can remove that bit. The reason for it being there is that you can't convert a null to DateTime. In my case I couldn't be certain if it would be or not so I needed the ability to capture nulls as well.
You can use it like this:
DateTime? MyDateTime = DTNullable(MyStartDate, "dd/MM/yyyy");
If you wanted you could alter the method to accept an array of strings and simply iterate through each and return them all in a list if they were of the same format.
As others have pointed out, months are MM not mm (minutes).
On a DateTime object you can call .ToString("MM/dd/yyyy"). Given the strings you have, you can first create new DateTime objects for each string and then call .ToString("MM/dd/yyyy"). For example:
var dateAsMmDdYyyy = DateTime.Now.ToString("MM/dd/yyyy");

How can I parse a DateTime from a string containing extra characters?

I have a string. The string is like this
Hello I am a Coder, My DOB is 12/09/2011.
I want to extract the date from this sentence. How do I do this using C#? I do not want regular expressions. This was an interview question asked to me recently.
This is my try
string myStr = "Hello 12/3/2013";
DateTime s;
DateTime.TryParse(myStr,out s);
Console.WriteLine(s);
I am getting the output as
01-01-0001 00:00:00
Both C# and JavaScript support regular expressions. You can use this pattern to find that section of the string:
\d{2}/\d{2}/\d{4}
Of course that doesn't ensure that it's a valid date, e.g. 13/88/0000 would match that pattern. You'd then have to parse the string using something like Date.Parse.
However, since you've stated regular expressions are not an option, here's a very crude one-liner:
var input = "Hello I am a Coder, My DOB is 12/09/2011.";
DateTime date = new DateTime();
input.Split().SkipWhile(s => !DateTime.TryParse(s, out date)).Any();
Console.WriteLine(date); // 12/9/2011 12:00:00 AM
Since you don't want to use REGEX, simply split the string on space and then use DateTime.TryParseExact to see if any string gets parsed as DateTime
string str = "Hello I am a Coder, My DOB is 12/09/2011";
string[] array = str.Split();//splits on space
string dateFormat = "M/d/yyyy"; //works with both single digit and double digit
//(day/month) for parsing
//or d/M/yyyy depending your date culture
DateTime tempDateTime;
var result = array.FirstOrDefault(r =>
DateTime.TryParseExact
(r,
dateFormat,
CultureInfo.InvariantCulture,
DateTimeStyles.NoCurrentDateDefault,
out tempDateTime));
Your result would contain the Date string, and your tempDateTime would contain the parsed DateTime.

Why does a call to DateTime.TryParseExact fail with input "1212012" using the format string "Mddyyyy"

I have a date string that is coming in as what I believe to be Mddyyyy. However, TryParseExact doesn't seem to be working. Here's the sample code that fails:
string datestring = "1212012";
DateTime td;
if (DateTime.TryParseExact(datestring, "Mddyyyy", new CultureInfo("en-US"), DateTimeStyles.None, out td))
{
Console.WriteLine(td.ToShortDateString());
}
else
{
Console.WriteLine("Invalid Date String");
}
That same code works if there's a leading zero, but I would think then that the leading zero would only work with a formatting string of MMddyyyy.
Here I propose an explanation and provide evidence for the proposal.
Proposed Explanation: The parser internally uses the format string to create a regular expression that contains a greedy quantifier (which means, in this case, it prefers to match 2-digit months over 1-digit months). The M in the OP's format string becomes something like \d{1,2} (though that would match months numbered from 0 to 99!) in the parser's internal regular expression.
Evidence: If you move the month to the end of both the data and the format string, the greedy quantifier cannot obtain more than 1 digit and so it matches the month as desired:
string datestring = "2120121";
DateTime td;
if (DateTime.TryParseExact(datestring, "ddyyyyM", new CultureInfo("en-US"), DateTimeStyles.None, out td))
{
Console.WriteLine(td.ToShortDateString());
}
else
{
Console.WriteLine("Invalid Date String");
}
Bottom Line: Don't rely on undocumented behavior. Always use unambiguous data, i.e., 2-digit months.

Categories

Resources