Programming

두 날짜 사이의 월 차이 계산

procodes 2020. 7. 16. 21:11
반응형

두 날짜 사이의 월 차이 계산


C # /. NET TimeSpan에는 TotalDays, TotalMinutes등이 있지만 총 개월 차이에 대한 공식을 알 수는 없습니다. 한 달에 다양한 날과 윤년이 계속 저를 던져 버립니다. TotalMonths를 어떻게받을 수 있습니까 ?

편집 더 명확하지 않은 것에 대해 죄송합니다 : 실제로 이것을 얻을 수는 TimeSpan없지만 사용 TotalDays하고 있다고 생각 TotalMinutes하고 총 달을 얻는 것을 제외하고는 내가 찾고있는 것을 표현하는 좋은 예가 될 것입니다 ...

예 : 2009 년 12 월 25 일-2009 년 10 월 6 일 = 총 2 개월 10 월 6 일부터 11 월 5 일까지는 0 개월입니다. 11 월 6 일, 1 개월 2 개월 12 월 6 일


TimeSpan"월"은 가변 측정 단위이므로을 ( 를) 얻을 수 없습니다 . 직접 계산해야하며 작동 방식을 정확히 파악해야합니다.

예를 들어, 날짜 좋아해야 July 5, 2009하고 August 4, 2009한 달 제로 개월 차이를 산출? 당신은 무엇에 대해 다음 중 하나를 양보해야한다고 경우 July 31, 2009August 1, 2009? 한 달? 단순히 Month날짜 값 의 차이입니까 , 아니면 실제 시간 범위와 더 관련이 있습니까? 이러한 모든 규칙을 결정하는 논리는 사소한 것이 아니므로 자신의 규칙을 결정하고 적절한 알고리즘을 구현해야합니다.

날짜 값을 완전히 무시하고 단순히 달의 차이 만 원하는 경우 다음을 사용할 수 있습니다.

public static int MonthDifference(this DateTime lValue, DateTime rValue)
{
    return (lValue.Month - rValue.Month) + 12 * (lValue.Year - rValue.Year);
}

이 값은 상대 차이를 반환합니다. 즉, rValue이보다 크면 lValue반환 값이 음수입니다. 절대적인 차이를 원하면 다음을 사용할 수 있습니다.

public static int MonthDifference(this DateTime lValue, DateTime rValue)
{
    return Math.Abs((lValue.Month - rValue.Month) + 12 * (lValue.Year - rValue.Year));
}

(이것은 오래된 질문이라는 것을 알고 있지만 ...)

이다 상대적으로 순수 .NET에서 할 고통. 나는 특히 다음과 같은 것들을 위해 설계된 Noda Time 라이브러리를 추천 합니다.

LocalDate start = new LocalDate(2009, 10, 6);
LocalDate end = new LocalDate(2009, 12, 25);
Period period = Period.Between(start, end);
int months = period.Months;

(다른 옵션도 있습니다. 예를 들어 몇 년 동안 몇 달 동안 만 원하는 경우을 사용합니다 Period period = Period.Between(start, end, PeriodUnits.Months);)


아마도 월의 분수에 대해 알고 싶지 않을 것입니다. 이 코드는 어떻습니까?


public static class DateTimeExtensions
{
    public static int TotalMonths(this DateTime start, DateTime end)
    {
        return (start.Year * 12 + start.Month) - (end.Year * 12 + end.Month);
    }
}

//  Console.WriteLine(
//     DateTime.Now.TotalMonths(
//         DateTime.Now.AddMonths(-1))); // prints "1"



TotalMonths가 의미하는 바를 정의해야합니다.
간단한 정의는 한 달에 30.4 일 (365.25 / 12)입니다.

그 외에도 분수를 포함한 모든 정의는 쓸모없는 것처럼 보이며 더 일반적인 정수 값 (날짜 사이의 월 단위)도 비표준 비즈니스 규칙에 따라 다릅니다.


당신은 날짜 시간에 스스로 그것을 해결해야합니다. 스텁 일을 처리하는 방법은 사용하려는 대상에 따라 다릅니다.

