سؤال

كيف يمكنني تحديد الفرق لكائنين Date () في JavaScript ، مع إرجاع عدد الأشهر فقط في الفرق؟

أي مساعدة ستكون رائعة :)

هل كانت مفيدة؟

المحلول

يخضع تعريف "عدد الأشهر في الفرق" للكثير من التفسير. :-)

يمكنك الحصول على العام والشهر واليوم من كائن تاريخ JavaScript. اعتمادًا على المعلومات التي تبحث عنها ، يمكنك استخدام تلك لمعرفة عدد الأشهر بين نقطتين في الوقت المناسب.

على سبيل المثال ، خارج الكفة ، هذا يكتشف عدد أشهر كاملة كذب بين تاريخين ، وليس حساب الأشهر الجزئية (على سبيل المثال ، باستثناء الشهر في كل تاريخ):

function monthDiff(d1, d2) {
    var months;
    months = (d2.getFullYear() - d1.getFullYear()) * 12;
    months -= d1.getMonth() + 1;
    months += d2.getMonth();
    return months <= 0 ? 0 : months;
}

monthDiff(
    new Date(2008, 10, 4), // November 4th, 2008
    new Date(2010, 2, 12)  // March 12th, 2010
);
// Result: 15: December 2008, all of 2009, and Jan & Feb 2010

monthDiff(
    new Date(2010, 0, 1),  // January 1st, 2010
    new Date(2010, 2, 12)  // March 12th, 2010
);
// Result: 1: February 2010 is the only full month between them

monthDiff(
    new Date(2010, 1, 1),  // February 1st, 2010
    new Date(2010, 2, 12)  // March 12th, 2010
);
// Result: 0: There are no *full* months between them

(لاحظ أن قيم الشهر في JavaScript تبدأ بـ 0 = يناير.)

إن الأشهر الكسرية في ما سبق أكثر تعقيدًا ، لأن ثلاثة أيام في شهر فبراير النموذجي هي جزء أكبر من ذلك الشهر (حوالي 10.714 ٪) عن ثلاثة أيام في أغسطس (حوالي 9.677 ٪) ، وبالطبع فبراير هو هدف متحرك اعتمادا على ما إذا كانت سنة قفزة.

هناك أيضا بعض مكتبات التاريخ والوقت متاح لجافا سكريبت الذي ربما يجعل هذا النوع من الأشياء أسهل.

نصائح أخرى

إذا لم تفكر في يوم الشهر ، فهذا هو الحل الأكثر بساطة إلى حد بعيد

function monthDiff(dateFrom, dateTo) {
 return dateTo.getMonth() - dateFrom.getMonth() + 
   (12 * (dateTo.getFullYear() - dateFrom.getFullYear()))
}


//examples
console.log(monthDiff(new Date(2000, 01), new Date(2000, 02))) // 1
console.log(monthDiff(new Date(1999, 02), new Date(2000, 02))) // 12 full year
console.log(monthDiff(new Date(2009, 11), new Date(2010, 0))) // 1

كن على علم بأن فهرس الشهر يعتمد على 0. هذا يعني ذاك January = 0 و December = 11.

في بعض الأحيان قد ترغب في الحصول على كمية الأشهر بين تاريخين متجاهلين تمامًا الجزء النهاري. على سبيل المثال ، إذا كان لديك تاريخان- 2013/06/21 و 2013/10/18- وأنت تهتم فقط بقطع الغيار 2013/06 و 2013/10 ، إليك السيناريوهات والحلول الممكنة:

var date1=new Date(2013,5,21);//Remember, months are 0 based in JS
var date2=new Date(2013,9,18);
var year1=date1.getFullYear();
var year2=date2.getFullYear();
var month1=date1.getMonth();
var month2=date2.getMonth();
if(month1===0){ //Have to take into account
  month1++;
  month2++;
}
var numberOfMonths; 

1. إذا كنت تريد فقط عدد الأشهر بين التاريخين باستثناء كل من الشهر 1 وشهر 2

numberOfMonths = (year2 - year1) * 12 + (month2 - month1) - 1;

2. إذا كنت تريد تضمين أي من الأشهر

numberOfMonths = (year2 - year1) * 12 + (month2 - month1);

3. إذا كنت ترغب في تضمين كلا الشهرين

