Octavian L Octavian L - 6 months ago 12
Javascript Question

Daily countdown timer - Display Message at 21:57

I'm struggling to figure out how Date() works, I found this on the web and wanted to make a countdown that stops at 21:57 UTC Time. It currently displays the message at 21:00 and apears until 22:00.

I tried to add

if(currenthours != 21 && currentminutes >= 57){
and always broke it and got the message. I want it to stop 3 minutes before 22:00 and display the message. After it gets to 22:00 restart the countdown for the next day at 21:57.

Any help will be greatly appreciated !



var date;
var display = document.getElementById('time');

setInterval(function(){
date = new Date( );
var currenthours = date.getUTCHours();
// alert(currenthours);
var currentminutes = date.getUTCMinutes();
// alert(currentminutes);
var hours;
var minutes;
var secondes;

if (currenthours != 21) {

if (currenthours < 21) {
hours = 20 - currenthours;
} else {
hours = 21 + (24 - currenthours);
}
minutes = 60 - date.getUTCMinutes();
secondes = 60 - date.getUTCSeconds();
display.innerHTML = ('00' + hours).slice(-2) + ' HOURS ' + '<p>' +
('00' + minutes).slice(-2) + ' MINUTES ' + '</p>' +
('00' + secondes).slice(-2) + ' SECONDS';
} else {
display.innerHTML = "IT'S 21:57";
}
},1000);

<div id='time'></div>





Made a fiddle
https://jsfiddle.net/5qrs0tcp/1/

Answer

Date objects are very simple, they're just a time value and some handy methods.

I think your logic just needs to be:

if (currenthours != 21 && currentminutes < 57) {
  // set the out of hours message
} else {
  // time is from 21:57 to 21:59 inclusive
}

The countdown doesn't quite work because you're counting to 00 not to 57, but otherwise there doesn't seem to be an issue.

var date;
var display = document.getElementById('time'); 

setInterval(function(){
  date = new Date( );
  var currenthours = date.getUTCHours();
  var currentminutes = date.getUTCMinutes();
  var hours;
  var minutes;
  var secondes;
  var limitHr = 5;    // Change these to required values 
  var limitMin = 02;  // Using 5:12 for convenience
  var message  = 'Currently: ' + date.toISOString() + '<p>';

  // Create new message if outside limitHr:limitMin to limitHr:59 inclusive
  if (currenthours != limitHr || currentminutes < limitMin) {

    if (currenthours <= limitHr) {
      hours = limitHr - currenthours;
    } else {
      hours = limitHr + (24 - currenthours);
    }
    
    minutes  = limitMin - date.getUTCMinutes();
    minutes += minutes < 0? 60 : 0; 
    secondes = 60 - date.getUTCSeconds();
    message += ('00' + hours).slice(-2) + ' HOURS ' + '<p>' + 
               ('00' + minutes).slice(-2) + ' MINUTES ' + '</p>' +
               ('00' + secondes).slice(-2) + ' SECONDS';
  } else {
    message += 'It\'s on or after ' + limitHr + ':' + 
                ('0'+limitMin).slice(-2) + ' GMT';
  }
  // Display the message
  display.innerHTML =  message;
},1000);
<div id="time"></div>

Yes, the timer has issues but that wasn't part of the question. For a counter, it's simpler to just work in time differences, so I've added some methods to Date.prototype for ISO time (to be consistent with ISO Date) and time difference, then use those functions.

The function builds a Date for the end time so that calculations can use Date methods.

// Return the UTC time component of a date in h:mm:ss.sss format
if (!Date.prototype.toISOTime) {
  Date.prototype.toISOTime = function() {
    return this.getUTCHours() + ':' + 
           ('0' + this.getUTCMinutes()).slice(-2) + ':' +
           ('0' + this.getUTCSeconds()).slice(-2) + '.' +
           ('00' + this.getUTCMilliseconds()).slice(-3) + 'Z';
  }
}

// Return the difference in time between two dates
// in h:mm:ss.sss format
if (!Date.prototype.timeDiff) {
  Date.prototype.timeDiff = function(date2) {
    var diff = Math.abs(this - date2);
    var sign = this > date2? '+' : '-';
    return sign + (diff/3.6e6|0) + ':' +                   // hours
           ('0' + ((diff%3.6e6)/6e4|0)).slice(-2) + ':' +  // minutes
           ('0' + ((diff%6e4)/1e3|0)).slice(-2) + '.' +    // seconds
           ('00' + (diff%1e3)).slice(-3);                  // milliseconds
  }
}

function countDown() {
  var now = new Date();
  var limitHr  = 1;
  var limitMin = 10;
  var limitDate = new Date(+now);
  // Set limitDate to next limit time
  limitDate.setUTCHours(limitHr, limitMin, 0, 0);
  var msg = ['Currently: ' + now.toISOTime() + '<br>' + 'Limit: ' + limitDate.toISOTime()];
  var diff;

  // If outside limitHr:limitMin to (limitHr + 1):00
  if (now.getUTCHours() != limitHr || now.getUTCMinutes() != limitMin) {
    if (now > limitDate) limitDate.setDate(limitDate.getDate() + 1);
    msg.push(now.timeDiff(limitDate));
  } else {
    msg.push('It\'s after ' + limitHr + ':' + ('0'+limitMin).slice(-2));
  }
  document.getElementById('msgDiv2').innerHTML = msg.join('<br>');
}

window.onload = function() {
 setInterval(countDown, 1000);
}
<div id="msgDiv2"></div>>

I've left the milliseconds in, round to seconds if you wish.

I've left the timer using setInterval, though I'd prefer to use setTimeout and manually calculate the time to just after the next full second so that it never skips. Most browsers using setTimeout will slowly drift so that they skip a second every now and then. Not really an issue unless you happen to see it, or compare it to the tick of the system clock.