한 가지 방법은 월을 계산 한 다음 마지막 날을 수정하는 것입니다. 다음과 같은 것 :

   DateTime start = new DateTime(2003, 12, 25);
   DateTime end = new DateTime(2009, 10, 6);
   int compMonth = (end.Month + end.Year * 12) - (start.Month + start.Year * 12);
   double daysInEndMonth = (end - end.AddMonths(1)).Days;
   double months = compMonth + (start.Day - end.Day) / daysInEndMonth;

나는에 아주 간단한 확장 메서드를 작성했습니다 DateTimeDateTimeOffset이 작업을 수행하는. 나는 그것이 TotalMonths속성 TimeSpan이 작동 하는 것과 똑같이 작동하기를 원했습니다 . 즉, 두 달 사이에 완전한 월 수를 반환하고 부분 개월은 무시하십시오. 그것은 그것을 기반으로하기 때문에 DateTime.AddMonths()다른 달 길이를 존중하고 인간이 개월 기간으로 이해 한 것을 반환합니다.

(불행히도 TimeSpan에서 확장 방법으로 구현 할 수는 없습니다. 실제 사용 된 날짜와 수개월 동안 중요한 정보를 유지하지 않기 때문입니다.)

코드와 테스트는 모두 GitHub에서 사용할 수 있습니다 . 코드는 매우 간단합니다.

public static int GetTotalMonthsFrom(this DateTime dt1, DateTime dt2)
{
    DateTime earlyDate = (dt1 > dt2) ? dt2.Date : dt1.Date;
    DateTime lateDate = (dt1 > dt2) ? dt1.Date : dt2.Date;

    // Start with 1 month's difference and keep incrementing
    // until we overshoot the late date
    int monthsDiff = 1;
    while (earlyDate.AddMonths(monthsDiff) <= lateDate)
    {
        monthsDiff++;
    }

    return monthsDiff - 1;
}

그리고 모든 단위 테스트 사례를 통과합니다.

// Simple comparison
Assert.AreEqual(1, new DateTime(2014, 1, 1).GetTotalMonthsFrom(new DateTime(2014, 2, 1)));
// Just under 1 month's diff
Assert.AreEqual(0, new DateTime(2014, 1, 1).GetTotalMonthsFrom(new DateTime(2014, 1, 31)));
// Just over 1 month's diff
Assert.AreEqual(1, new DateTime(2014, 1, 1).GetTotalMonthsFrom(new DateTime(2014, 2, 2)));
// 31 Jan to 28 Feb
Assert.AreEqual(1, new DateTime(2014, 1, 31).GetTotalMonthsFrom(new DateTime(2014, 2, 28)));
// Leap year 29 Feb to 29 Mar
Assert.AreEqual(1, new DateTime(2012, 2, 29).GetTotalMonthsFrom(new DateTime(2012, 3, 29)));
// Whole year minus a day
Assert.AreEqual(11, new DateTime(2012, 1, 1).GetTotalMonthsFrom(new DateTime(2012, 12, 31)));
// Whole year
Assert.AreEqual(12, new DateTime(2012, 1, 1).GetTotalMonthsFrom(new DateTime(2013, 1, 1)));
// 29 Feb (leap) to 28 Feb (non-leap)
Assert.AreEqual(12, new DateTime(2012, 2, 29).GetTotalMonthsFrom(new DateTime(2013, 2, 28)));
// 100 years
Assert.AreEqual(1200, new DateTime(2000, 1, 1).GetTotalMonthsFrom(new DateTime(2100, 1, 1)));
// Same date
Assert.AreEqual(0, new DateTime(2014, 8, 5).GetTotalMonthsFrom(new DateTime(2014, 8, 5)));
// Past date
Assert.AreEqual(6, new DateTime(2012, 1, 1).GetTotalMonthsFrom(new DateTime(2011, 6, 10)));

나는 이렇게 할 것입니다 :

