2010-11-08 3 views
52

Как рассчитать разницу между двумя датами в годах?Разница в датах в годах с использованием C#

Например: (Datetime.Now.Today() - 11/03/2007) по годам.

+0

Кредит за то, что он обманул доггетт. –

+1

Код, который вы отметили как ответ, является фактическим фактом неправильным. Он может вернуть неверные результаты. – Mick

+0

. Я удивлен тем, что многие из нижеприведенных ответов неверны, но голосовали. – Mick

ответ

78

Я написал реализацию, которая должным образом работает с датами ровно на один год.

Однако он не изящно обрабатывает отрицательные временные интервалы, в отличие от другого алгоритма. Он также не использует свою собственную арифметику дат, вместо этого полагаясь на стандартную библиотеку.

Итак, без дальнейших церемоний, вот код:

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); 
+7

Это означает, что в среднем приходится високосных лет, но он будет отключен одним из них до 18 часов каждый год. –

+5

Используя этот метод, разница между 1/1/2007 и 1/1/2008 составит 0 лет. Интуитивно, это должно быть 1 год. –

+2

Хорошая точка. Я не знаю другого эффективного способа сделать это, хотя ... возможно, добавить один день? –

4

Неясно, как вы хотите, чтобы справиться с дробными лет, но, возможно, как это:

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); 
+0

Согласно этому методу, 2/28/2009 - 1 год после 2/29/2008, тогда как кажется, что он должен быть чуть меньше 1 года. Я полагаю, что обработка високосных лет всегда будет немного неудовлетворительной. –

+0

@o. nate: Исправлено, может быть (используя трюк, найденный на этом другом вопросе, замеченном Доггеттом). Я думаю, что что-то вроде решения Даны может понадобиться, чтобы исправить случай високосного дня в обоих направлениях. –

5
var totalYears = 
    (DateTime.Today - new DateTime(2007, 03, 11)).TotalDays 
    /365.2425; 

Среднее количество дней от Wikipedia/Leap_year ,

+0

В среднем правильный. Но не всегда. – Mick

34

Использование:

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); 
} 
+0

Это скажет, что 2008-ноябрь-02 - это год спустя 2007-ноября-03, большинство людей скажут, что на один день короткий. –

+0

Вы правы. Я обновил свой код, чтобы уйти от свойств Year, Month и Day. Сейчас он становится немного уродливым, но работает на високосные годы. – dana

+2

для моего случая это решение –

2

Если вы пытаетесь получить чей-то возраст увидеть это

How do I calculate someone's age in C#?

+0

Или даже если вы не ... хорошее место, на вопрос с совершенно другой формулировкой. –

0

Если вы имеете дело с месяцами и годами вам нужно что-то, что знает, сколько дней каждый месяц имеет и какие годы являются високосными.

Введите Gregorian Calendar (и другие виды культуры Calendar).

Хотя календарь не предоставляет методы для прямого вычисления разности между двумя точками во время, у него есть такие методы, как

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

я реализовал метод расширения, чтобы получить количество лет между двумя датами, округленные целыми месяцами.

/// <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; 
    } 
+0

Это решение обрабатывается каждый месяц как 1/12 года. Это будет искажать, потому что некоторые месяцы не имеют такого размера –

+0

Не всегда возвращает правильный результат – Mick

18

Нам пришлось запрограммировать чек, чтобы установить, была ли разница между двумя датами, датой начала и окончания более 2 лет.

Благодаря кончиков выше это было сделано следующим образом:

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

if EndDate > TwoYears ..... 
+1

Возможно, это не актуальное решение вопроса, но оно решило мою проблему, поэтому upvote :) –

+3

Сокращенная версия: If (Birthday.AddYears (18)> DateTime.UtcNow.Date) // под 18 –

0
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); 
    } 
1
int Age = new DateTime((DateTime.Now - BirthDateTime).Ticks).Year; 
+0

На самом деле это неверно, поскольку он округляется. Мне 40, и это отчет 41. Я не 41 еще 3 недели. –

+0

Плюс это неверно объясняет високосные годы – Mick

2

Вот аккуратный трюк, который позволяет система автоматически обрабатывает високосные годы. Он дает точный ответ для всех комбинаций дат.

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); 
+1

Простой и эффективный! –

8

Если вам это нужно знать чей-то возраст тривиальным причинам, то TimeSpan в порядке, но если вам нужно для расчета пенсионный, долгосрочные депозиты или что-нибудь еще для финансовых, научных или юридических целей, то я боюсь, что TimeSpan выиграл 't быть достаточно точным, потому что Timespan предполагает, что каждый год имеет такое же количество дней, столько же часов и столько же секунд.

В действительности продолжительность нескольких лет может варьироваться (по разным причинам, выходящим за рамки этого ответа). Для того, чтобы обойти ограничения TimeSpan, то вы можете имитировать то, что делает, который Excel является:

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; 
    } 
0
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 
0

Простое решение:

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

Может быть, это будет полезно для ответа на вопрос: Число дней учитывая год,

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

Что касается DateTime.DayOfYear Property.

0

Это лучший код для расчета года и месяц разницы:

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; 
    } 
} 
0

отлично работает:

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; 
    } 
0

базируются простой кодом Даны, который производит правильный ответ в большинстве случаев следующий. Но он не принимал во внимание менее одного года между датами. Итак, вот код, который я использую для получения согласованных результатов:

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; 
} 
Смежные вопросы