使用 C # 的年份日期差异

如何计算年份中两个日期之间的日期差?

例如: 以年为单位的 (Datetime.Now.Today() - 11/03/2007)

203406 次浏览

I have written an implementation that properly works with dates exactly one year apart.

However, it does not gracefully handle negative timespans, unlike the other algorithm. It also doesn't use its own date arithmetic, instead relying upon the standard library for that.

So without further ado, here is the code:

DateTime zeroTime = new DateTime(1, 1, 1);


DateTime a = new DateTime(2007, 1, 1);
DateTime b = new DateTime(2008, 1, 1);


TimeSpan span = b - a;
// Because we start at year 1 for the Gregorian
// calendar, we must subtract a year here.
int years = (zeroTime + span).Year - 1;


// 1, where my other algorithm resulted in 0.
Console.WriteLine("Yrs elapsed: " + years);

It's unclear how you want to handle fractional years, but perhaps like this:

DateTime now = DateTime.Now;
DateTime origin = new DateTime(2007, 11, 3);
int calendar_years = now.Year - origin.Year;
int whole_years = calendar_years - ((now.AddYears(-calendar_years) >= origin)? 0: 1);
int another_method = calendar_years - ((now.Month - origin.Month) * 32 >= origin.Day - now.Day)? 0: 1);
var totalYears =
(DateTime.Today - new DateTime(2007, 03, 11)).TotalDays
/ 365.2425;

Average days from Wikipedia/Leap_year.

Use:

int Years(DateTime start, DateTime end)
{
return (end.Year - start.Year - 1) +
(((end.Month > start.Month) ||
((end.Month == start.Month) && (end.Day >= start.Day))) ? 1 : 0);
}

If you're dealing with months and years you need something that knows how many days each month has and which years are leap years.

Enter the Gregorian Calendar (and other culture-specific Calendar implementations).

While Calendar doesn't provide methods to directly calculate the difference between two points in time, it does have methods such as

DateTime AddWeeks(DateTime time, int weeks)
DateTime AddMonths(DateTime time, int months)
DateTime AddYears(DateTime time, int years)

I implemented an extension method to get the number of years between two dates, rounded by whole months.

    /// <summary>
/// Gets the total number of years between two dates, rounded to whole months.
/// Examples:
/// 2011-12-14, 2012-12-15 returns 1.
/// 2011-12-14, 2012-12-14 returns 1.
/// 2011-12-14, 2012-12-13 returns 0,9167.
/// </summary>
/// <param name="start">
/// Stardate of time period
/// </param>
/// <param name="end">
/// Enddate of time period
/// </param>
/// <returns>
/// Total Years between the two days
/// </returns>
public static double DifferenceTotalYears(this DateTime start, DateTime end)
{
// Get difference in total months.
int months = ((end.Year - start.Year) * 12) + (end.Month - start.Month);


// substract 1 month if end month is not completed
if (end.Day < start.Day)
{
months--;
}


double totalyears = months / 12d;
return totalyears;
}

We had to code a check to establish if the difference between two dates, a start and end date was greater than 2 years.

Thanks to the tips above it was done as follows:

 DateTime StartDate = Convert.ToDateTime("01/01/2012");
DateTime EndDate = Convert.ToDateTime("01/01/2014");
DateTime TwoYears = StartDate.AddYears(2);


if EndDate > TwoYears .....

I found this at TimeSpan for years, months and days:

DateTime target_dob = THE_DOB;
DateTime true_age = DateTime.MinValue + ((TimeSpan)(DateTime.Now - target_dob )); // Minimum value as 1/1/1
int yr = true_age.Year - 1;
    public string GetAgeText(DateTime birthDate)
{
const double ApproxDaysPerMonth = 30.4375;
const double ApproxDaysPerYear = 365.25;


int iDays = (DateTime.Now - birthDate).Days;


int iYear = (int)(iDays / ApproxDaysPerYear);
iDays -= (int)(iYear * ApproxDaysPerYear);


int iMonths = (int)(iDays / ApproxDaysPerMonth);
iDays -= (int)(iMonths * ApproxDaysPerMonth);


return string.Format("{0} år, {1} måneder, {2} dage", iYear, iMonths, iDays);
}
int Age = new DateTime((DateTime.Now - BirthDateTime).Ticks).Year;