static int TotelMonthDifference(this DateTime dtThis, DateTime dtOther)
{
    int intReturn = 0;

    dtThis = dtThis.Date.AddDays(-(dtThis.Day-1));
    dtOther = dtOther.Date.AddDays(-(dtOther.Day-1));

    while (dtOther.Date > dtThis.Date)
    {
        intReturn++;     
        dtThis = dtThis.AddMonths(1);
    }

    return intReturn;
}

당신은 항상 물건을 가정하기 때문에 이것에 대한 명확한 대답은 많지 않습니다.

이 솔루션은 비교를 위해 월을 저장한다고 가정하고 두 날짜 사이의 월을 계산합니다 (달의 날짜가 계산에서 고려 됨).

예를 들어, 2012 년 1 월 30 일의 날짜 인 경우 2012 년 2 월 29 일은 한 달이 아니라 2013 년 3 월 1 일입니다.

그것은 꽤 철저하게 테스트되었으며, 아마도 우리가 그것을 사용할 때 정리 할 것이고 아마도 Timespan 대신 두 날짜가 걸릴 것입니다. 이것이 다른 누군가를 돕기를 바랍니다.

private static int TotalMonthDifference(DateTime dtThis, DateTime dtOther)
{
    int intReturn = 0;
    bool sameMonth = false;

    if (dtOther.Date < dtThis.Date) //used for an error catch in program, returns -1
        intReturn--;

    int dayOfMonth = dtThis.Day; //captures the month of day for when it adds a month and doesn't have that many days
    int daysinMonth = 0; //used to caputre how many days are in the month

    while (dtOther.Date > dtThis.Date) //while Other date is still under the other
    {
        dtThis = dtThis.AddMonths(1); //as we loop, we just keep adding a month for testing
        daysinMonth = DateTime.DaysInMonth(dtThis.Year, dtThis.Month); //grabs the days in the current tested month

        if (dtThis.Day != dayOfMonth) //Example 30 Jan 2013 will go to 28 Feb when a month is added, so when it goes to march it will be 28th and not 30th
        {
            if (daysinMonth < dayOfMonth) // uses day in month max if can't set back to day of month
                dtThis.AddDays(daysinMonth - dtThis.Day);
            else
                dtThis.AddDays(dayOfMonth - dtThis.Day);
        }
        if (((dtOther.Year == dtThis.Year) && (dtOther.Month == dtThis.Month))) //If the loop puts it in the same month and year
        {
            if (dtOther.Day >= dayOfMonth) //check to see if it is the same day or later to add one to month
                intReturn++;
            sameMonth = true; //sets this to cancel out of the normal counting of month
        }
        if ((!sameMonth)&&(dtOther.Date > dtThis.Date))//so as long as it didn't reach the same month (or if i started in the same month, one month ahead, add a month)
            intReturn++;
    }
    return intReturn; //return month
}

내가 아는 오래된 질문이지만 누군가를 도울 수 있습니다. 위의 @Adam 허용 답변을 사용했지만 그 차이가 1 또는 -1인지 확인한 다음 전체 월의 차이인지 확인하십시오. 따라서 21/07/55 및 20/08/55는 한 달이 아니지만 21/07/55 및 21/07/55가됩니다.

/// <summary>
/// Amended date of birth cannot be greater than or equal to one month either side of original date of birth.
/// </summary>
/// <param name="dateOfBirth">Date of birth user could have amended.</param>
/// <param name="originalDateOfBirth">Original date of birth to compare against.</param>
/// <returns></returns>
public JsonResult ValidateDateOfBirth(string dateOfBirth, string originalDateOfBirth)
{
    DateTime dob, originalDob;
    bool isValid = false;

    if (DateTime.TryParse(dateOfBirth, out dob) && DateTime.TryParse(originalDateOfBirth, out originalDob))
    {
        int diff = ((dob.Month - originalDob.Month) + 12 * (dob.Year - originalDob.Year));

        switch (diff)
        {
            case 0:
                // We're on the same month, so ok.
                isValid = true;
                break;
            case -1:
                // The month is the previous month, so check if the date makes it a calendar month out.
                isValid = (dob.Day > originalDob.Day);
                break;
            case 1:
                // The month is the next month, so check if the date makes it a calendar month out.
                isValid = (dob.Day < originalDob.Day);
                break;
            default:
                // Either zero or greater than 1 month difference, so not ok.
                isValid = false;
                break;
        }
        if (!isValid)
            return Json("Date of Birth cannot be greater than one month either side of the date we hold.", JsonRequestBehavior.AllowGet);
    }
    else
    {
        return Json("Date of Birth is invalid.", JsonRequestBehavior.AllowGet);
    }
    return Json(true, JsonRequestBehavior.AllowGet);
}

