[C#] 두 날짜 사이의 월 차이

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를 호출 할 수 있습니다.

  1. Microsoft.VisualBasic.dll참조로 프로젝트에 추가
  2. 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);


답변

노다 시간 사용 :

LocalDate start = new LocalDate(2013, 1, 5);
LocalDate end = new LocalDate(2014, 6, 1);
Period period = Period.Between(start, end, PeriodUnits.Months);
Console.WriteLine(period.Months); // 16

(예제 출처)