Scott Chamberlain
Scott Chamberlain

Reputation: 127553

Convert a two digit year to a four digit year

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 sure I am doing it horribly wrong, any pointers?

Upvotes: 43

Views: 54686

Answers (18)

user18582947
user18582947

Reputation: 11

My answer will not match your question but for credit cards I just add 2 digits of current year

private int UpconvertTwoDigitYearToFour(int yearTwoOrFour)
{
    try
    {
        if (yearTwoOrFour.ToString().Length <= 2)
        {
            DateTime yearOnly = DateTime.ParseExact(yearTwoOrFour.ToString("D2"), "yy", null);
            return yearOnly.Year;
        }
    }
    catch
    {
    }

    return yearTwoOrFour;
}

Upvotes: 1

Code
Code

Reputation: 739

 int fYear = Convert.ToInt32(txtYear.Value.ToString().Substring(2, 2));

Upvotes: 0

Abhishek Garg
Abhishek Garg

Reputation: 3242

Based on above solutions, here is mine, i used in android while using java

it takes current year in two digit format then checks for if input year length is equal to 2, if yes then it get current year and from this year it splits first two digits of century, then it adds this century with year user input. to make it 4 digit year.

public static int getConvertedYearFromTwoToFourDigits(String year) {
        if (year.length() == 2) {
            int currentYear = Calendar.getInstance().get(Calendar.YEAR);
            String firstTwoDigitsOfCurrentYear = String.valueOf(currentYear).substring(0, 2);
            year = firstTwoDigitsOfCurrentYear + year;
        }
        return Integer.parseInt(year);
    }

Upvotes: 0

Shiv
Shiv

Reputation: 21

This Method can convert the credit card last two year digits to four year


private static int ToFourDigitYear(int year)
{
    string stringYear = year.ToString("00");
    if (stringYear.Length == 2)
    {
        int currentYear = DateTime.Now.Year;
        string firstTwoDigitsOfCurrentYear = currentYear.ToString().Substring(0, 2);
        year = Convert.ToInt32(firstTwoDigitsOfCurrentYear + stringYear);
        if (year < currentYear)
            year = year + 100;
    }
    return year;
}

Upvotes: 2

Beeing Jk
Beeing Jk

Reputation: 3926

My two cents,

Given an age range=[18, 100+], two digits year=90, I can do

current year - twoDigitsYear = 2018 - 90 = 1928, I got 19, 28

hence 19 is the first two digits of year of born, and 28 is the age, which is
year=1990, age=28

But it won't work when age 0 and 100 both included in the range, same to some of the other answers here.

Upvotes: 0

tyler_mitchell
tyler_mitchell

Reputation: 1747

This solution we use for Expiration Dates, the user enters MM and YY into separate fields. This results in dates being the 31st or 30th and 28th or 29th also for February.

/// <summary>
/// Creates datetime for current century and sets days to end of month
/// </summary>
/// <param name="MM"></param>
/// <param name="YY"></param>
/// <returns></returns>
public static DateTime GetEndOfMonth(string MM, string YY)
{
    // YY -> YYYY #RipVanWinkle
    // Gets Current century and adds YY to it.
    // Minus 5 to allow dates that may be expired to be entered.
    // eg. today is 2017, 12 = 2012 and 11 = 2111
    int currentYear = DateTime.Now.Year;
    string thisYear = currentYear.ToString().Substring(0, 2) + YY;
    int month = Int32.Parse(MM);
    int year = Int32.Parse(thisYear);
    if ((currentYear - 5) > year)
        year += 100;

    return new DateTime(year, month, DateTime.DaysInMonth(year, month));
}

Upvotes: 1

Ellen22
Ellen22

Reputation: 101

To change a 2-digit year to 4-digit current or earlier -

year = year + (DateTime.Today.Year - DateTime.Today.Year%100);
if (year > DateTime.Today.Year)
                year = year - 100;