전체 답변을 원할 때 허용되는 답변이 완벽하게 작동합니다.

부분 개월이 필요했습니다. 이것이 부분 개월 동안 내가 생각해 낸 해결책입니다.

    /// <summary>
    /// Calculate the difference in months.
    /// This will round up to count partial months.
    /// </summary>
    /// <param name="lValue"></param>
    /// <param name="rValue"></param>
    /// <returns></returns>
    public static int MonthDifference(DateTime lValue, DateTime rValue)
    {
        var yearDifferenceInMonths = (lValue.Year - rValue.Year) * 12;
        var monthDifference = lValue.Month - rValue.Month;

        return yearDifferenceInMonths + monthDifference + 
            (lValue.Day > rValue.Day
                ? 1 : 0); // If end day is greater than start day, add 1 to round up the partial month
    }

나는 또한 부분 년에 대한 동일한 요구와 년 차이가 필요했습니다. 내가 생각해 낸 해결책은 다음과 같습니다.

    /// <summary>
    /// Calculate the differences in years.
    /// This will round up to catch partial months.
    /// </summary>
    /// <param name="lValue"></param>
    /// <param name="rValue"></param>
    /// <returns></returns>
    public static int YearDifference(DateTime lValue, DateTime rValue)
    {
        return lValue.Year - rValue.Year +
               (lValue.Month > rValue.Month // Partial month, same year
                   ? 1
                   : ((lValue.Month = rValue.Month) 
                     && (lValue.Day > rValue.Day)) // Partial month, same year and month
                   ? 1 : 0);
    }

case IntervalType.Month:
    returnValue = start.AddMonths(-end.Month).Month.ToString();
    break;
case IntervalType.Year:
    returnValue = (start.Year - end.Year).ToString();
    break;

몇 달의 문제는 실제로 간단한 척도가 아니며 크기가 일정하지 않다는 것입니다. 포함시키려는 규칙을 정의하고 거기서부터 작업해야합니다. 예를 들어 1 월 1 일에서 2 월 1 일까지-2 개월이 포함되어 있다고 주장하거나 1 개월이라고 말할 수 있습니다. 그렇다면 "1 월 1 일 20:00"부터 "2 월 1 일 00:00"은 한 달 전체가 아닙니다. 0입니까? 1? 다른 방법은 어떻습니까 (1 월 1 일 00:00부터 2 월 1 일 20:00까지) ... 1? 2?

먼저 규칙을 정의한 다음 직접 코드를 작성해야합니다.


1사이 에 결과를 표시하려는 경우 :28th Feb1st March

DateTime date1, date2;
int monthSpan = (date2.Year - date1.Year) * 12 + date2.Month - date1.Month

라이브러리는 DateTime의 모든 부분을 고려하여 월 차이를 계산합니다.

