3

I am trying to calculate difference between two dates in days. However, when the two dates are in different months the days in the previous month are discarded.

For instance, if start date is March 31, and end date is April 1st, the difference is 0.

HTML:

<ngb-datepicker #dp (select)="onDateSelection($event)" [displayMonths]="2" [dayTemplate]="t" outsideDays="hidden">
    </ngb-datepicker>

    <ng-template #t let-date let-focused="focused">
      <span class="custom-day"
            [class.focused]="focused"
            [class.range]="isRange(date)"
            [class.faded]="isHovered(date) || isInside(date)"
            (mouseenter)="hoveredDate = date"
            (mouseleave)="hoveredDate = null">
        {{ date.day }}
      </span>
    </ng-template>

    <p>Number of selected dates: {{DiffDate}}</p>


    <pre>From: {{ fromDate | json }} </pre>
    <pre>To: {{ toDate | json }} </pre> 

Typsript File:

    import {Component} from '@angular/core';
    import {NgbDate, NgbCalendar} from '@ng-bootstrap/ng-bootstrap';

    @Component({
      selector: 'ngbd-datepicker-range',
      templateUrl: './datepicker-range.html',
      styles: [`
        .custom-day {
          text-align: center;
          padding: 0.185rem 0.25rem;
          display: inline-block;
          height: 2rem;
          width: 2rem;
        }
        .custom-day.focused {
          background-color: #e6e6e6;
        }
        .custom-day.range, .custom-day:hover {
          background-color: rgb(2, 117, 216);
          color: white;
        }
        .custom-day.faded {
          background-color: rgba(2, 117, 216, 0.5);
        }
      `]
    })
    export class NgbdDatepickerRange {

      hoveredDate: NgbDate;

      fromDate: NgbDate;
      toDate: NgbDate;
      DiffDate;
      enddate;
      startDate;

      constructor(calendar: NgbCalendar) {
        this.fromDate = calendar.getToday();
        this.toDate = calendar.getNext(calendar.getToday(), 'd', 10);
      }

      onDateSelection(date: NgbDate) {
        if (!this.fromDate && !this.toDate) {
          this.fromDate = date;
        } else if (this.fromDate && !this.toDate && date.after(this.fromDate)) {
          this.toDate = date;
        } else {
          this.toDate = null;
          this.fromDate = date;
        }
        this.enddate=new Date (this.toDate.year,this.toDate.month,this.toDate.day);

        this.startDate=new Date (this.fromDate.year,this.fromDate.month,this.fromDate.day);

        this.DiffDate=Math.floor((Date.UTC(this.enddate.getFullYear(),this.enddate.getMonth(),this.enddate.getDate())-Date.UTC(this.startDate.getFullYear(),this.startDate.getMonth(),this.startDate.getDate()) )/(1000 * 60 * 60 * 24));
        //this.DiffDate=(this.DiffDate/86400000);

      }

      isHovered(date: NgbDate) {
        return this.fromDate && !this.toDate && this.hoveredDate && date.after(this.fromDate) && date.before(this.hoveredDate);
      }

      isInside(date: NgbDate) {
        return date.after(this.fromDate) && date.before(this.toDate);
      }

      isRange(date: NgbDate) {
        return date.equals(this.fromDate) || date.equals(this.toDate) || this.isInside(date) || this.isHovered(date);
      }
    }

If two days are in the same month, it is working fine.

Appreciate your support in advance.

update: I figured how to fix it. Everything is working as expected, except when the day selected is the last day of the month. A live demo can be found below:

The DEMO Here

For instance, start date: March 19, end date: Marc 21st. Difference is 2 days.

But when start day selected is March 31st, it is calculated as May 1st:

Any idea what is going wrong? Thanks in advance.

Kurt Hamilton
  • 12,490
  • 1
  • 24
  • 40
