-4

I want to make a function, that replaces element on specific time and changes HTML inside. I'm getting current time in hours and minutes and I'm trying to solve it by logical operators. I don't know, how to solve it properly (I'm not familiar with objects or methods yet), but I tried my best - I will be grateful, if someone shows me how to make it work or some better way to do this (but it should be just JavaScript or jQuery).

function messageOnSpecificTime(){
  var date=new Date();
  var hour=date.getHours();
  var minutes=date.getMinutes();
//  var messageBox=document.getElementsByClassName("iziToast-message");

 if (hour>=8 && hour<9 && minutes>=0 && minutes<30){
    document.getElementsByClassName("iziToast-message").innerHTML = "Message 8:00 - 8:30"
  } else if (hour>=8 && hour<9 && minutes>=30 && minutes<59){
    document.getElementsByClassName("iziToast-message").innerHTML = "Message 8:00 - 8:30"
  } else if (hour>=9 && hour<10 && minutes>=0 && minutes<30) {
    document.getElementsByClassName("iziToast-message").innerHTML = "Message 8:00 - 8:30"
  } else if (hour>=9 && hour<10 && minutes>=30 && minutes<59) {
    document.getElementsByClassName("iziToast-message").innerHTML = "Message 8:00 - 8:30"
  } else if (hour>=10 && hour<11 && minutes>=0 && minutes<30) {
    document.getElementsByClassName("iziToast-message").innerHTML = "Message 8:00 - 8:30"
  } else if (hour>=10 && hour<11 && minutes>=30 && minutes<59){
    document.getElementsByClassName("iziToast-message").innerHTML = "Message 8:00 - 8:30"
  } else if (hour>=11 && hour<12 && minutes>=0 && minutes<30){
    document.getElementsByClassName("iziToast-message").innerHTML = "Message 8:00 - 8:30"
  } else if (hour>=11 && hour<12 && minutes>=30 && minutes<59) {
    document.getElementsByClassName("iziToast-message").innerHTML = "Message 8:00 - 8:30"
  } else if (hour>=12 && hour<13 && minutes>=0 && minutes<30) {
    document.getElementsByClassName("iziToast-message").innerHTML = "Message 8:00 - 8:30"
  } else if (hour>=12 && hour<13 && minutes>=30 && minutes<59) {
    document.getElementsByClassName("iziToast-message").innerHTML = "Message 8:00 - 8:30"
  } else if (hour>=13 && hour<14 && minutes>=0 && minutes<30) {
    document.getElementsByClassName("iziToast-message").innerHTML = "Message 8:00 - 8:30"
  } else if (hour>=13 && hour<14 && minutes>=30 && minutes<59) {
    document.getElementsByClassName("iziToast-message").innerHTML = "Message 8:00 - 8:30"
  } else if (hour>=14 && hour<15 && minutes>=0 && minutes<30) {
    document.getElementsByClassName("iziToast-message").innerHTML = "Message 8:00 - 8:30"
  } else if (hour>=14 && hour<15 && minutes>=30 && minutes<59) {
    document.getElementsByClassName("iziToast-message").innerHTML = "Message 8:00 - 8:30"
  } else if (hour>=15 && hour<16 && minutes>=0 && minutes<30) {
    document.getElementsByClassName("iziToast-message").innerHTML = "Message 8:00 - 8:30"
  } else if (hour>=15 && hour<16 && minutes>=30 && minutes<59) {
    document.getElementsByClassName("iziToast-message").innerHTML = "Message 8:00 - 8:30"
  } else if (hour>=16 && hour<17 && minutes>=0 && minutes<30) {
    document.getElementsByClassName("iziToast-message").innerHTML = "Message 8:00 - 8:30"
  } else if (hour>=16 && hour<17 && minutes>=30 && minutes<59) {
    document.getElementsByClassName("iziToast-message").innerHTML = "Message 8:00 - 8:30"
  } else if (hour>=17 && hour<18 && minutes>=0 && minutes<30) {
    document.getElementsByClassName("iziToast-message").innerHTML = "Message 8:00 - 8:30"
  } else if (hour>=17 && hour<18 && minutes>=30 && minutes<59) {
    document.getElementsByClassName("iziToast-message").innerHTML = "Message 8:00 - 8:30"
  } else if (hour>=18 && hour<19 && minutes>=0 && minutes<30) {
    document.getElementsByClassName("iziToast-message").innerHTML = "Message 8:00 - 8:30"
  } else if (hour>=18 && hour<19 && minutes>=30 && minutes<59) {
    document.getElementsByClassName("iziToast-message").innerHTML = "Message 8:00 - 8:30"
  } else if (hour>=19 && hour<20 && minutes>=0 && minutes<30) {
    document.getElementsByClassName("iziToast-message").innerHTML = "Message 8:00 - 8:30"
  } else {
    document.getElementsByClassName("iziToast-message").innerHTML = "All for today folks!"
  }
}