numberOfMonths = (year2 - year1) * 12 + (month2 - month1) + 1;

فيما يلي وظيفة توفر بدقة عدد الأشهر بين تواريخين.
إن السلوك الافتراضي لا يحسب سوى أشهر كاملة ، على سبيل المثال ، 3 أشهر ويوم واحد سيؤدي إلى اختلاف 3 أشهر. يمكنك منع ذلك عن طريق ضبط roundUpFractionalMonths بارام كما true, ، لذلك سيتم إرجاع الفرق لمدة 3 أشهر و 1 يوم 4 أشهر.

الإجابة المقبولة أعلاه (إجابة TJ Crowder) ليست دقيقة ، فهي تُرجع القيم الخاطئة في بعض الأحيان.

علي سبيل المثال، monthDiff(new Date('Jul 01, 2015'), new Date('Aug 05, 2015')) عائدات 0 وهذا خطأ من الواضح. الفرق الصحيح هو إما شهر كامل أو شهرين تقريبًا.

ها هي الوظيفة التي كتبتها:

function getMonthsBetween(date1,date2,roundUpFractionalMonths)
{
    //Months will be calculated between start and end dates.
    //Make sure start date is less than end date.
    //But remember if the difference should be negative.
    var startDate=date1;
    var endDate=date2;
    var inverse=false;
    if(date1>date2)
    {
        startDate=date2;
        endDate=date1;
        inverse=true;
    }

    //Calculate the differences between the start and end dates
    var yearsDifference=endDate.getFullYear()-startDate.getFullYear();
    var monthsDifference=endDate.getMonth()-startDate.getMonth();
    var daysDifference=endDate.getDate()-startDate.getDate();

    var monthCorrection=0;
    //If roundUpFractionalMonths is true, check if an extra month needs to be added from rounding up.
    //The difference is done by ceiling (round up), e.g. 3 months and 1 day will be 4 months.
    if(roundUpFractionalMonths===true && daysDifference>0)
    {
        monthCorrection=1;
    }
    //If the day difference between the 2 months is negative, the last month is not a whole month.
    else if(roundUpFractionalMonths!==true && daysDifference<0)
    {
        monthCorrection=-1;
    }

    return (inverse?-1:1)*(yearsDifference*12+monthsDifference+monthCorrection);
};

إذا كنت بحاجة إلى حساب الأشهر الكاملة ، بغض النظر عن أن الشهر 28 أو 29 أو 30 أو 31 يومًا. أدناه يجب أن تعمل.

var months = to.getMonth() - from.getMonth() 
    + (12 * (to.getFullYear() - from.getFullYear()));

if(to.getDate() < from.getDate()){
    months--;
}
return months;

هذه نسخة ممتدة من الإجابة https://stackoverflow.com/a/4312956/1987208 ولكن يحدد الحالة التي تحسب فيها شهر واحد للقضية من 31 يناير إلى الأول من فبراير (يوم واحد).

هذا سوف يغطي ما يلي.

  • من 1 يناير إلى 31 يناير ---> 30 يومًا ---> سوف يؤدي إلى 0 (منطقي لأنه ليس شهرًا كاملاً)
  • 1 فبراير إلى الأول من مارس ---> 28 أو 29 يومًا ---> سيؤدي إلى 1 (منطقي لأنه شهر كامل)
  • من 15 فبراير إلى 15 مارس ---> 28 أو 29 يومًا ---> سوف يؤدي إلى 1 (منطقي منذ تمرير شهر)
  • 31 يناير إلى الأول من فبراير ---> يوم واحد ---> سوف يؤدي إلى 0 (واضحة ولكن الإجابة المذكورة في النشر تنتج في شهر واحد)