// ----------------------------------------------------------------------
public void DateDiffSample()
{
  DateTime date1 = new DateTime( 2009, 11, 8, 7, 13, 59 );
  Console.WriteLine( "Date1: {0}", date1 );
  // > Date1: 08.11.2009 07:13:59
  DateTime date2 = new DateTime( 2011, 3, 20, 19, 55, 28 );
  Console.WriteLine( "Date2: {0}", date2 );
  // > Date2: 20.03.2011 19:55:28

  DateDiff dateDiff = new DateDiff( date1, date2 );

  // differences
  Console.WriteLine( "DateDiff.Years: {0}", dateDiff.Years );
  // > DateDiff.Years: 1
  Console.WriteLine( "DateDiff.Quarters: {0}", dateDiff.Quarters );
  // > DateDiff.Quarters: 5
  Console.WriteLine( "DateDiff.Months: {0}", dateDiff.Months );
  // > DateDiff.Months: 16
  Console.WriteLine( "DateDiff.Weeks: {0}", dateDiff.Weeks );
  // > DateDiff.Weeks: 70
  Console.WriteLine( "DateDiff.Days: {0}", dateDiff.Days );
  // > DateDiff.Days: 497
  Console.WriteLine( "DateDiff.Weekdays: {0}", dateDiff.Weekdays );
  // > DateDiff.Weekdays: 71
  Console.WriteLine( "DateDiff.Hours: {0}", dateDiff.Hours );
  // > DateDiff.Hours: 11940
  Console.WriteLine( "DateDiff.Minutes: {0}", dateDiff.Minutes );
  // > DateDiff.Minutes: 716441
  Console.WriteLine( "DateDiff.Seconds: {0}", dateDiff.Seconds );
  // > DateDiff.Seconds: 42986489

  // elapsed
  Console.WriteLine( "DateDiff.ElapsedYears: {0}", dateDiff.ElapsedYears );
  // > DateDiff.ElapsedYears: 1
  Console.WriteLine( "DateDiff.ElapsedMonths: {0}", dateDiff.ElapsedMonths );
  // > DateDiff.ElapsedMonths: 4
  Console.WriteLine( "DateDiff.ElapsedDays: {0}", dateDiff.ElapsedDays );
  // > DateDiff.ElapsedDays: 12
  Console.WriteLine( "DateDiff.ElapsedHours: {0}", dateDiff.ElapsedHours );
  // > DateDiff.ElapsedHours: 12
  Console.WriteLine( "DateDiff.ElapsedMinutes: {0}", dateDiff.ElapsedMinutes );
  // > DateDiff.ElapsedMinutes: 41
  Console.WriteLine( "DateDiff.ElapsedSeconds: {0}", dateDiff.ElapsedSeconds );
  // > DateDiff.ElapsedSeconds: 29
} // DateDiffSample

