Count up from a date with JavaScript

Display elapsed days, hours, minutes and seconds from an explicit timestamp, with independent timer state, pause/resume and cleanup.

Live example

See how far you’ve come.

Choose a starting date and see the elapsed time, down to the second.

Runs automatically in your local time zone. Change the date to try your own. Pause freezes the display, not time itself.

Your result will appear here.

A count-up subtracts the starting date from the current time. Enable JavaScript to try one.

Show elapsed time from a starting point

This works for time since a launch, an event or another known instant. The demo calculates locally in your browser; it does not track attendance or send time records anywhere.

Subtract the starting timestamp from the current clock on every update. That lets the display catch up after a paused or background tab instead of assuming every timer callback happened on time.

HTML

<p>Started <time datetime="2014-01-01T12:00:00Z">1 January 2014, 12:00 UTC</time>.</p>
<p id="elapsed" role="timer" aria-live="off">Elapsed time is not running.</p>
<div id="elapsed-controls" hidden>
  <button type="button" id="start-elapsed">Start</button>
  <button type="button" id="pause-elapsed">Pause</button>
</div>

JavaScript

function elapsedParts(start, now = Date.now()) {
  if (!Number.isFinite(start) || !Number.isFinite(now)) return null;
  if (start > now) return null;
  const total = Math.floor((now - start) / 1000);
  return {
    days: Math.floor(total / 86400),
    hours: Math.floor(total % 86400 / 3600),
    minutes: Math.floor(total % 3600 / 60),
    seconds: total % 60,
  };
}

function createCountUp(output, start) {
  if (!Number.isFinite(start)) throw new TypeError('A valid start time is required');
  let timer;
  let running = false;
  let destroyed = false;
  function draw() {
    const value = elapsedParts(start);
    output.textContent = value
      ? `${value.days}d ${value.hours}h ${value.minutes}m ${value.seconds}s`
      : 'The start time is still in the future.';
  }
  function tick() {
    timer = undefined;
    if (!running || document.hidden) return;
    draw();
    timer = setTimeout(tick, 1000);
  }
  function resume() {
    if (destroyed) return;
    clearTimeout(timer);
    running = true;
    tick();
  }
  function pause() {
    running = false;
    clearTimeout(timer);
    timer = undefined;
  }
  function visibility() {
    clearTimeout(timer);
    timer = undefined;
    if (running && !document.hidden) tick();
  }
  document.addEventListener('visibilitychange', visibility);
  draw();
  return { resume, pause, destroy() {
    pause();
    destroyed = true;
    document.removeEventListener('visibilitychange', visibility);
  } };
}

const elapsed = createCountUp(
  document.querySelector('#elapsed'), Date.parse('2014-01-01T12:00:00Z'),
);
document.querySelector('#elapsed-controls').hidden = false;
document.querySelector('#start-elapsed').addEventListener('click', elapsed.resume);
document.querySelector('#pause-elapsed').addEventListener('click', elapsed.pause);

Run this as a deferred script. Each counter gets independent state; clicking Start repeatedly does not create extra timer chains. Call elapsed.destroy() when removing the view, and remove its associated button listeners.

Elapsed days are not calendar years

The units above are fixed durations: a day is 24 hours. Do not divide days by 365 to calculate an age or exact anniversary—leap years and calendar rules matter. Use complete timestamps with a timezone, and validate any dates entered by a visitor before parsing them.

Pause stops display updates, not time itself. Resume shows the current elapsed duration. The visible source date remains useful without JavaScript, and aria-live="off" avoids announcing every second. For measurements that must survive clock changes accurately within one session, use a monotonic clock such as performance.now() instead of a calendar timestamp.

References: Date.parse, timer scheduling, and page visibility.

Original version27 May 2014

Kept here for reference and earlier links. The updated guide above is the recommended starting point; older code may depend on retired services or different software versions.

Expanding on my previous Javascript countdown timer, I've got an easy count up from date counter using pure JavaScript here for you!

Example: Counting up from 1st Jan 2014 12:00:00

00days00hours00minutes00seconds

The basic HTML:

<div class="countup" id="countup1">
  <span class="timeel days">00</span>
  <span class="timeel timeRefDays">days</span>
  <span class="timeel hours">00</span>
  <span class="timeel timeRefHours">hours</span>
  <span class="timeel minutes">00</span>
  <span class="timeel timeRefMinutes">minutes</span>
  <span class="timeel seconds">00</span>
  <span class="timeel timeRefSeconds">seconds</span>
</div>

