Countdown timer using Moment js

JavascriptJqueryCountdownUnix TimestampMomentjs

Javascript Problem Overview


I am making a countdown timer for an event page, i used moment js for this.

Here is fiddle for this.

I am calculating date difference between event date and current date (timestamp), then using "duration" method from moment js. But the time left is not coming as expected.
Expected - 00:30m:00s
Actual - 5h:59m:00s

Code :

<script>
  $(document).ready(function(){

    var eventTime = '1366549200';
    var currentTime = '1366547400';
    var time = eventTime - currentTime;
    var duration = moment.duration(time*1000, 'milliseconds');
    var interval = 1000;

    setInterval(function(){
      duration = moment.duration(duration.asMilliseconds() - interval, 'milliseconds');
      $('.countdown').text(moment(duration.asMilliseconds()).format('H[h]:mm[m]:ss[s]'));
    }, interval);
  });
  </script>

I read the momentjs documentation to figure out the problem, but no luck.

Thanks for your time.

Update :

I end up doing like this :

<script>
  $(document).ready(function(){

    var eventTime = '1366549200';
    var currentTime = '1366547400';
    var leftTime = eventTime - currentTime;//Now i am passing the left time from controller itself which handles timezone stuff (UTC), just to simply question i used harcoded values.
    var duration = moment.duration(leftTime, 'seconds');
    var interval = 1000;

    setInterval(function(){
      // Time Out check
      if (duration.asSeconds() <= 0) {
        clearInterval(intervalId);
        window.location.reload(true); #skip the cache and reload the page from the server
      }

      //Otherwise
      duration = moment.duration(duration.asSeconds() - 1, 'seconds');
      $('.countdown').text(duration.days() + 'd:' + duration.hours()+ 'h:' + duration.minutes()+ 'm:' + duration.seconds() + 's');
    }, interval);
  });
  </script>

JS Fiddle.

Javascript Solutions


Solution 1 - Javascript

In the last statement you are converting the duration to time which also considers the timezone. I assume that your timezone is +530, so 5 hours and 30 minutes gets added to 30 minutes. You can do as given below.

var eventTime= 1366549200; // Timestamp - Sun, 21 Apr 2013 13:00:00 GMT
var currentTime = 1366547400; // Timestamp - Sun, 21 Apr 2013 12:30:00 GMT
var diffTime = eventTime - currentTime;
var duration = moment.duration(diffTime*1000, 'milliseconds');
var interval = 1000;

setInterval(function(){
  duration = moment.duration(duration - interval, 'milliseconds');
    $('.countdown').text(duration.hours() + ":" + duration.minutes() + ":" + duration.seconds())
}, interval);

Solution 2 - Javascript

Check out this plugin:

moment-countdown

> moment-countdown is a tiny moment.js plugin that integrates with > Countdown.js. The file is here.

How it works?

//from then until now
moment("1982-5-25").countdown().toString(); //=> '30 years, 10 months, 14 days, 1 hour, 8 minutes, and 14 seconds'

//accepts a moment, JS Date, or anything parsable by the Date constructor
moment("1955-8-21").countdown("1982-5-25").toString(); //=> '26 years, 9 months, and 4 days'

//also works with the args flipped, like diff()
moment("1982-5-25").countdown("1955-8-21").toString(); //=> '26 years, 9 months, and 4 days'

//accepts all of countdown's options
moment().countdown("1982-5-25", countdown.MONTHS|countdown.WEEKS, NaN, 2).toString(); //=> '370 months, and 2.01 weeks'

Solution 3 - Javascript

Although I'm sure this won't be accepted as the answer to this very old question, I came here looking for a way to do this and this is how I solved the problem.

I created a demonstration here at codepen.io.

The Html:
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.13.0/moment.min.js" type="text/javascript"></script>
<script src="https://cdn.rawgit.com/mckamey/countdownjs/master/countdown.min.js" type="text/javascript"></script>
<script src="https://code.jquery.com/jquery-3.0.0.min.js" type="text/javascript"></script>
<div>
  The time is now: <span class="now"></span>, a timer will go off <span class="duration"></span> at <span class="then"></span>
