Search code examples
javascripttypescriptrxjsmomentjscountdown

Momentjs countdown - Duration is showing negative numbers


I am tring to create a countdown with MomentJS (2.22.2) and Rxjs (6.2.2) interval. But when I reach some points in time my countdown goes crazy and outputs negative numbers, where it should have, for example, substracted a day and started at 23 hours.

Any help on how I should fix this?


Example

local time: 2018-09-05T18:49

End time: 2018-11-03T18:00

this results in:

Negative countdown


My code

'this.days', 'this.hours', 'this.minutes' & 'this.seconds' are local variables that hold a string representation of the resulting time (string format, because I want to show leading zero's)

interval(1000).subscribe(() => {
      const now = moment();
      let timeLeft = this.endDate.diff(now, 'milliseconds', true);
      let endDate = moment(this.endDate); // Use 'moment' to make a new copy

      // Days
      const days = Math.floor(moment.duration(timeLeft).asDays());
      console.warn(moment.duration(timeLeft).asDays());
      this.days = Countdown.addLeadingZeros(days.toString(), 3);

      endDate = endDate.subtract(days, 'days');
      timeLeft = endDate.diff(now, 'milliseconds', true);

      // Hours
      const hours = Math.floor(moment.duration(timeLeft).asHours());
      console.warn(Math.round(moment.duration(timeLeft).asHours()));
      this.hours = Countdown.addLeadingZeros(hours.toString(), 2);

      endDate = endDate.subtract(hours, 'hours');
      timeLeft = endDate.diff(now, 'milliseconds', true);

      // Minutes
      const minutes = Math.floor(moment.duration(timeLeft).asMinutes());
      this.minutes = Countdown.addLeadingZeros(minutes.toString(), 2);

      endDate = endDate.subtract(minutes, 'minutes');
      timeLeft = endDate.diff(now, 'milliseconds', true);

      // Seconds
      const seconds = Math.floor(moment.duration(timeLeft).asSeconds());
      this.seconds = Countdown.addLeadingZeros(seconds.toString(), 2);
});

Does anyone see what I am doing wrong here or how I could improve this code?


Solution

  • The negative numbers arise in your code because of daylight-saving time changes.

    Here in the UK there is a change of daylight-savings time between 2018-09-05 and 2018-11-03. In fact it is on 2018-10-28. I can reproduce your problem if I choose two dates on either side of this, but not if both dates are on the same side. I'm guessing that where you live there is also a change of daylight-savings time between 2018-09-05 and 2018-11-03.

    The simplest way to avoid problems like this is to calculate the time difference using times in UTC. Instead of writing

      const now = moment();
    

    write

      const now = moment().utc();
    

    and ensure that this.endDate is created in UTC not local time.