AbdalRahman Farag
  • 197
  • 1
  • 8
  • 18
  • 2
    I think just convert the dates to milliseconds then subtract and then convert to days. Might work. – fastAsTortoise Mar 09 '19 at 11:09
  • 1
    (dateTo.valueOf() - dateFrom.valueOf()) / 86400000 – MRsa Mar 09 '19 at 11:11
  • Thanks, I tried this, but not working as well – AbdalRahman Farag Mar 09 '19 at 11:29
  • Check this: https://stackoverflow.com/questions/9129928/how-to-calculate-number-of-days-between-two-dates – robert Mar 09 '19 at 11:34
  • Thanks...I tried below, but still not working: this.DiffDate=Math.floor((Date.UTC(this.enddate.getFullYear(),this.enddate.getMonth(),this.enddate.getDate())-Date.UTC(this.startDate.getFullYear(),this.startDate.getMonth(),this.startDate.getDate()) )/(1000 * 60 * 60 * 24)); Any suggestion – AbdalRahman Farag Mar 09 '19 at 11:45
  • Below lines are only working if we are on the same month...if different months, the difference in days is 0: this.enddate=new Date (this.toDate.year,this.toDate.month,this.toDate.day); this.startDate=new Date (this.fromDate.year,this.fromDate.month,this.fromDate.day); this.DiffDate=Math.floor((Date.UTC(this.enddate.getFullYear(),this.enddate.getMonth(),this.enddate.getDate())-Date.UTC(this.startDate.getFullYear(),this.startDate.getMonth(),this.startDate.getDate()) )/(1000 * 60 * 60 * 24)); – AbdalRahman Farag Mar 09 '19 at 11:51
  • in new Date, month beging by 0, 0=january, 1=february..., in ngb-bootstrap, fromDate.month begin by 1, 1=january,2=february.. – Eliseo Mar 09 '19 at 14:51

3 Answers3

6

Using moment's diff function you can get the proper 1 day diff between these two dates.

this.firstDate = moment('2019/03/31');
this.secondDate = moment('2019/04/01');
this.diffInDays = Math.abs(this.firstDate.diff(this.secondDate, 'days')); 

See this stackblitz for demo.

Update:

I forked your stackblitz. Generally created two new functions and cleaned up some duplication.

NgbDate has three properties year, month and day. The important thing is that month is starting from 1 (not from zero for JS native Date object) See NgbDate docs here.

  private createDateFromNgbDate(ngbDate: NgbDate): Date {
    const date: Date = new Date(Date.UTC(ngbDate.year, ngbDate.month-1, ngbDate.day));  
    return date;
  }

And a separate function to calculate the diff in days like this:

private calcDaysDiff(): number {
    const fromDate: Date = this.createDateFromNgbDate(this.fromDate);
    const toDate: Date = this.createDateFromNgbDate(this.toDate);  
    const daysDiff = Math.floor(Math.abs(<any>fromDate - <any>toDate) / (1000*60*60*24));
    return daysDiff;
  }

Check the updated stackblitz and let me know if you still have issues.

robert
  • 5,742
  • 7
  • 28
  • 37
  • many thanks for your support. I updated, my code, and it is actually working. However, the issue I have when I selected dates from different months. For instance, when I select two dates from the same month, the difference is calculated correctly. However, when I select two different dates, the data is corrupted. A live demo can be found at: https://stackblitz.com/github/abdelrahman84/Vacation-Planner-Angular?fbclid=IwAR2DBGEyLKUReyLx0LLnmnSaOp3BYVjOQvZJdQCvaHGlSTXHkb4BPg0Ymt4 – AbdalRahman Farag Mar 10 '19 at 17:07
  • I can't thank you enough. This fixed my issue, and everything is working as expected. Have a wonderful day – AbdalRahman Farag Mar 11 '19 at 09:59
1

For date and time calculations user Moment.js. In your case, use difference method in Moment.js, https://momentjs.com/docs/#/displaying/difference/

var a = moment([2007, 0, 29]);
var b = moment([2007, 0, 28]);
a.diff(b, 'days') // 1
Nilupul Sandeepa
  • 748
  • 6
  • 20
0

Use this code:

const oneday = 24 * 60 * 60 * 1000;
const momentDate = new Date(this.applicationData.businessProfile.registration_date); // Replace event.value with your date value
const formattedDate = moment(momentDate).format("YYYY-MM-DD");
const formattedDatecurrent = new Date(this.now);
this.applicationData.businessProfile.registration_date=formattedDate;
console.log(formattedDate);

console.log(formattedDatecurrent);

const Difference_In_Time = Math.round(Math.abs((Number(momentDate)  - Number(formattedDatecurrent) )/oneday));
console.log(Difference_In_Time);
B. Go
  • 1,436
  • 4
  • 15
  • 22