C# regex replacement - not able to use matched variables - c#

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");
}

Related

Converting a string to date in c#

from a file i read a string like this: "Nov 4 07:27:27 2022 GMT". I try to convert this to german Datetime, later it will be stored in a SQL-table.
Currently i do the conversion like this:
MyTmpString = "Nov 4 07:27:27 2022 GMT";
string format;
CultureInfo provider = CultureInfo.InvariantCulture;
format = "MMM d HH:mm:ss yyyy GMT";
try {
Datum_von = DateTime.ParseExact(MyTmpString, format, provider);
Console.WriteLine("{0} converts to {1}.", MyTmpString, Datum_von.ToString());
}
catch (FormatException) {
Console.WriteLine("{0} is not in the correct format.", MyTmpString);
}
This works for that specific case. I already run into problems if day as more than 1 digit. In this case i have to use a format like this:
format = "MMM dd HH:mm:ss yyyy GMT";
May be the string occurs in more variants currently i dont know. i dont want to create a format and try-catch for every possibility. Iam looking for a kind of universal conversionmethod to have a german date at the end.
What should i do here, do you have any recommendations?
Thank you,
Hans
As Hans Kesting suggests, ParseExact's -d format shouldn't care if days are 1 or 2 digits. Your problem is the extra spaces.
Also instead of relying on catching an exception, which is expensive performance-wise, you should use TryParseExact. It even has an option that allows you to ignore superfluous white space in the string:
var myTmpString = "Nov 14 07:27:27 2022 GMT";
// Or var myTmpString = "Nov 4 07:27:27 2022 GMT";
System.Globalization.CultureInfo provider = System.Globalization.CultureInfo.InvariantCulture;
string format = "MMM d HH:mm:ss yyyy GMT";
bool result = DateTime.TryParseExact(myTmpString, format, provider, System.Globalization.DateTimeStyles.AllowWhiteSpaces, out DateTime datum_von);
if (result)
{
Console.WriteLine("{0} converts to {1}.", myTmpString, datum_von.ToString());
}
else
{
Console.WriteLine("{0} is not in the correct format.", myTmpString);
}
If TryParseExact returns true, you can use the value from the out parameter, otherwise parsing has failed.

C# second DateTime.ParseExact check if first one has failed

I'm testing a piece of code to see if the rules will work each time, so I just made a short console application that has 1 string as an input value which I can replace at any time.
string titleID = "document for the period ended 31 March 2014";
// the other variation in the input will be "document for the period
// ended March 31 2014"
What I'm doing is I take a specific part from it (depending if it contains a specific word - nvm the details, there is a consistency so I don't worry about this condition). Afterwards I'm taking the rest of the string after a specific position in order to do a DateTime.ParseExact
Ultimately I need to figure out how to check if the first DateTime.ParseExact has failed
to then perform a second attempt with a different custom format.
This is how it looks like:
if(titleID.Contains("ended "))
{
// take the fragment of the input string after the word "ended"
TakeEndPeriod = titleID.Substring(titleID.LastIndexOf("ended "));
// get everything after the 6th char -> should be "31 March 2014"
GetEndPeriod = TakeEndPeriod.Substring(6);
format2 = "dd MMMM yyyy"; // custom date format which is mirroring
// the date from the input string
// parse the date in order to convert it to the required output format
try
{
DateTime ModEndPeriod = DateTime.ParseExact(GetEndPeriod, format2, System.Globalization.CultureInfo.InvariantCulture);
NewEndPeriod = ModEndPeriod.ToString("yyyy-MM-ddT00:00:00Z");
// required target output format of the date
// and it also needs to be a string
}
catch
{
}
}
// show output step by step
Console.WriteLine(TakeEndPeriod);
Console.ReadLine();
Console.WriteLine(GetEndPeriod);
Console.ReadLine();
Console.WriteLine(NewEndPeriod);
Console.ReadLine();
Everything works fine until I try a different input string, f.eg. "document for the period ended March 31 2014"
So in this case if wanted to parse "March 31 2014" I'd have to switch my custom format to
"MMMM dd yyyy" and I do that and it works, but I cannot figure out how to check if the first parse fails in order to perform the second one.
First parse - > success -> change format and .ToString
|-> check if failed , if true do second parse with different format -> change format and .ToString
I've tried
if (String.IsNullOrEmpty(NewEndPeriod))
{ do second parse }
Or
if (NewEndPeriod == null)
{ do second parse }
But I get a blank result at Console.WriteLine(NewEndPeriod);
Any ideas how to approach this?
** EDIT: **
Adding here an alternative answer I got which is using Parse instead of TryParseExact, since Parse will handle both of the format variations without the need to specify them
DateTime DT = DateTime.Parse(GetEndPeriod);
//The variable DT will now have the parsed date.
NewEndPeriod = DT.ToString("yyyy-MM-ddT00:00:00Z");
but I cannot figure out how to check if the first parse fails in order
to perform the second one
Instead of DateTime.ParseExact use DateTime.TryParseExact that will return a bool indicating if parsing was successful or not.
DateTime ModEndPeriod;
if (!DateTime.TryParseExact(GetEndPeriod,
format,
CultureInfo.InvariantCulture,
DateTimeStyles.None,
out ModEndPeriod))
{
//parsing failed
}
You can also use multiple formats for parsing using the DateTime.TryParse overload which takes an array of formats:
string[] formatArray = new [] { "dd MMMM yyyy","MMMM dd yyyy"};
DateTime ModEndPeriod;
if (!DateTime.TryParseExact(GetEndPeriod,
formatArray,
CultureInfo.InvariantCulture,
DateTimeStyles.None,
out ModEndPeriod))
{
//parsing failed
}