The Pure Javascript:
Just add the date you want to count up from on line ~7, (where the countUpFromTime function is first called).


/*
 * Basic Count Up from Date and Time
 * Author: @mrwigster / https://guwii.com/bytes/count-date-time-javascript/
 */
window.onload = function() {
  // Month Day, Year Hour:Minute:Second, id-of-element-container
  countUpFromTime("Jan 1, 2014 12:00:00", 'countup1'); // ****** Change this line!
};
function countUpFromTime(countFrom, id) {
  countFrom = new Date(countFrom).getTime();
  var now = new Date(),
      countFrom = new Date(countFrom),
      timeDifference = (now - countFrom);
    
  var secondsInADay = 60 * 60 * 1000 * 24,
      secondsInAHour = 60 * 60 * 1000;
    
  days = Math.floor(timeDifference / (secondsInADay) * 1);
  hours = Math.floor((timeDifference % (secondsInADay)) / (secondsInAHour) * 1);
  mins = Math.floor(((timeDifference % (secondsInADay)) % (secondsInAHour)) / (60 * 1000) * 1);
  secs = Math.floor((((timeDifference % (secondsInADay)) % (secondsInAHour)) % (60 * 1000)) / 1000 * 1);

  var idEl = document.getElementById(id);
  idEl.getElementsByClassName('days')[0].innerHTML = days;
  idEl.getElementsByClassName('hours')[0].innerHTML = hours;
  idEl.getElementsByClassName('minutes')[0].innerHTML = mins;
  idEl.getElementsByClassName('seconds')[0].innerHTML = secs;

  clearTimeout(countUpFromTime.interval);
  countUpFromTime.interval = setTimeout(function(){ countUpFromTime(countFrom, id); }, 1000);
}

The very basic styling for the top example, you can do better I'm sure!

<style>
.countup {
  text-align: center;
  margin-bottom: 20px;
}
.countup .timeel {
  display: inline-block;
  padding: 10px;
  background: #151515;
  margin: 0;
  color: white;
  min-width: 2.6rem;
  margin-left: 13px;
  border-radius: 10px 0 0 10px;
}
.countup span[class*="timeRef"] {
  border-radius: 0 10px 10px 0;
  margin-left: 0;
  background: #e8c152;
  color: black;
}
</style>

Looking for it to show Years instead of days?

Use this code:

<div class="countup" id="countup1">
  <span class="timeel years">00</span>
  <span class="timeel timeRefYears">years</span>
  <span class="timeel days">00</span>
  <span class="timeel timeRefDays">days</span>
  <span class="timeel hours">00</span>
  <span class="timeel timeRefHours">hours</span>
  <span class="timeel minutes">00</span>
  <span class="timeel timeRefMinutes">minutes</span>
  <span class="timeel seconds">00</span>
  <span class="timeel timeRefSeconds">seconds</span>
</div>

window.onload = function() {
  // Month Day, Year Hour:Minute:Second, id-of-element-container
  countUpFromTime("Jan 1, 2014 12:00:00", 'countup1'); // ****** Change this line!
};
function countUpFromTime(countFrom, id) {
  countFrom = new Date(countFrom).getTime();
  var now = new Date(),
      countFrom = new Date(countFrom),
      timeDifference = (now - countFrom);
    
  var secondsInADay = 60 * 60 * 1000 * 24,
      secondsInAHour = 60 * 60 * 1000;
    
  days = Math.floor(timeDifference / (secondsInADay) * 1);
  years = Math.floor(days / 365);
  if (years > 1){ days = days - (years * 365) }
  hours = Math.floor((timeDifference % (secondsInADay)) / (secondsInAHour) * 1);
  mins = Math.floor(((timeDifference % (secondsInADay)) % (secondsInAHour)) / (60 * 1000) * 1);
  secs = Math.floor((((timeDifference % (secondsInADay)) % (secondsInAHour)) % (60 * 1000)) / 1000 * 1);

  var idEl = document.getElementById(id);
  idEl.getElementsByClassName('years')[0].innerHTML = years;
  idEl.getElementsByClassName('days')[0].innerHTML = days;
  idEl.getElementsByClassName('hours')[0].innerHTML = hours;
  idEl.getElementsByClassName('minutes')[0].innerHTML = mins;
  idEl.getElementsByClassName('seconds')[0].innerHTML = secs;

  clearTimeout(countUpFromTime.interval);
  countUpFromTime.interval = setTimeout(function(){ countUpFromTime(countFrom, id); }, 1000);
}

Keep exploring

A couple more useful notes.