</div>
<div class="difference">The timer is set to go off <span></span></div>
<div class="countdown"></div>
The Javascript:
var now = moment(); // new Date().getTime();
var then = moment().add(60, 'seconds'); // new Date(now + 60 * 1000);

$(".now").text(moment(now).format('h:mm:ss a'));
$(".then").text(moment(then).format('h:mm:ss a'));
$(".duration").text(moment(now).to(then));
(function timerLoop() {
  $(".difference > span").text(moment().to(then));
  $(".countdown").text(countdown(then).toString());
  requestAnimationFrame(timerLoop);
})();
Output:
The time is now: 5:29:35 pm, a timer will go off in a minute at 5:30:35 pm
The timer is set to go off in a minute
1 minute

Note: 2nd line above updates as per momentjs and 3rd line above updates as per countdownjs and all of this is animated at about ~60FPS because of requestAnimationFrame()


Code Snippet:

Alternatively you can just look at this code snippet:

var now = moment(); // new Date().getTime();
var then = moment().add(60, 'seconds'); // new Date(now + 60 * 1000);

$(".now").text(moment(now).format('h:mm:ss a'));
$(".then").text(moment(then).format('h:mm:ss a'));
$(".duration").text(moment(now).to(then));
(function timerLoop() {
  $(".difference > span").text(moment().to(then));
  $(".countdown").text(countdown(then).toString());
  requestAnimationFrame(timerLoop);
})();

// CountdownJS: http://countdownjs.org/
// Rawgit: http://rawgit.com/
// MomentJS: http://momentjs.com/
// jQuery: https://jquery.com/
// Light reading about the requestAnimationFrame pattern:
// http://www.paulirish.com/2011/requestanimationframe-for-smart-animating/
// https://css-tricks.com/using-requestanimationframe/

<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.13.0/moment.min.js" type="text/javascript"></script>
<script src="https://cdn.rawgit.com/mckamey/countdownjs/master/countdown.min.js" type="text/javascript"></script>
<script src="https://code.jquery.com/jquery-3.0.0.min.js" type="text/javascript"></script>
<div>
  The time is now: <span class="now"></span>,
</div>
<div>
  a timer will go off <span class="duration"></span> at <span class="then"></span>
</div>
<div class="difference">The timer is set to go off <span></span></div>
<div class="countdown"></div>

Requirements:
Optional Requirements:

Additionally here is some light reading about the requestAnimationFrame() pattern:

I found the requestAnimationFrame() pattern to be much a more elegant solution than the setInterval() pattern.

Solution 4 - Javascript

I thought I'd throw this out there too (no plugins). It counts down for 10 seconds into the future.

    var countDownDate = moment().add(10, 'seconds');

      var x = setInterval(function() {
        diff = countDownDate.diff(moment());
    
        if (diff <= 0) {
          clearInterval(x);
           // If the count down is finished, write some text 
          $('.countdown').text("EXPIRED");
        } else
          $('.countdown').text(moment.utc(diff).format("HH:mm:ss"));

      }, 1000);

<script src="https://momentjs.com/downloads/moment.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<div class="countdown"></div>

Solution 5 - Javascript

Timezones. You have to deal with them, by using getTimezoneOffset() if you want your visitors from around the wolrd to get the same time.

Try this http://jsfiddle.net/cxyms/2/, it works for me, but I'm not sure will it work with other timezones.

var eventTimeStamp = '1366549200'; // Timestamp - Sun, 21 Apr 2013 13:00:00 GMT
var currentTimeStamp = '1366547400'; // Timestamp - Sun, 21 Apr 2013 12:30:00 GMT

var eventTime = new Date();
eventTime.setTime(366549200);

var Offset = new Date(eventTime.getTimezoneOffset()*60000)

var Diff = eventTimeStamp - currentTimeStamp + (Offset.getTime() / 2);
var duration = moment.duration(Diff, 'milliseconds');
var interval = 1000;

setInterval(function(){
  duration = moment.duration(duration.asMilliseconds() - interval, 'milliseconds');
  $('.countdown').text(moment(duration.asMilliseconds()).format('H[h]:mm[m]:ss[s]'));
}, interval);

Solution 6 - Javascript

The following also requires the moment-duration-format plugin:

