C #에서 두 날짜 사이의 월 차이를 계산하는 방법은 무엇입니까?
DateDiff()
C # 에 VB의 방법 이 있습니까? 몇 년 떨어진 두 날짜 사이의 월 차이를 찾아야합니다. 설명서에는 TimeSpan
다음과 같이 사용할 수 있다고 나와 있습니다 .
TimeSpan ts = date1 - date2;
그러나 이것은 나에게 데이터를 제공합니다. 매월 30 일이 아니기 때문에이 숫자를 30으로 나누고 싶지 않습니다. 두 피연산자 값이 서로 상당히 떨어져 있기 때문에 30을 나누면 잘못된 값을 줄 수 있습니다.
어떤 제안?
답변
달의 날짜가 관련이 없다고 가정하면 (예 : 2011.1.1과 2010.12.31 사이의 차이는 1), date1> date2는 양수 값을, date2> date1은 음수 값을 갖습니다.
((date1.Year - date2.Year) * 12) + date1.Month - date2.Month
또는 두 날짜 사이에 ‘평균 월’의 대략적인 수를 원한다고 가정하면 다음은 매우 큰 날짜 차이에 대해 작동합니다.
date1.Subtract(date2).Days / (365.25 / 12)
후자의 솔루션을 사용하는 경우 단위 테스트는 애플리케이션이 작동하도록 설계된 가장 넓은 날짜 범위를 명시하고 그에 따라 계산 결과를 검증해야합니다.
업데이트 ( Gary 덕분에 )
‘평균 월’방법을 사용하는 경우 ‘연간 평균 일 수’에 사용할 약간 더 정확한 수는 365.2425 입니다.
답변
다음은 시간 구성 요소와 함께 모든 날짜 구성 요소를 포함한다는 점을 제외하고 DateTimeSpan
, 를 반환하는 포괄적 인 솔루션 TimeSpan
입니다.
용법:
void Main()
{
DateTime compareTo = DateTime.Parse("8/13/2010 8:33:21 AM");
DateTime now = DateTime.Parse("2/9/2012 10:10:11 AM");
var dateSpan = DateTimeSpan.CompareDates(compareTo, now);
Console.WriteLine("Years: " + dateSpan.Years);
Console.WriteLine("Months: " + dateSpan.Months);
Console.WriteLine("Days: " + dateSpan.Days);
Console.WriteLine("Hours: " + dateSpan.Hours);
Console.WriteLine("Minutes: " + dateSpan.Minutes);
Console.WriteLine("Seconds: " + dateSpan.Seconds);
Console.WriteLine("Milliseconds: " + dateSpan.Milliseconds);
}
출력 :
년 : 1
개월 : 5
일 : 27
시간 : 1
분 : 36
초 : 50
밀리 초 : 0
편의상 논리를 DateTimeSpan
구조체에 집중 시켰지만 원하는 위치로 메소드를 이동할 수 있습니다 CompareDates
. 또한 어느 날짜가 다른 날짜보다 먼저 나오는지는 중요하지 않습니다.
public struct DateTimeSpan
{
public int Years { get; }
public int Months { get; }
public int Days { get; }
public int Hours { get; }
public int Minutes { get; }
public int Seconds { get; }
public int Milliseconds { get; }
public DateTimeSpan(int years, int months, int days, int hours, int minutes, int seconds, int milliseconds)
{
Years = years;
Months = months;
Days = days;
Hours = hours;
Minutes = minutes;
Seconds = seconds;
Milliseconds = milliseconds;
}
enum Phase { Years, Months, Days, Done }
public static DateTimeSpan CompareDates(DateTime date1, DateTime date2)
{
if (date2 < date1)
{
var sub = date1;
date1 = date2;
date2 = sub;
}
DateTime current = date1;
int years = 0;
int months = 0;
int days = 0;
Phase phase = Phase.Years;
DateTimeSpan span = new DateTimeSpan();
int officialDay = current.Day;
while (phase != Phase.Done)
{
switch (phase)
{
case Phase.Years:
if (current.AddYears(years + 1) > date2)
{
phase = Phase.Months;
current = current.AddYears(years);
}
else
{
years++;
}
break;
case Phase.Months:
if (current.AddMonths(months + 1) > date2)
{
phase = Phase.Days;
current = current.AddMonths(months);
if (current.Day < officialDay && officialDay <= DateTime.DaysInMonth(current.Year, current.Month))
current = current.AddDays(officialDay - current.Day);
}
else
{
months++;
}
break;
case Phase.Days:
if (current.AddDays(days + 1) > date2)
{
current = current.AddDays(days);
var timespan = date2 - current;
span = new DateTimeSpan(years, months, days, timespan.Hours, timespan.Minutes, timespan.Seconds, timespan.Milliseconds);
phase = Phase.Done;
}
else
{
days++;
}
break;
}
}
return span;
}
}
답변
넌 할 수있어
if ( date1.AddMonths(x) > date2 )
답변
전체 월의 정확한 수를 원하면 다음 달 같은 날에 도달하는 달을 고려할 때 항상 양수 (2000-01-15, 2000-02-14는 0을 반환 함)를 원합니다 (연령 계산과 같은 것).
public static int GetMonthsBetween(DateTime from, DateTime to)
{
if (from > to) return GetMonthsBetween(to, from);
var monthDiff = Math.Abs((to.Year * 12 + (to.Month - 1)) - (from.Year * 12 + (from.Month - 1)));
if (from.AddMonths(monthDiff) > to || to.Day < from.Day)
{
return monthDiff - 1;
}
else
{
return monthDiff;
}
}
편집 이유 : 이전 코드는 다음과 같은 경우에 올바르지 않습니다.
new { From = new DateTime(1900, 8, 31), To = new DateTime(1901, 8, 30), Result = 11 },
Test cases I used to test the function:
var tests = new[]
{
new { From = new DateTime(1900, 1, 1), To = new DateTime(1900, 1, 1), Result = 0 },
new { From = new DateTime(1900, 1, 1), To = new DateTime(1900, 1, 2), Result = 0 },
new { From = new DateTime(1900, 1, 2), To = new DateTime(1900, 1, 1), Result = 0 },
new { From = new DateTime(1900, 1, 1), To = new DateTime(1900, 2, 1), Result = 1 },
new { From = new DateTime(1900, 2, 1), To = new DateTime(1900, 1, 1), Result = 1 },
new { From = new DateTime(1900, 1, 31), To = new DateTime(1900, 2, 1), Result = 0 },
new { From = new DateTime(1900, 8, 31), To = new DateTime(1900, 9, 30), Result = 0 },
new { From = new DateTime(1900, 8, 31), To = new DateTime(1900, 10, 1), Result = 1 },
new { From = new DateTime(1900, 1, 1), To = new DateTime(1901, 1, 1), Result = 12 },
new { From = new DateTime(1900, 1, 1), To = new DateTime(1911, 1, 1), Result = 132 },
new { From = new DateTime(1900, 8, 31), To = new DateTime(1901, 8, 30), Result = 11 },
};
답변
MSDN을 통해 VB.NET 에서이 방법의 사용법을 확인했으며 사용법이 많이있는 것 같습니다. C #에는 이러한 기본 제공 방법이 없습니다. (좋은 생각은 아니지만) C #에서 VB를 호출 할 수 있습니다.
Microsoft.VisualBasic.dll
참조로 프로젝트에 추가Microsoft.VisualBasic.DateAndTime.DateDiff
코드에서 사용
답변
날짜와 상관없이 월 (시작 및 끝 포함)의 차이를 얻으려면 :
DateTime start = new DateTime(2013, 1, 1);
DateTime end = new DateTime(2014, 2, 1);
var diffMonths = (end.Month + end.Year * 12) - (start.Month + start.Year * 12);