1

I have been looking at a countup timer to run from a specific date, however the code I have used only seems to display the length of time for the previous 15 years and no further back? This is a very simple concept that I just can't get to work, dates such as jan 12 2001 are fine but any lower than 1999 does not seem to have an effect and the days limits arount 5440...

window.onload=function() {
  // Month,Day,Year,Hour,Minute,Second
  upTime('oct,01,0000,00:00:00'); // ****** Change this line!
}

function upTime(countTo) {
  now = new Date();
  countTo = new Date(countTo);
  difference = (now-countTo);

  days=Math.floor(difference/(60*60*1000*24)*1);
  hours=Math.floor((difference%(60*60*1000*24))/(60*60*1000)*1);
  mins=Math.floor(((difference%(60*60*1000*24))%(60*60*1000))/(60*1000)*1);
  secs=Math.floor((((difference%(60*60*1000*24))%(60*60*1000))%(60*1000))/1000*1);

  document.getElementById('days').firstChild.nodeValue = days;
  document.getElementById('hours').firstChild.nodeValue = hours;
  document.getElementById('minutes').firstChild.nodeValue = mins;
  document.getElementById('seconds').firstChild.nodeValue = secs;

  clearTimeout(upTime.to);
  upTime.to=setTimeout(function(){ upTime(countTo); },1000);
}
#countup p {
  display: inline-block;
  padding: 5px;
  background: #FFA500;
  margin: 0 0 20px;
}
<div id="countup">
  It's been
  <p id="days">00</p>
  <p class="timeRefDays">days</p>
  <p id="hours">00</p>
  <p class="timeRefHours">hours</p>
  <p id="minutes">00</p>
  <p class="timeRefMinutes">minutes</p>
  <p id="seconds">00</p>
  <p class="timeRefSeconds">second</p>
</div>
David
  • 6,695
  • 3
  • 29
  • 46
L. Smith
  • 105
  • 3
  • 10
  • Maybe because seconds exceeding the integer limit, _Overflown_ – Tushar Aug 24 '15 at 08:45
  • 1
    `oct,01,0000,00:00:00` is such a strange format that it's a miracle that it works at all; you'll need to use a standard format like `yyyy-mm-dd hh:mm:ss`. – JJJ Aug 24 '15 at 08:52
  • Also, if you cast difference back to a date, you don't have to use Math.floor hacks to get your date settings. – Shilly Aug 24 '15 at 08:56
  • 1
    I don't see the issue [here](http://jsfiddle.net/uc8cddvz/). Could you check again. I set year with 1901 – Neo Aug 24 '15 at 08:56
  • Changing the date to the top comment has allowed dates back to 1000, but I need to go back to 0000 and then negative values – L. Smith Aug 24 '15 at 08:59
  • As @Mr Neo, I aslo have created a fiddle without issues... try his fiddle and tell us. Btw, which browser are you using? – David Aug 24 '15 at 09:02
  • I am using chrome, I see that it is working, and thats fine, but try a date before 1000, ie 0999 or 0000, this doesnt produce a date timer that is correct – L. Smith Aug 24 '15 at 09:05
  • with date before 1000, you could use `countTo.setFullYear(countTo.getFullYear() - 1000);`. Try this, bro – Neo Aug 24 '15 at 09:17
  • 1
    Why don't use [`new Date(year, month, day, hours, minutes, seconds, milliseconds`](http://www.w3schools.com/js/js_dates.asp)? Otherwise use a date string like `new Date("October 13, 2014 11:13:00");` or ISO date `"2015-12-24T12:00:00"` as the example in http://www.w3schools.com/js/js_date_formats.asp. Moreover you don't need to divide by `60*60*1000*24` (and other constants) again and again. Save the temporary result after each step and use it for the next step. It's clearer and faster – phuclv Aug 24 '15 at 09:28

1 Answers1

1

EDIT:

I have improved the snippet and included additional information and links.


The problem is how you set up the Date() object. Go here to check out different valid options.

In your case, what you want to do is:

var countTo = new Date(year, month, day, hours, minutes, seconds);

But you are passing just one parameter and, in that case, it should be the number of milliseconds in UCT between the specified date and midnight January 1, 1970.

Also, you can create the Date() object first and then set individually the different time units. When you do so, you must use setFullYear. I have used setYear in the first edition of my answer and that is plainly wrong: it is not just obsolete, but also lead to unexpected results in the 0-99 range (as the OP pointed out in a comment to this answer).

