tags:

views:

1075

answers:

6

This is a question of best practices. I have a utility that takes in a two digit year as a string and I need to convert it to a four digit year as a string. right now I do

//DOB's format is "MMM (D)D YY" that first digit of the day is not there for numbers 1-9
string tmpYear = rowIn.DOB.Substring(rowIn.DOB.Length - 3, 2); //-3 because it is 0 indexed
if (Convert.ToInt16(tmpYear) > 50)
    tmpYear = String.Format("19{0}", tmpYear);
else
    tmpYear = String.Format("20{0}", tmpYear);

I am shure I am doing it horribly wrong, any pointers?

+13  A: 

Given that there are people alive now born before 1950, but none born after 2010, your use of 50 as the flipping point seems broken.

For date of birth, can you not set the flip point to the 'year of now' (i.e. 10) in your app? Even then you'll have problems with those born before 1911...

There's no perfect way to do this - you're creating information out of thin air.

I've assumed DOB = date-of-birth. For other data (say, maturity of a financial instrument) the choice might be different, but just as imperfect.

martin clayton
You are right about the DOB, but they are for animals not humans, and their lifespan is at most 40 years. but you are right about using a moving target. I will now use `if (Convert.ToInt16(String.Format("20{0}", tmpYear[2])) > DateTime.Today.Year + 3) // Causes Y2.1K problem, but I will be retired by then.`
Scott Chamberlain
Like an animal _Logan's Run_ eh? With a moving threshold year, and given no 100year+ lifespans, you should be ok. I assumed humans obviously. You could address the Y2K1 issue by making the Century part derive from Today too...
martin clayton
+3  A: 

It might be smarter to check tmpYear > currentYear%100. If it is, then it's 19XX, otherwise 20XX.

Wallacoloo
+1  A: 

I think Java has a good implementation of this:

http://java.sun.com/javase/6/docs/api/java/text/SimpleDateFormat.html#year

People rarely specify years far into the future using a two-digit code. The Java implementation handles this by assuming a range of 80 years behind and 20 years ahead of the current year. So right now, 30 would be 2030, while 31 would be 1931. Additionally, this implementation is flexible, modifying its ranges as time goes on, so that you don't have to change the code every decade or so.

I just tested, and Excel also uses these same rules for 2-digit year conversion. 1/1/29 turns into 1/1/2029. 1/1/30 turns into 1/1/1930.

jdmichal
+4  A: 

Once you've taken the other suggestions as to when to flip your century assumptions from 19 to 20, the best of all possible worlds involves updating your data source once and for all with 4-digit years, so you can stop making assumptions all the time.

Joel Mueller
Unfortunately I have no control over the data source.
Scott Chamberlain
A: 

Out of curiosity, from where do you get this data? From a form? In that case; I would simply ask the user to fill in (or somehow select) the year with four digits or get the users age and month/day of birth, and use that data to figure out what year they were born. That way, you wouldn't have to worry about this problem at all :)

Edit: Use DateTime for working with this kind of data.

Leif
+1  A: 

You can also use the DateTime.TryParse method to convert your date. It uses the current culture settings to define the pivot year (in my case it is 2029)

DateTime resultDate;
Console.WriteLine("CultureInfo.CurrentCulture.Calendar.TwoDigitYearMax : {0}", System.Globalization.CultureInfo.CurrentCulture.Calendar.TwoDigitYearMax);
DateTime.TryParse("01/01/28", out resultDate);
Console.WriteLine("Generated date with year=28 - {0}",resultDate);
DateTime.TryParse("01/02/29",out resultDate);
Console.WriteLine("Generated date with year=29 - {0}", resultDate);
DateTime.TryParse("01/03/30", out resultDate);
Console.WriteLine("Generated date with year=30 - {0}", resultDate);

The output is:

CultureInfo.CurrentCulture.Calendar.TwoDigitYearMax : 2029

Generated date with year=28 - 01/01/2028 00:00:00

Generated date with year=29 - 01/02/2029 00:00:00

Generated date with year=30 - 01/03/1930 00:00:00

If you want to change the behavior you can create a culture with the year you want to use as pivot. This thread shows an example

DateTime.TryParse century control C#

But as martin stated, if you want to manage a time period that spans more than 100 year, there is no way to do it with only 2 digits.

FrenchData