아래는 실제로 가장 정확한 방법입니다. "1 개월"의 정의는 월에 따라 달라 지므로 다른 답변들도이를 고려하지 않습니다! 당신이 프레임 워크에 내장되지 않은 문제에 대한 자세한 정보를 원하는 경우, 당신은이 게시물에 읽을 수 있습니다 .Years & .Months와 진짜 시간 범위 개체 (단, 해당 게시물을 읽는 것은 이해하고 아래의 기능을 사용할 필요가 없습니다, 그것은 다른 사람들이 사용하기를 좋아하는 근사치의 본질적인 부정확성없이 100 % 작동합니다. 그리고 .ReverseIt 기능을 프레임 워크에있는 내장 .Reverse 기능으로 자유롭게 교체하십시오 (완전히 여기에 있습니다).

최대 몇 년 (6 개 부품 / 세그먼트 포함)까지 날짜 / 시간 정확도, 초 및 분 또는 초, 분 및 일 수에 관계없이 얻을 수 있습니다. 상위 2 개를 지정하고 1 년이 지난 경우 "1 년 3 개월 전"을 반환하고 두 개의 세그먼트를 요청했기 때문에 나머지는 반환하지 않습니다. 몇 시간이 지난 경우 "2 시간 1 분 전"만 반환됩니다. 물론 1, 2, 3, 4, 5 또는 6 세그먼트를 지정하면 동일한 규칙이 적용됩니다 (초, 분, 시간, 일, 월, 연도는 6 가지 유형 만 만들기 때문에 6으로 최대 값을 초과 함). 또한 모든 유형에 대해 1 분 이상인지 여부에 따라 "분"대 "분"과 같은 그래머 문제를 수정하며 생성 된 "문자열"은 문법적으로 항상 정확합니다.

다음은 사용할 예제입니다. bAllowSegments는 표시 할 세그먼트 수를 식별합니다. 즉, 3 인 경우 반환 문자열은 (예를 들어) ... "3 years, 2 months and 13 days"(상위 3 시간으로시, 분 및 초는 포함하지 않음 ) 그러나 며칠 전과 같이 날짜가 최신 날짜 인 경우 동일한 세그먼트 (3)를 지정하면 "4 days, 1 hour and 13 minutes ago"대신 반환 되므로 모든 것이 고려됩니다.

if bAllowSegments is 2 it would return "3 years and 2 months" and if 6 (maximum value) would return "3 years, 2 months, 13 days, 13 hours, 29 minutes and 9 seconds", but, be reminded that it will NEVER RETURN something like this "0 years, 0 months, 0 days, 3 hours, 2 minutes and 13 seconds ago" as it understands there is no date data in the top 3 segments and ignores them, even if you specify 6 segments, so don't worry :). Of course, if there is a segment with 0 in it, it will take that into account when forming the string, and will display as "3 days and 4 seconds ago" and ignoring the "0 hours" part! Enjoy and please comment if you like.

 Public Function RealTimeUntilNow(ByVal dt As DateTime, Optional ByVal bAllowSegments As Byte = 2) As String
  ' bAllowSegments identifies how many segments to show... ie: if 3, then return string would be (as an example)...
  ' "3 years, 2 months and 13 days" the top 3 time categories are returned, if bAllowSegments is 2 it would return
  ' "3 years and 2 months" and if 6 (maximum value) would return "3 years, 2 months, 13 days, 13 hours, 29 minutes and 9 seconds"
  Dim rYears, rMonths, rDays, rHours, rMinutes, rSeconds As Int16
  Dim dtNow = DateTime.Now
  Dim daysInBaseMonth = Date.DaysInMonth(dt.Year, dt.Month)

  rYears = dtNow.Year - dt.Year
  rMonths = dtNow.Month - dt.Month
  If rMonths < 0 Then rMonths += 12 : rYears -= 1 ' add 1 year to months, and remove 1 year from years.
  rDays = dtNow.Day - dt.Day
  If rDays < 0 Then rDays += daysInBaseMonth : rMonths -= 1
  rHours = dtNow.Hour - dt.Hour
  If rHours < 0 Then rHours += 24 : rDays -= 1
  rMinutes = dtNow.Minute - dt.Minute
  If rMinutes < 0 Then rMinutes += 60 : rHours -= 1
  rSeconds = dtNow.Second - dt.Second
  If rSeconds < 0 Then rSeconds += 60 : rMinutes -= 1

  ' this is the display functionality
  Dim sb As StringBuilder = New StringBuilder()
  Dim iSegmentsAdded As Int16 = 0

  If rYears > 0 Then sb.Append(rYears) : sb.Append(" year" & If(rYears <> 1, "s", "") & ", ") : iSegmentsAdded += 1
  If bAllowSegments = iSegmentsAdded Then GoTo parseAndReturn

  If rMonths > 0 Then sb.AppendFormat(rMonths) : sb.Append(" month" & If(rMonths <> 1, "s", "") & ", ") : iSegmentsAdded += 1
  If bAllowSegments = iSegmentsAdded Then GoTo parseAndReturn

  If rDays > 0 Then sb.Append(rDays) : sb.Append(" day" & If(rDays <> 1, "s", "") & ", ") : iSegmentsAdded += 1
  If bAllowSegments = iSegmentsAdded Then GoTo parseAndReturn

  If rHours > 0 Then sb.Append(rHours) : sb.Append(" hour" & If(rHours <> 1, "s", "") & ", ") : iSegmentsAdded += 1
  If bAllowSegments = iSegmentsAdded Then GoTo parseAndReturn

  If rMinutes > 0 Then sb.Append(rMinutes) : sb.Append(" minute" & If(rMinutes <> 1, "s", "") & ", ") : iSegmentsAdded += 1
  If bAllowSegments = iSegmentsAdded Then GoTo parseAndReturn

  If rSeconds > 0 Then sb.Append(rSeconds) : sb.Append(" second" & If(rSeconds <> 1, "s", "") & "") : iSegmentsAdded += 1

parseAndReturn:

  ' if the string is entirely empty, that means it was just posted so its less than a second ago, and an empty string getting passed will cause an error
  ' so we construct our own meaningful string which will still fit into the "Posted * ago " syntax...

  If sb.ToString = "" Then sb.Append("less than 1 second")

  Return ReplaceLast(sb.ToString.TrimEnd(" ", ",").ToString, ",", " and")

 End Function

물론, "ReplaceLast"함수가 필요합니다.이 함수는 소스 문자열과 교체 할 항목을 지정하는 인수 및이를 대체하려는 항목을 지정하는 인수가 필요하며 해당 문자열의 마지막 발생 만 대체합니다. ... 내가 없거나 구현하고 싶지 않은 경우 내 것을 포함 시켰으므로 여기에서는 수정없이 "있는 그대로"작동합니다. 리버스 기능이 더 이상 필요하지 않다는 것을 알고 있습니다 (.net에 있음). ReplaceLast 및 ReverseIt 기능은 .net 이전 일부터 이월되므로 날짜가 어떻게 생겼는지 변명하십시오 (여전히 100 % 작동, 사용 중임) 10 년 이상 동안, 버그가 없다고 보증 할 수 있습니다) : ...). 건배.