I have cleaned up my snippet to make it useful also for other people:

//we get a reference to the input elements
var i_year = document.getElementById('i_year');
var i_month = document.getElementById('i_month');
var i_day = document.getElementById('i_day');
var i_hours = document.getElementById('i_hours');
var i_minutes = document.getElementById('i_minutes');
var i_seconds = document.getElementById('i_seconds');
var button = document.getElementById('start_counting');

//we declare a new date, it will be the default value
var start_time = new Date();

//counting starts!
setInterval(function() {
  upTime();
}, 1000);

function upTime() {
  //if the inputs have any value, we update start_time
  if (i_year.value) start_time.setFullYear(i_year.value);
  //Months go from 0 to 11, so we substract 1
  if (i_month.value) start_time.setMonth(i_month.value - 1);
  if (i_day.value) start_time.setDate(i_day.value);
  if (i_hours.value) start_time.setHours(i_hours.value);
  if (i_minutes.value) start_time.setMinutes(i_minutes.value);
  if (i_seconds.value) start_time.setSeconds(i_seconds.value);

  //difference between both dates in ms
  var difference = (new Date() - start_time);

  var msSecond = 1000;
  var msMinute = 60 * msSecond;
  var msHour = 60 * msMinute;
  var msDay = 24 * msHour;

  var days = Math.floor(difference / msDay);
  difference -= days * msDay;

  var hours = Math.floor(difference / msHour);
  difference -= hours * msHour;

  var minutes = Math.floor(difference / msMinute);
  difference -= minutes * msMinute;

  var seconds = Math.floor(difference / msSecond);

  //updating the counter with the new values
  document.getElementById('days').firstChild.nodeValue = days;
  document.getElementById('hours').firstChild.nodeValue = hours;
  document.getElementById('minutes').firstChild.nodeValue = minutes;
  document.getElementById('seconds').firstChild.nodeValue = seconds;

}
#countup p {
  display: inline-block;
  padding: 5px;
  background: #FFA500;
  margin: 0 0 20px;
}

#target_date input {
  display: inline-block;
  width: 50px;
  margin-bottom: 10px;
}
<div id="target_date">
  <input type="text" id="i_year" placeholder="Year">
  <input type="text" id="i_month" placeholder="Month">
  <input type="text" id="i_day" placeholder="Day">
  <input type="text" id="i_hours" placeholder="Hours">
  <input type="text" id="i_minutes" placeholder="Minutes">
  <input type="text" id="i_seconds" placeholder="Seconds">
</div>
<hr>

<div id="countup">
  It's been
  <p id="days">0</p>
  <p>days</p>
  <p id="hours">0</p>
  <p>hours</p>
  <p id="minutes">0</p>
  <p>minutes</p>
  <p id="seconds">0</p>
  <p>second</p>
</div>

The range of years supported in the date object is approximately 285,616 years before and after 1970. That is due to the actual range of times supported by ECMAScript Date objects. Read here and here about it.

One last thing. If you dig into the topic you will find critics to the way javascript deals with calculating the difference between dates. Not all are true (e.g. as you can check in the snippet javacript does get into account leap-years). But it will be problematic to go back thousands of years back in time if you need completely accurate results. Not just because of technical aspects, but also due to human ones (calendar changes through history, timezones, daylight saving times, etc.).

There are javascript specific libraries for this kind of calculation. I think Moment.js is one of the most popular ones.

Hope it helps!

Community
  • 1
  • 1
David
  • 6,695
  • 3
  • 29
  • 46
  • This is great, and works for years down to 1000, but when I try 0001 and years beginning with 0 dont work and the js assumes 0100 to be 1915, any help with this – L. Smith Aug 24 '15 at 09:43
  • I can't reproduce that behavior. If I set year as `setYear(1)` it makes a correct calculation. Play with the [fiddle](https://jsfiddle.net/7qk7n5rd/) and tell us. – David Aug 24 '15 at 09:47
  • 1
    https://jsfiddle.net/w7LLLz83/ Trying this, setting the year to one does not produce the correct answer, this shows 114 years in the past and not the 2014 years that it should be – L. Smith Aug 24 '15 at 09:50
  • @L.Smith: My bad, I update the snippet, we must use setFullYear() – David Aug 24 '15 at 09:57