Upvotes: 0

Vedran
Vedran

Reputation: 11029

The .NET framework has a method that does exactly what you want:

int fourDigitYear = CultureInfo.CurrentCulture.Calendar.ToFourDigitYear(twoDigitYear)

That way you will correctly adhere to current regional settings as defined in Control Panel (or group policy):

Regional settings

Upvotes: 81

Mattias Engman
Mattias Engman

Reputation: 58

If you calculate for a person he will probably not be more than 100 years...

Eg: 751212

var nr = "751212";
var century = DateTime.Now.AddYears(-100).Year.ToString().Substring(0, 2);

var days = (DateTime.Now - DateTime.Parse(century + nr)).Days;
decimal years = days / 365.25m;
if(years>=99)
 century = DateTime.Now.Year.ToString().Substring(0, 2);

var fullnr = century+nr;

Upvotes: 0

RealWillyWonka
RealWillyWonka

Reputation: 713

The implementation of

System.Globalization.CultureInfo.CurrentCulture.Calendar.ToFourDigitYear 

is

public virtual int ToFourDigitYear(int year)
{
  if (year < 0)
    throw new ArgumentOutOfRangeException("year", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
  if (year < 100)
    return (this.TwoDigitYearMax / 100 - (year > this.TwoDigitYearMax % 100 ? 1 : 0)) * 100 + year;
  else
    return year;
}

Hope this helps!

Upvotes: 5

Pawel Cioch
Pawel Cioch

Reputation: 3184

My answer will not match your question but for credit cards I just add 2 digits of current year

    private int UpconvertTwoDigitYearToFour(int yearTwoOrFour)
    {
        try
        {
            if (yearTwoOrFour.ToString().Length <= 2)
            {
                DateTime yearOnly = DateTime.ParseExact(yearTwoOrFour.ToString("D2"), "yy", null);
                return yearOnly.Year;
            }
        }
        catch
        {
        }

        return yearTwoOrFour;
    }

Upvotes: 0

bizah
bizah

Reputation: 247

Had a similar issue, and came up with this... HTH!

value = this.GetDate()

if (value.Length >= 6)//ensure that the date is mmddyy
{
    int year = 0;

    if (int.TryParse(value.Substring(4, 2), out year))
    {
        int pastMillenium = int.Parse(DateTime.Now.ToString("yyyy").Substring(0, 2)) - 1;

        if (year > int.Parse(DateTime.Now.ToString("yy")))//if its a future year it's most likely 19XX
        {
            value = string.Format("{0}{1}{2}", value.Substring(0, 4), pastMillenium, year.ToString().PadLeft(2, '0'));
        }
        else
        {
            value = string.Format("{0}{1}{2}", value.Substring(0, 4), pastMillenium + 1, year.ToString().PadLeft(2, '0'));
        }
    }
    else
    {
        value = string.Empty;
    }
}
else
{
    value = string.Empty;
}

Upvotes: 0

Jags
Jags

Reputation: 9

Try this simple code

//Invoke TextBoxDateFormat method with date as parameter.

Method

public void TextBoxDateFormat(string str1)

{

// Takes the current date format if MM/DD/YY or MM/DD/YYYY

DateTime dt = Convert.ToDateTime(str1);

//Converts the requested date into MM/DD/YYYY and assign it to textbox field

TextBox = String.Format("{0:MM/dd/yyyy}", dt.ToShortDateString());


//include your validation code if required

}

Upvotes: 0

FrenchData
FrenchData

Reputation: 630

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.

Upvotes: 8

jdmichal
jdmichal

Reputation: 11152

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.

Upvotes: 5

leifericf
leifericf

Reputation: 2372

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.

Upvotes: 0

martin clayton
martin clayton

Reputation: 78105

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.

Upvotes: 16

Ponkadoodle
Ponkadoodle

Reputation: 5957

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

Upvotes: 4

Related Questions