<Extension()> _ 
Public Function ReplaceLast(ByVal sReplacable As String, ByVal sReplaceWhat As String, ByVal sReplaceWith As String) As String 
    ' let empty string arguments run, incase we dont know if we are sending and empty string or not. 
    sReplacable = sReplacable.ReverseIt 
    sReplacable = Replace(sReplacable, sReplaceWhat.ReverseIt, sReplaceWith.ReverseIt, , 1) ' only does first item on reversed version! 
    Return sReplacable.ReverseIt.ToString 
End Function 

<Extension()> _ 
Public Function ReverseIt(ByVal strS As String, Optional ByVal n As Integer = -1) As String 
    Dim strTempX As String = "", intI As Integer 

    If n > strS.Length Or n = -1 Then n = strS.Length 

    For intI = n To 1 Step -1 
        strTempX = strTempX + Mid(strS, intI, 1) 
    Next intI 

    ReverseIt = strTempX + Right(strS, Len(strS) - n) 

End Function 

정확한 숫자를 원한다면, 당신이 말한 것처럼 어떤 달을 다루고 있는지, 윤년을 다루고 있는지를 알아야하기 때문에 Timespan에서만 할 수는 없습니다.

대략적인 숫자를 사용하거나 원래 DateTimes로 약간의 피싱을 수행하십시오.


http://www.astro.uu.nl/~strous/AA/en/reken/juliaansedag.html

Gregorian Date에서 Julian day number 로 시간을 변환 할 수있는 경우 , 월, 일, 초 등을 얻기 위해 double을 입력 할 수있는 zulian day number의 비교를 수행하는 연산자를 작성할 수 있습니다. Gregorian에서 Julian로 변환하기위한 알고리즘 링크


idiomatic-c #에서는이를 정확하게 수행 할 수있는 방법이 없습니다. 사람들이 코딩 한이 CodeProject 예제 와 같은 몇 가지 해결 방법 있습니다.


몇 달과 몇 년을 다루는 경우 매월 며칠이 지났으며 윤년인지 알고 싶은 것이 필요합니다.

그레고리력 및 다른 문화권 별 달력 구현을 입력하십시오 .

Calendar는 두 시점 간의 차이를 직접 계산하는 방법을 제공하지 않지만 다음과 같은 방법을 제공합니다.

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

DateTime start = new DateTime(2003, 12, 25);
DateTime end = new DateTime(2009, 10, 6);
int compMonth = (end.Month + end.Year * 12) - (start.Month + start.Year * 12);
double daysInEndMonth = (end - end.AddMonths(1)).Days;
double months = compMonth + (start.Day - end.Day) / daysInEndMonth;