To calculate the elapsed years (age), the result will be minus one.

var timeSpan = DateTime.Now - birthDateTime;
int age = new DateTime(timeSpan.Ticks).Year - 1;

Here is a neat trick which lets the system deal with leap years automagically. It gives an accurate answer for all date combinations.

DateTime dt1 = new DateTime(1987, 9, 23, 13, 12, 12, 0);
DateTime dt2 = new DateTime(2007, 6, 15, 16, 25, 46, 0);


DateTime tmp = dt1;
int years = -1;
while (tmp < dt2)
{
years++;
tmp = tmp.AddYears(1);
}


Console.WriteLine("{0}", years);

If you need it for knowing someone's age for trivial reasons then Timespan is OK but if you need for calculating superannuation, long term deposits or anything else for financial, scientific or legal purposes then I'm afraid Timespan won't be accurate enough because Timespan assumes that every year has the same number of days, same # of hours and same # of seconds).

In reality the length of some years will vary (for different reasons that are outside the scope of this answer). To get around Timespan's limitation then you can mimic what Excel does which is:

    public int GetDifferenceInYears(DateTime startDate, DateTime endDate)
{
//Excel documentation says "COMPLETE calendar years in between dates"
int years = endDate.Year - startDate.Year;


if (startDate.Month == endDate.Month &&// if the start month and the end month are the same
endDate.Day < startDate.Day// AND the end day is less than the start day
|| endDate.Month < startDate.Month)// OR if the end month is less than the start month
{
years--;
}


return years;
}
DateTime musteriDogum = new DateTime(dogumYil, dogumAy, dogumGun);


int additionalDays = ((DateTime.Now.Year - dogumYil) / 4); //Count of the years with 366 days


int extraDays = additionalDays + ((DateTime.Now.Year % 4 == 0 || musteriDogum.Year % 4 == 0) ? 1 : 0); //We add 1 if this year or year inserted has 366 days


int yearsOld = ((DateTime.Now - musteriDogum).Days - extraDays ) / 365; // Now we extract these extra days from total days and we can divide to 365

Simple solution:

public int getYearDiff(DateTime startDate, DateTime endDate){
int y = Year(endDate) - Year(startDate);
int startMonth = Month(startDate);
int endMonth = Month(endDate);
if (endMonth < startMonth)
return y - 1;
if (endMonth > startMonth)
return y;
return (Day(endDate) < Day(startDate) ? y - 1 : y);
}

Maybe this will be helpful for answering the question: Count of days in given year,

new DateTime(anyDate.Year, 12, 31).DayOfYear //will include leap years too

Regarding DateTime.DayOfYear Property.

This is the best code to calculate year and month difference:

DateTime firstDate = DateTime.Parse("1/31/2019");
DateTime secondDate = DateTime.Parse("2/1/2016");


int totalYears = firstDate.Year - secondDate.Year;
int totalMonths = 0;


if (firstDate.Month > secondDate.Month)
totalMonths = firstDate.Month - secondDate.Month;
else if (firstDate.Month < secondDate.Month)
{
totalYears -= 1;
int monthDifference = secondDate.Month - firstDate.Month;
totalMonths = 12 - monthDifference;
}


if ((firstDate.Day - secondDate.Day) == 30)
{
totalMonths += 1;
if (totalMonths % 12 == 0)
{
totalYears += 1;
totalMonths = 0;
}
}

Works perfect:

    internal static int GetDifferenceInYears(DateTime startDate)
{
int finalResult = 0;


const int DaysInYear = 365;


DateTime endDate = DateTime.Now;


TimeSpan timeSpan = endDate - startDate;


if (timeSpan.TotalDays > 365)
{
finalResult = (int)Math.Round((timeSpan.TotalDays / DaysInYear), MidpointRounding.ToEven);
}


return finalResult;
}

The following is based off Dana's simple code which produces the correct answer in most cases. But it did not take in to account less than a year between dates. So here is the code that I use to produce consistent results:

public static int DateDiffYears(DateTime startDate, DateTime endDate)
{
var yr = endDate.Year - startDate.Year - 1 +
(endDate.Month >= startDate.Month && endDate.Day >= startDate.Day ? 1 : 0);
return yr < 0 ? 0 : yr;
}