window.onload = function() {
    setInterval(messageOnSpecificTime(),6000)
}
  • Your messages are identical. I'm sure you didn't mean that... Did you mean to target hours and minutes into half an hour periods? – iAmOren Sep 24 '20 at 18:42
  • There's a fundamental problem in the code ... see http://stackoverflow.com/questions/10693845/what-do-queryselectorall-getelementsbyclassname-and-other-getelementsby-method . What comes to the "_better way_", I think you can easily calculate the time for the message, without a single `if` statement. – Teemu Sep 24 '20 at 18:44
  • Presumably the messages should show the actual hour instead of "08:00"!!! If that is the case, then the message just needs to include the hour in the string. The only test you actually need to perform is to determine whether the minutes value is between 0 and 29 or 30 and 59 and then append an appropriate string to the message – ATD Sep 24 '20 at 18:48

3 Answers3

0

Using Conditional (ternary) operator.
I've split hour+":"+(minutes<30?"00":"30")+" to "+(hour+(minutes<30?0:1))+":"+(minutes<30?"30":"00") in the code snippet to multiple lines to be able to track the logic.

function messageOnSpecificTime(date=new Date()){
  // var date=new Date();
  var hour=date.getHours();
  var minutes=date.getMinutes();
  var message=
    hour+":"+
    (minutes<30?"00":"30")+
    " to "+
    (hour+
      (minutes<30?0:1)
    )+
    ":"+
    (minutes<30?"30":"00")
  ;
  return message;
};

console.log(messageOnSpecificTime());
console.log(messageOnSpecificTime(new Date("8/8/88 7:00")));
console.log(messageOnSpecificTime(new Date("8/8/88 7:18")));
console.log(messageOnSpecificTime(new Date("8/8/88 7:47")));
console.log(messageOnSpecificTime(new Date("8/8/88 23:47")));
iAmOren
  • 2,609
  • 2
  • 9
  • 23
  • 1
    Why not just `minutes = Math.floor(date.getMinutes() / 30) * 30;` ..? – Teemu Sep 24 '20 at 19:01
  • @Teemu, nice suggestion! Done! – iAmOren Sep 24 '20 at 19:03
  • ... `time = hours + ':' + ('0' + minutes).substr(-2);` ... = ). There's also [padStart](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/padStart), but then `mins` must be explicitly converted to a string. – Teemu Sep 24 '20 at 19:08
  • @Teemu, yeah... improved one thing, another falls apart... – iAmOren Sep 24 '20 at 19:09
  • Well, it shouldn't be that hard, https://jsfiddle.net/psfd825k/ , let the language make the work, don't do it yourself. – Teemu Sep 24 '20 at 19:18
  • Thanks, I know how to add leading zeros. That takes care of the "from" hour - not the "to" hour. I'm leaving this as is - thanks again! – iAmOren Sep 24 '20 at 19:22
  • One suggestion for you: What we are actually looking at are two timestamps - ie, two dates. So, change the minutes of the first Date to either 0 or 30 as appropriate and create a second Date with those minutes + 30. Then just output the time parts from both as a message. – ATD Sep 24 '20 at 19:34
  • @ATD, thank you. I've decided to leave my answer as is. What works is enough for me = doesn't have to be the best. – iAmOren Sep 24 '20 at 19:42