이 메소드는 3 번째 요소가 포함 된 목록을 리턴합니다. 첫 번째는 연도, 두 번째는 월, 종료 요소는 일입니다.

public static List<int> GetDurationInEnglish(DateTime from, DateTime to)
    {
        try
        {
            if (from > to)
                return null;

            var fY = from.Year;
            var fM = from.Month;
            var fD = DateTime.DaysInMonth(fY, fM);

            var tY = to.Year;
            var tM = to.Month;
            var tD = DateTime.DaysInMonth(tY, tM);

            int dY = 0;
            int dM = 0;
            int dD = 0;

            if (fD > tD)
            {
                tM--;

                if (tM <= 0)
                {
                    tY--;
                    tM = 12;
                    tD += DateTime.DaysInMonth(tY, tM);
                }
                else
                {
                    tD += DateTime.DaysInMonth(tY, tM);
                }
            }
            dD = tD - fD;

            if (fM > tM)
            {
                tY--;

                tM += 12;
            }
            dM = tM - fM;

            dY = tY - fY;

            return new List<int>() { dY, dM, dD };
        }
        catch (Exception exception)
        {
            //todo: log exception with parameters in db

            return null;
        }
    }

정확한 것으로 판명 된 달의 차이를 얻는 데 기여한 내용은 다음과 같습니다.

namespace System
{
     public static class DateTimeExtensions
     {
         public static Int32 DiffMonths( this DateTime start, DateTime end )
         {
             Int32 months = 0;
             DateTime tmp = start;

             while ( tmp < end )
             {
                 months++;
                 tmp = tmp.AddMonths( 1 );
             }

             return months;
        }
    }
}

용법:

Int32 months = DateTime.Now.DiffMonths( DateTime.Now.AddYears( 5 ) );

DiffYears라는 다른 메소드를 작성하고 while 루프에서 AddMonths 대신 위와 동일한 로직을 정확하게 적용 할 수 있습니다.


게임에 늦었지만, 이것이 누군가에게 도움이 될 것이라고 생각합니다. 대부분의 사람들은 달이 다르게 변한다는 사실을 제외하고 날짜별로 매달 측정하는 경향이 있습니다. 그 사고 프레임을 사용하여 우리를 위해 날짜를 비교하는 하나의 라이너를 만들었습니다. 다음 프로세스를 사용하십시오.

  1. 연도를 비교할 때 1을 초과하는 연도에 12를 곱하면 1 년보다 작을 수있는 경우는 없습니다.
  2. 연말이 더 큰 경우 현재 날짜가 전날 2A보다 크거나 같은지 평가해야합니다. 종료일이 크거나 같으면 현재 월을 취한 다음 12 개월을 더하여 시작 월 2B의 월을 뺍니다. 종료일이 시작일보다 적은 경우 빼기 전에 시작 월에 1을 추가한다는 점을 제외하고 위와 동일하게 수행합니다.
  3. 연말이 크지 않은 경우 2A / 2B와 동일하게 수행하지만 연중 평가할 필요가 없으므로 12 개월을 추가하지 않습니다.

        DateTime date = new DateTime(2003, 11, 25);
        DateTime today = new DateTime(2004, 12, 26);
        var time = (today.Year - date.Year > 1 ? (today.Year - date.Year - 1) * 12 : 0) +  (today.Year > date.Year ? (today.Day >= date.Day ? today.Month + 12 - date.Month : today.Month + 12 - (date.Month + 1)) : (today.Day >= date.Day ? today.Month - date.Month : today.Month - (date.Month + 1)));
    

두 날짜 사이의 월 수를 계산하십시오.

$date1 = '2017-01-20';
$date2 = '2019-01-20';

$ts1 = strtotime($date1);
$ts2 = strtotime($date2);

$year1 = date('Y', $ts1);
$year2 = date('Y', $ts2);

$month1 = date('m', $ts1);
$month2 = date('m', $ts2);

echo $joining_months = (($year2 - $year1) * 12) + ($month2 - $month1);

참고 URL : https://stackoverflow.com/questions/1525990/calculating-the-difference-in-months-between-two-dates

반응형