Convert Date Formatting Codes to date

The user is supposed to enter date in format: %m %d %Y
What I need to do is convert the date to: 11 11 2013 ( which is today`s date). I have not worked much with dates. Is there some method that does this conversion out of the box? I looked through DateTime options but couldn't find what I need.
Edit:
From the answers received it seems that it is not very clear what I am asking.
In our software the user can insert dates in format like this:
http://ellislab.com/expressionengine/user-guide/templates/date_variable_formatting.html
I am trying to parse this user input and return the today date. So from the link above:
%m - month - “01” to “12”
%d - day of the month, 2 digits with leading zeros - “01” to “31”
%Y - year, 4 digits - “1999”
I was wondering if there is a method that takes %m %d %Y as an input and returns the corresponding today date in the specified format ( which is 11 11 2013 today). Or at least something close to that.
Hope it is more clear now.
EDIT 2:
After digging a little bit more I found that what I am looking for is an equivalent of C++ strftime in C#.
http://www.cplusplus.com/reference/ctime/strftime/
But for some reason I cannot see an example this to implemented in C#.
You can use DateTime.TryParseExact to parse a string to date and DateTime-ToString to convert it back to string with your desired format:
DateTime parsedDate;
if (DateTime.TryParseExact("11 11 2013", "MM dd yyyy", System.Globalization.CultureInfo.InvariantCulture, System.Globalization.DateTimeStyles.None, out parsedDate))
{
// parsed successfully, parsedDate is initialized
string result = parsedDate.ToString("MM dd yyyy", System.Globalization.CultureInfo.InvariantCulture);
Console.Write(result);
}
My go-tos for DateTime Input and Output:
http://www.dotnetperls.com/datetime-parse for input (parsing)
http://www.csharp-examples.net/string-format-datetime/ for output (formatting)
string dateString = "01 01 1992";
string format = "MM dd yyyy";
DateTime dateTime = DateTime.ParseExact(dateString, format, CultureInfo.InvariantCulture);
Edit since his edit makes my above answer irrelevant (but will leave there for reference):
From what you're saying, you want to output today's date in a dynamically-defined format?
So if I want to see month, date, year, I say "MM dd YY" and you return it to me?
If so:
DateTime dt = DateTime.Today; // or initialize it as before, with the parsing (but just a regular DateTime dt = DateTime.Parse() or something quite similar)
Then
String formatString = "MM dd YY";
String.Format("{0:"+ formatString+"}", dt);
Your question is still quite unclear, though.
Use ParseExact:
var date = DateTime.ParseExact("9 1 2009", "M d yyyy", CultureInfo.InvariantCulture);

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.

How to parse date from string?

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

Categories

Resources