Using Regex convert dd/mm/yy into dd/mm/yyyy

1.7k views Asked by At

I'm using Regex and I want to convert dd/mm/yy into full dd/mm/yyyy.

For example. User enters his date of birth: 01/11/94
The program converts the year 94 into 1994.

Now if the user inserts date of birth: 01/11/09
The program converts the year 09 to 01/11/2009 because it can't be 1909. Unless you a vampire.

And now if the user inserts the date of birth: 01/11/15
The program let's the user to continue to type because its the current year. 2015. Incorporation of current date validity check function here would be necessary.

I have come this far but I need help making it fully functional. If you'd like to help, I can show you somewhat of the code I've created.

3

There are 3 answers

1
ΩmegaMan On

There are tools designed to do this which provide more value than regex processing.

The tool to use is DateTime with its ParseExact with the appropriate date format specifications to do the converstion.

Here are four examples with the result in the comment:

DateTime.ParseExact("01/02/15", "MM/dd/yy", CultureInfo.InvariantCulture)
        .ToString("MM/dd/yyyy"); // 01/02/2015

DateTime.ParseExact("01/02/93", "MM/dd/yy", CultureInfo.InvariantCulture)
        .ToString("MM/dd/yyyy"); // 01/02/1993

DateTime.ParseExact("01/02/00", "MM/dd/yy", CultureInfo.InvariantCulture)
        .ToString("MM/dd/yyyy"); // 01/02/2000

 DateTime.ParseExact("01/02/09", "MM/dd/yy", CultureInfo.InvariantCulture)
         .ToString("MM/dd/yyyy") // 01/02/2009
1
Sébastien Sevrin On

I really like Regular Expressions and use them almost everywhere, but in this context, it is not the way I would recommend (unless you want to do this for academic purposes).

I would use DateTime.TryParse or DateTime.TryParseExact.

The first thing you can write is:

Console.WriteLine("Enter the date:");
string dateString = Console.ReadLine();
DateTime date;

if(!DateTime.TryParseExact(dateString, "dd/MM/yy", CultureInfo.InvariantCulture, DateTimeStyles.None, out date))
{
    throw new InvalidOperationException("Not a valid date");
}
Console.WriteLine(date.ToString("dd/MM/yyyy", CultureInfo.InvariantCulture));
// dateString = "17/04/88" => 17/04/1988
// dateString = "17/04/1988" => "Not a valid date"

.NET Fiddle


That's nice, but wait, if somebody enters a date in the format dd/MM/yyyy it fails. The TryParseExect method takes an overload with string[] where you can specify multiple formats

Console.WriteLine("Enter the date (you can write it in the dd/MM/yyyy format):");
string dateString = Console.ReadLine();
DateTime date;

if (!DateTime.TryParseExact(dateString, new string[] { "dd/MM/yyyy", "dd/MM/yy" }, CultureInfo.InvariantCulture, DateTimeStyles.None, out date))
{
    throw new InvalidOperationException("Not a valid date");
}
Console.WriteLine(date.ToString("dd/MM/yyyy", CultureInfo.InvariantCulture));
// dateString = "17/04/1988" => "17/04/1988"
// dateString = "17/04/29" => 17/04/2029
// dateString = "17/04/30" => 17/04/1930

.NET Fiddle


That's nice, but wait, if somebody was born in 17/04/29, it will display 17/04/2029, that's in the future! If somebody reads this post in 2029+, note that it was written in 2015.

That's because of the Calendar.TwoDigitYearMax Property

This property allows a 2-digit year to be properly translated to a 4-digit year. For example, if this property is set to 2029, the 100-year range is from 1930 to 2029. Therefore, a 2-digit value of 30 is interpreted as 1930, while a 2-digit value of 29 is interpreted as 2029.

At this time, the property defaults to 2029, I'm not sure about what will be done when this date is reached, maybe a Year 2029 problem?


You can improve it again, but there is no magic, you will have to make choices because as you already know, 2 digit years are impossible to resolve unless you make assumptions.

So what you need is answer the following questions:

1) What is the date range I would like to resolve => from CurrentYear - 99 to CurrentYear?

If yes, we could write something like this:

// Execution date: 18/06/2015
Console.WriteLine("Enter the date (if you want to enter a date from more than 99 years ago, you can enter the date in the dd/MM/yyyy format):");
string dateString = Console.ReadLine();
DateTime date;
CultureInfo ci = (CultureInfo)CultureInfo.InvariantCulture.Clone();
ci.Calendar.TwoDigitYearMax = DateTime.Now.Year;

if(!DateTime.TryParseExact(dateString, new string[] { "dd/MM/yyyy", "dd/MM/yy" }, ci, DateTimeStyles.None, out date))
{
    throw new InvalidOperationException("Not a valid date");
}
Console.WriteLine(date.ToString("dd/MM/yyyy", CultureInfo.InvariantCulture));
// dateString = "17/04/15" => 17/04/2015
// dateString = "17/04/16" => 17/04/1916

.NET Fiddle


2) We are talking about birthdates, right?
Do we really need to manage people who are less than 1 year old?

Or if your birthdate is used in a system where you can say, for example, it is impossible for somebody to be less than 16 years old, you could change this range to handle dates from CurrentYear - 99 - 16 to CurrentYear - 16.
That way you can manage people from 16 to 115 years.

// Execution date: 18/06/2015
Console.WriteLine("Enter your birth date (if you are less than 16 year old you have to wait, if you are very old you can try to enter your birthdate in the dd/MM/yyyy format):");
string dateString = Console.ReadLine();
DateTime date;
CultureInfo ci = (CultureInfo)CultureInfo.InvariantCulture.Clone();
ci.Calendar.TwoDigitYearMax = DateTime.Now.Year - 16;

if (!DateTime.TryParseExact(dateString, new string[] { "dd/MM/yyyy", "dd/MM/yy" }, ci, DateTimeStyles.None, out date))
{
    throw new InvalidOperationException("Not a valid date");
}
Console.WriteLine(date.ToString("dd/MM/yyyy", CultureInfo.InvariantCulture));
// dateString = "17/04/99" => 17/04/1999
// dateString = "17/04/16" => 17/04/1900

.NET Fiddle

That's as far as this post goes, you can continue customizing it, like:

  • Being able to configure the minimum age
  • Adding checks to validate that the date is not in the future (if you enter 31/12/<TwoDigitYearMax>, it would still be valid with the above code)
0
maraaaaaaaa On

Maybe something like:

string pattern = "\D\d{2}$"

shortYear.Replace(pattern, FullYear);

string FullYear(string value)
{
    string seperator = value.Substring(0,1);
    value = value.Substring(1,2);

    if(int32.Parse(value) < int32.Parse(DateTime.Now.Year.ToString().Substring(value.Length -2, 2))
        return seperator + DateTime.Now.Year.ToString().Substring(0, value.Length -2) + value;
    return seperator + (DateTime.Now.Year - 100).ToString().Substring(0, value.Length -2) + value;
}