الفرق في أشهر بين تاريخين في جافا سكريبت:

 start_date = new Date(year, month, day); //Create start date object by passing appropiate argument
 end_date = new Date(new Date(year, month, day)

إجمالي الأشهر بين start_date و end_date:

 total_months = (end_date.getFullYear() - start_date.getFullYear())*12 + (end_date.getMonth() - start_date.getMonth())

أعلم أن هذا متأخر حقًا ، لكن نشره على أي حال فقط في حال يساعد الآخرين. فيما يلي وظيفة توصلت إليها ، يبدو أنها تقوم بعمل جيد في حساب الاختلافات في أشهر بين تاريخين. من المسلم به أن الأمر أكثر شهرة من Mr.Crowder ، ولكنه يوفر نتائج أكثر دقة عن طريق التنقل عبر كائن التاريخ. إنه في AS3 ولكن يجب أن تكون قادرًا على إسقاط الكتابة القوية وسيكون لديك JS. لا تتردد في جعلها أجمل النظر أي شخص هناك!

    function countMonths ( startDate:Date, endDate:Date ):int
    {
        var stepDate:Date = new Date;
        stepDate.time = startDate.time;
        var monthCount:int;

        while( stepDate.time <= endDate.time ) { 
            stepDate.month += 1;
            monthCount += 1;
        }           

        if ( stepDate != endDate ) { 
            monthCount -= 1;
        }

        return monthCount;
    }

النظر في كل تاريخ من حيث الأشهر ، ثم اطرح لإيجاد الفرق.

var past_date = new Date('11/1/2014');
var current_date = new Date();

var difference = (current_date.getFullYear()*12 + current_date.getMonth()) - (past_date.getFullYear()*12 + past_date.getMonth());

سيحصل هذا على الفرق بين الأشهر بين التاريخين ، متجاهلين الأيام.

للتوسع في إجابة @TJ ، إذا كنت تبحث عن أشهر بسيطة ، بدلاً من أشهر التقويم الكاملة ، يمكنك فقط التحقق مما إذا كان تاريخ D2 أكبر من أو يساوي من D1. أي إذا كان D2 في وقت لاحق في شهره من D1 في شهره ، فهناك شهر آخر. لذلك يجب أن تكون قادرًا على القيام بذلك:

function monthDiff(d1, d2) {
    var months;
    months = (d2.getFullYear() - d1.getFullYear()) * 12;
    months -= d1.getMonth() + 1;
    months += d2.getMonth();
    // edit: increment months if d2 comes later in its month than d1 in its month
    if (d2.getDate() >= d1.getDate())
        months++
    // end edit
    return months <= 0 ? 0 : months;
}

monthDiff(
    new Date(2008, 10, 4), // November 4th, 2008
    new Date(2010, 2, 12)  // March 12th, 2010
);
// Result: 16; 4 Nov – 4 Dec '08, 4 Dec '08 – 4 Dec '09, 4 Dec '09 – 4 March '10

هذا لا يفسر تمامًا مشكلات الوقت (على سبيل المثال 3 مارس في الساعة 4:00 مساءً و 3 أبريل في الساعة 3:00 مساءً) ، لكنه أكثر دقة ولمجرد خطين من التعليمات البرمجية.

هناك طريقتان ، رياضيات وسريعة ، ولكن تخضع للتقلبات في التقويم ، أو التكرار والبطيء ، ولكنهم يتعاملون مع جميع الشذوذ (أو على الأقل مندوبون يتعاملون معهم مع مكتبة تم اختبارها جيدًا).

إذا قمت بالتكرار من خلال التقويم ، فإن زيادة تاريخ البدء بمقدار شهر واحد ومعرفة ما إذا كنا نمر تاريخ الانتهاء. هذا المندوب الشذوذ معالجة الفصول المدمجة في التاريخ () ، ولكن يمكن أن يكون بطيئا لو أنت تفعل هذا لعدد كبير من التواريخ. إجابة جيمس تأخذ هذا النهج. بقدر ما لا أحب الفكرة ، أعتقد أن هذا هو النهج "الأكثر أمانًا" ، وإذا كنت تفعل فقط واحد الحساب ، اختلاف الأداء حقًا ضئيل. نميل إلى محاولة الإفراط في تحسين المهام التي لن يتم تنفيذها إلا مرة واحدة.

الآن، لو أنت تقوم بحساب هذه الوظيفة على مجموعة بيانات ، ربما لا ترغب في تشغيل هذه الوظيفة على كل صف (أو لا سمح الله ، عدة مرات لكل سجل). في هذه الحالة ، يمكنك استخدام أي من الإجابات الأخرى هنا تقريبًا إلا الجواب المقبول ، وهو خطأ (الفرق بين new Date() و new Date() هو -1)؟

إليكم طعنتي في نهج رياضي وسريع ، والذي يفسر أطوال الشهر المختلفة وسنوات القفز. يجب عليك حقًا استخدام وظيفة كهذه فقط إذا كنت ستطبق هذا على مجموعة بيانات (القيام بهذا الحساب مرارًا وتكرارًا). إذا كنت بحاجة فقط إلى القيام بذلك مرة واحدة ، فاستخدم نهج جيمس التكراري أعلاه ، حيث تقوم بتفويض معالجة جميع الاستثناءات (العديدة) إلى كائن Date ().

function diffInMonths(from, to){
    var months = to.getMonth() - from.getMonth() + (12 * (to.getFullYear() - from.getFullYear()));

    if(to.getDate() < from.getDate()){
        var newFrom = new Date(to.getFullYear(),to.getMonth(),from.getDate());
        if (to < newFrom  && to.getMonth() == newFrom.getMonth() && to.getYear() %4 != 0){
            months--;
        }
    }

    return months;
}

هنا أنت تمر نهجًا آخر مع حلقات أقل:

calculateTotalMonthsDifference = function(firstDate, secondDate) {
        var fm = firstDate.getMonth();
        var fy = firstDate.getFullYear();
        var sm = secondDate.getMonth();
        var sy = secondDate.getFullYear();
        var months = Math.abs(((fy - sy) * 12) + fm - sm);
        var firstBefore = firstDate > secondDate;
        firstDate.setFullYear(sy);
        firstDate.setMonth(sm);
        firstBefore ? firstDate < secondDate ? months-- : "" : secondDate < firstDate ? months-- : "";
        return months;
}

احسب الفرق بين تاريخين تشمل جزء الشهر (الأيام).


var difference = (date2.getDate() - date1.getDate()) / 30 +
    date2.getMonth() - date1.getMonth() +
    (12 * (date2.getFullYear() - date1.getFullYear()));

علي سبيل المثال:
Date1: 24/09/2015 (24 سبتمبر 2015)
Date2: 09/11/2015 (9 نوفمبر 2015)
الفرق: 2.5 (أشهر)

هذا يجب أن يعمل بشكل جيد:

function monthDiff(d1, d2) {
    var months;
    months = (d2.getFullYear() - d1.getFullYear()) * 12;
    months += d2.getMonth() - d1.getMonth();
    return months;
}

يمكنك أيضًا التفكير في هذا الحل ، هذا function إرجاع فرق الشهر في عدد صحيح أو رقم

تمرير تاريخ البدء كأول أو آخر param, ، هو تسامح خطأ. بمعنى ، ستظل الوظيفة تعيد نفس القيمة.

const diffInMonths = (end, start) => {
   var timeDiff = Math.abs(end.getTime() - start.getTime());
   return Math.round(timeDiff / (2e3 * 3600 * 365.25));
}

const result = diffInMonths(new Date(2015, 3, 28), new Date(2010, 1, 25));

// shows month difference as integer/number
console.log(result);

function calcualteMonthYr(){
    var fromDate =new Date($('#txtDurationFrom2').val()); //date picker (text fields)
    var toDate = new Date($('#txtDurationTo2').val());

var months=0;
        months = (toDate.getFullYear() - fromDate.getFullYear()) * 12;
        months -= fromDate.getMonth();
        months += toDate.getMonth();
            if (toDate.getDate() < fromDate.getDate()){
                months--;
            }
    $('#txtTimePeriod2').val(months);
}

يتبع الرمز الشهور الكامل بين تاريخين من خلال أخذ NR من أيام الأشهر الجزئية في الاعتبار أيضًا.

var monthDiff = function(d1, d2) {
  if( d2 < d1 ) { 
    var dTmp = d2;
    d2 = d1;
    d1 = dTmp;
  }

  var months = (d2.getFullYear() - d1.getFullYear()) * 12;
  months -= d1.getMonth() + 1;
  months += d2.getMonth();

  if( d1.getDate() <= d2.getDate() ) months += 1;

  return months;
}

monthDiff(new Date(2015, 01, 20), new Date(2015, 02, 20))
> 1

monthDiff(new Date(2015, 01, 20), new Date(2015, 02, 19))
> 0

monthDiff(new Date(2015, 01, 20), new Date(2015, 01, 22))
> 0
function monthDiff(d1, d2) {
var months, d1day, d2day, d1new, d2new, diffdate,d2month,d2year,d1maxday,d2maxday;
months = (d2.getFullYear() - d1.getFullYear()) * 12;
months -= d1.getMonth() + 1;
months += d2.getMonth();
months = (months <= 0 ? 0 : months);
d1day = d1.getDate();
d2day = d2.getDate();
if(d1day > d2day)
{
    d2month = d2.getMonth();
    d2year = d2.getFullYear();
    d1new = new Date(d2year, d2month-1, d1day,0,0,0,0);
    var timeDiff = Math.abs(d2.getTime() - d1new.getTime());
          diffdate = Math.abs(Math.ceil(timeDiff / (1000 * 3600 * 24))); 
    d1new = new Date(d2year, d2month, 1,0,0,0,0);
    d1new.setDate(d1new.getDate()-1);
    d1maxday = d1new.getDate();
    months += diffdate / d1maxday;
}
else
{
      if(!(d1.getMonth() == d2.getMonth() && d1.getFullYear() == d2.getFullYear()))
    {
        months += 1;
    }
    diffdate = d2day - d1day + 1;
    d2month = d2.getMonth();
    d2year = d2.getFullYear();
    d2new = new Date(d2year, d2month + 1, 1, 0, 0, 0, 0);
    d2new.setDate(d2new.getDate()-1);
    d2maxday = d2new.getDate();
    months += diffdate / d2maxday;
}

return months;

}

أدناه سوف يجلب المنطق الفرق في الأشهر

(endDate.getFullYear()*12+endDate.getMonth())-(startDate.getFullYear()*12+startDate.getMonth())
function monthDiff(date1, date2, countDays) {

  countDays = (typeof countDays !== 'undefined') ?  countDays : false;

  if (!date1 || !date2) {
    return 0;
  }

  let bigDate = date1;
  let smallDate = date2;

  if (date1 < date2) {
    bigDate = date2;
    smallDate = date1;
  }

  let monthsCount = (bigDate.getFullYear() - smallDate.getFullYear()) * 12 + (bigDate.getMonth() - smallDate.getMonth());

  if (countDays && bigDate.getDate() < smallDate.getDate()) {
    --monthsCount;
  }

  return monthsCount;
}

انظر ما أستخدمه:

function monthDiff() {
    var startdate = Date.parseExact($("#startingDate").val(), "dd/MM/yyyy");
    var enddate = Date.parseExact($("#endingDate").val(), "dd/MM/yyyy");
    var months = 0;
    while (startdate < enddate) {
        if (startdate.getMonth() === 1 && startdate.getDate() === 28) {
            months++;
            startdate.addMonths(1);
            startdate.addDays(2);
        } else {
            months++;
            startdate.addMonths(1);
        }
    }
    return months;
}

كما أنه يحسب الأيام ويحولها في أشهر.

function monthDiff(d1, d2) {
    var months;
    months = (d2.getFullYear() - d1.getFullYear()) * 12;   //calculates months between two years
    months -= d1.getMonth() + 1; 
    months += d2.getMonth();  //calculates number of complete months between two months
    day1 = 30-d1.getDate();  
    day2 = day1 + d2.getDate();
    months += parseInt(day2/30);  //calculates no of complete months lie between two dates
    return months <= 0 ? 0 : months;
}

monthDiff(
    new Date(2017, 8, 8), // Aug 8th, 2017    (d1)
    new Date(2017, 12, 12)  // Dec 12th, 2017   (d2)
);
//return value will be 4 months 

للازدهار ،

مع لحظة يمكنك تحقيق ذلك من خلال العمل:

const monthsLeft = moment(endDate).diff(moment(startDate), 'month');
anyVar = (((DisplayTo.getFullYear() * 12) + DisplayTo.getMonth()) - ((DisplayFrom.getFullYear() * 12) + DisplayFrom.getMonth()));

تتمثل إحدى الطرق في كتابة خدمة ويب Java بسيطة (REST/JSON) التي تستخدم مكتبة Joda

http://joda-time.sourceforge.net/faq.html#datediff

لحساب الفرق بين تاريخين واستدعاء تلك الخدمة من JavaScript.

هذا يفترض أن نهايتك الخلفية في جافا.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top