$.fn.countdown = function ( options ) {
	var $target = $(this);
	var defaults = {
		seconds: 0,
		format: 'hh:mm:ss',
		stopAtZero: true
	};
	var settings = $.extend(defaults, options);
	var eventTime = Date.now() + ( settings.seconds * 1000 );
	var diffTime = eventTime - Date.now();
	var duration = moment.duration( diffTime, 'milliseconds' );
	var interval = 0;
	$target.text( duration.format( settings.format, { trim: false }) );
	var counter = setInterval(function () {
		$target.text( moment.duration( duration.asSeconds() - ++interval, 'seconds' ).format( settings.format, { trim: false }) );
		if( settings.stopAtZero && interval >= settings.seconds ) clearInterval( counter );
	}, 1000);
};

Usage example:

$('#someDiv').countdown({
	seconds: 30*60,
	format: 'mm:ss'
});

Solution 7 - Javascript

Here's my timer for 5 minutes:

var start = moment("5:00", "m:ss");
var seconds = start.minutes() * 60;
this.interval = setInterval(() => {
    this.timerDisplay = start.subtract(1, "second").format("m:ss");
    seconds--;
    if (seconds === 0) clearInterval(this.interval);
}, 1000);

Solution 8 - Javascript

Here are some other solutions. No need to use additional plugins.

Snippets down below uses .subtract API and requires moment 2.1.0+

Snippets are also available in here https://jsfiddle.net/traBolic/ku5cyrev/

Formatting with the .format API:

const duration = moment.duration(9, 's');

const intervalId = setInterval(() => {
  duration.subtract(1, "s");

  const inMilliseconds = duration.asMilliseconds();

  // "mm:ss:SS" will include milliseconds
  console.log(moment.utc(inMilliseconds).format("HH[h]:mm[m]:ss[s]"));

  if (inMilliseconds !== 0) return;

  clearInterval(intervalId);
  console.warn("Times up!");
}, 1000);

<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.27.0/moment.min.js"></script>

Manuel formatting by .hours, .minutes and .seconds API in a template string

const duration = moment.duration(9, 's');

const intervalId = setInterval(() => {
  duration.subtract(1, "s");

  console.log(`${duration.hours()}h:${duration.minutes()}m:${duration.seconds()}s`);
  // `:${duration.milliseconds()}` to add milliseconds

  if (duration.asMilliseconds() !== 0) return;

  clearInterval(intervalId);
  console.warn("Times up!");
}, 1000);

<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.27.0/moment.min.js"></script>

Solution 9 - Javascript

This worked for me a mixture from the above answers.

const moment = require('moment');
require("moment-countdown");
let timeRemaining = 2330;
console.log('moment', moment(moment().add(timeRemaining, 'seconds')).countdown().toString());

Solution 10 - Javascript

You're not using react native or react so forgive me this isn't a solution for you. - since this is a 7 year old post I'm pretty sure you figured it out by now ;)

But I was looking for something similar for react-native and it led me to this SO question. Incase anyone else winds up down the same road I thought I'd share my use-moment-countdown hook for react or react native: https://github.com/BrooklinJazz/use-moment-countdown.

For example you can make a 10 minute timer like so:

import React from 'react'

import  { useCountdown } from 'use-moment-countdown'

const App = () => {
  const {start, time} = useCountdown({m: 10})
  return (
    <div onClick={start}>
      {time.format("hh:mm:ss")}
    </div>
  )
}

export default App

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionArpit RawatView Question on Stackoverflow
Solution 1 - JavascriptDiodeView Answer on Stackoverflow
Solution 2 - JavascriptLeniel MaccaferriView Answer on Stackoverflow
Solution 3 - JavascriptJeremy IglehartView Answer on Stackoverflow
Solution 4 - Javascriptamackay11View Answer on Stackoverflow
Solution 5 - JavascriptLemurrView Answer on Stackoverflow
Solution 6 - JavascriptStephen RView Answer on Stackoverflow
Solution 7 - JavascriptAndrew SamoleView Answer on Stackoverflow
Solution 8 - JavascriptSahin D.View Answer on Stackoverflow
Solution 9 - Javascriptuser1503606View Answer on Stackoverflow
Solution 10 - JavascriptBrooklin MyersView Answer on Stackoverflow