0

Apart from the fact that this gets an hour and minutes from select list and needs to convert the hour value into a number to add 1 (which wouldn't happen in the actual code as that should already be a number), why not just do:

function messageOnSpecificTime() {
  let h = document.getElementById("hours").value;
  let m = document.getElementById("minutes").value;
  let msg = "";
  if (m < 30) {
    msg = h + ":00 - " + h + ":30";
  } else {
    msg = h + ":30 - " + (Number(h) + 1) + ":00";
  }
  document.getElementById("message").innerHTML = msg;
}
Pick an hour: <select id="hours">
<option value=0>0</option>
<option value=1>1</option>
<option value=2>2</option>
<option value=3>3</option>
<option value=4>4</option>
<option value=5>5</option>
<option value=6>6</option>
<option value=7>7</option>
<option value=8>8</option>
<option value=9>9</option>
<option value=10>10</option>
<option value=11>11</option>
<option value=12>12</option>
<option value=13>13</option>
<option value=14>14</option>
<option value=15>15</option>
<option value=16>16</option>
<option value=17>17</option>
<option value=18>18</option>
<option value=19>19</option>
<option value=20>20</option>
<option value=21>21</option>
<option value=22>22</option>
<option value=23>23</option>
</select>

Pick minutes: <select id="minutes">
<option value=0>0</option>
<option value=1>1</option>
<option value=2>2</option>
<option value=3>3</option>
<option value=4>4</option>
<option value=5>5</option>
<option value=6>6</option>
<option value=7>7</option>
<option value=8>8</option>
<option value=9>9</option>
<option value=10>10</option>
<option value=11>11</option>
<option value=12>12</option>
<option value=13>13</option>
<option value=14>14</option>
<option value=15>15</option>
<option value=16>16</option>
<option value=17>17</option>
<option value=18>18</option>
<option value=19>19</option>
<option value=20>20</option>
<option value=21>21</option>
<option value=22>22</option>
<option value=23>23</option>
<option value=24>24</option>
<option value=25>25</option>
<option value=26>26</option>
<option value=27>27</option>
<option value=28>28</option>
<option value=29>29</option>
<option value=30>30</option>
<option value=31>31</option>
<option value=32>32</option>
<option value=33>33</option>
<option value=34>34</option>
<option value=35>35</option>
<option value=36>36</option>
<option value=37>37</option>
<option value=38>38</option>
<option value=39>39</option>
<option value=40>40</option>
<option value=41>41</option>
<option value=42>42</option>
<option value=43>43</option>
<option value=44>44</option>
<option value=45>45</option>
<option value=46>46</option>
<option value=47>47</option>
<option value=48>48</option>
<option value=49>49</option>
<option value=50>50</option>
<option value=51>51</option>
<option value=52>52</option>
<option value=53>53</option>
<option value=54>54</option>
<option value=55>55</option>
<option value=56>56</option>
<option value=57>57</option>
<option value=58>58</option>
<option value=59>59</option>
</select>
<button onclick="messageOnSpecificTime();">Show message</button><br>
<br>
<span id="message"></span>
ATD
  • 1,199
  • 1
  • 2
  • 8
0

Assuming you've an individual message for the each time range, you could build a timer to show the messages, and consider the messages being data instead of them being a part of the code, like they are in your example. In the below code, the messages are stored in a simple object, a key representing the time, and a value being the message itself. The timer takes care of choosing a correct message.

// Store the messages in an object, like this:
const messages = {
  80: 'Message shown between 8:00 - 8:30',
  85: 'Message shown between 8:30 - 9:00',
  90: 'Message shown between 9:00 - 9:30',
  95: 'Message shown between 9:30 - 10:00',
  100: 'Message shown between 10:00 - 10:30',
  105: 'Message shown between 10:30 - 11:00',
  110: 'Message shown between 11:00 - 11:30',
  115: 'Message shown between 11:30 - 12:00',
  120: 'Message shown between 12:00 - 12:30',
  125: 'Message shown between 12:30 - 13:00',
  130: 'Message shown between 13:00 - 13:30',
  135: 'Message shown between 13:30 - 14:00',
  140: 'Message shown between 14:00 - 14:30',
  145: 'Message shown between 14:30 - 15:00',
  150: 'Message shown between 15:00 - 15:30',
  155: 'Message shown between 15:30 - 16:00',
  160: 'Message shown between 16:00 - 16:30',
  165: 'Message shown between 16:30 - 17:00',
  170: 'Message shown between 17:00 - 17:30',
  175: 'Message shown between 17:30 - 18:00',
  180: 'Message shown between 18:00 - 18:30',
  185: 'Message shown between 18:30 - 19:00',
  190: 'Message shown between 19:00 - 19:30',
  0: 'All for today folks!'
};

const now = new Date(),
  // A reference to the element to show the message in
  pad = document.querySelector('.iziToast-message');
    // Time to go before the next half-/full-hour occurs
let nextHalf = (((59 - now.getMinutes()) % 30 + 1) * 60 - now.getSeconds()) * 1000,
  // Index following time, initialized to the nearest half-/full-hour
  time = 10 * now.getHours() + Math.floor(now.getMinutes() / 30) * 5;

// Set the timer, execute the function once immediately to show the current message
(function showMessage() {
  // Set an index matching a key in messages object
  const key = (time < 80 || time > 190) ? 0 : time;
  // Rewrite the content of the message on the page
  pad.textContent = messages[key];
  // Increase the time by half an hour in range 0 - 235 (0:00 - 23:30)
  time = (time + 5) % 240;
  // Run this function again when the next half-/full-hour occurs
  setTimeout(showMessage, nextHalf);
}());
// Set the delay to take a half an hour, will be used when `showMessage` is called next time
nextHalf = 1800000;
<div class="iziToast-message"></div>

The (function () {...}()); construction is ImmediatelyInvokedFunctionExpression.

The messages are separated from the actual executable part, and are included in the properties of the messages object. The keys of the properties are representing the start time when the message in the property should be shown. It's easier to update the messages in an object when the keys are reflecting the actual time. This could be done using an array too, but with an array, the relationship between the time and the message index is less clear, as a sparse array is best to be avoided.

I've also chosen hard-coded time range in the messages, as it takes less code than a dynamic time range creation, and you've free hands to position the range in the message where ever you want.

At first, the code calculates the time to the next nearest half-/full-hour from the current time (nextHalf). Then a simplified time index is created (time), the index matches to the keys in the messages object. Then showMessage is called, and the key (key) for the current message is calculated. If the current time is out of the range (8:00 - 19:30), the key defaults to 0. Then the content of the message box is rewritten, and a new time for the next showMessage call is calculated. The new call is delayed so (nextHalf), that the timer fires on the next half-/full-hour.

To understand, how the code works, it's essential to know, that setTimeout does not block the execution of the current script. Instead, it's executed immediately, and the callback and delay arguments are passed with their current values. Setting a new value to the variable holding the delay after the setTimeout call, does not have an affect to the previously set timer. The new delay is used only in the delayed future calls of the showMessage function.

The advantage of the relatively complex timer is, that you don't have to re-write the message in short intervals, as the timer calibrates to the actual time, and calls itself half-hourly.

A demo at jsFiddle. In the demo a half an hour takes only a second, it's less boring than to wait for a half an hour to see something to happen.

It's notable, that a simpler, and perhaps even more accurate version of the timer can be written. This function contains all the needed variables, excluding the messages object and the reference to the message box element (pad), which are still included in the outer scope.

(function showMessage () {
    const now = new Date(),
      time = 10 * now.getHours() + Math.floor(now.getMinutes() / 30) * 5,
      key = (time < 80 || time > 190) ? 0 : time,
      nextHalf = (((59 - now.getMinutes()) % 30 + 1) * 60 - now.getSeconds()) * 1000;
    pad.textContent = messages[key];
    setTimeout(showMessage, nextHalf);
}());

A demo of this variant, it's not speeded up, though.

Teemu
  • 21,017
  • 6
  • 49
  • 91