Search code examples
javascripttimetimercountdowncountdowntimer

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/

This is what I ended up with :

    /*
    |================================|
    |         COUNTDOWN TIMER        |
    |================================|
    */

    // 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);
      }
    }

    // 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);
        return timeobj = {
              hours   : (diff/3.6e6|0),                                    // hours
              minutes : ('0' + ((diff%3.6e6)/6e4|0)).slice(-2),            // minutes
              seconds : ('0' + ((diff%6e4)/1e3|0)).slice(-2)               // seconds
          }
      }
    }

    function countDown() {
      var now = new Date();
      var limitHr  = 19;
      var limitMin = 55;
      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 msg = [];
      var diff;

      // If outside limitHr:limitMin to (limitHr + 1):00
      if (now.getUTCHours() == limitHr && now.getUTCMinutes() >= limitMin) {
         msg.push('Countdown stopped'); 

       setTimeout(function(){
        msg = ['Wait for it'];

        var jsonCounter = {
            stats          : msg
        }

        jsonfile.writeFileSync(DailyGamePath, jsonCounter, {spaces: 3});
       },5000);


         var jsonCounter = {
             stats          : msg
         }

         jsonfile.writeFileSync(DailyGamePath, jsonCounter, {spaces: 3});

      } else {

        if (now > limitDate) limitDate.setDate(limitDate.getDate() + 1);

        var jsonCounter = {
            hours      : now.timeDiff(limitDate).hours,
            minutes    : now.timeDiff(limitDate).minutes,
            seconds    : now.timeDiff(limitDate).seconds,
            validating : msg
        }
        jsonfile.writeFileSync(DailyGamePath, jsonCounter, {spaces: 3});

      }
    }

     setInterval(countDown, 1000);

    var daily_status;
    setTimeout( function(){
    setInterval( function() {
    jsonfile.readFile(DailyGamePath, (err, obj) => {
        daily_status={
          hours: obj.hours,
          minutes: obj.minutes,
          seconds: obj.seconds,
          stats: obj.stats,
          validating: obj.validating
        };
        return daily_status;
      });
    }, 1000);
    }, 3000);

    setTimeout( function(){
    io.sockets.on('connection', (socket) => {
       setInterval( function() {
          // var GameStatus=DailyGameStatus();
          socket.broadcast.emit('stream', {hours:daily_status.hours, minutes:daily_status.minutes, seconds:daily_status.seconds, stats:daily_status.stats, validating:daily_status.validating});
       }, 1000);
    });
    }, 3000);

Solution

  • 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.