0

I have this code snippet from another question on StackOverflow. Can someone explain to me what is happening here and how it is able to generate times from 12am to 11:30pm and what I should do if I want it only from 9:00 am to 5:30 pm. You don't have to give me the complete code, at least if you guys can help me understand what is happening here, step by step, I'd be able to carry it forward from there. I am pretty new to JS and still learning.

var times = []
  , periods = ['AM', 'PM']
  , hours = [9, 10, 11, 12, 1, 2, 3, 4, 5]
  , prop = null
  , hour = null
  , min = null; 

for (prop in periods) {
  for (hour in hours) {
    for (min = 0; min < 60; min += 5) {
      times.push(('0' + hours[hour]).slice(-2) + ':' + ('0' + min).slice(-2) + " " + periods[prop]);
    }
  }
}
Community
  • 1
  • 1
DeA
  • 1,748
  • 3
  • 22
  • 41
  • Before to close the question, if @DeA could clearly asks what he wants (we don't really want to go to another question to find that). – ValLeNain Feb 14 '17 at 21:41
  • 1
    Just because I haven't posted code here, doesn't mean I haven't tried. If you need a code snippet that might help increase relevance, please ask. – DeA Feb 14 '17 at 21:41
  • Alright, I shall remove all references to that question and frame it in a different way – DeA Feb 14 '17 at 21:42
  • Does it look ok now? Is this now abiding by the community standards? – DeA Feb 14 '17 at 21:48

3 Answers3

2

Probably the main thing you are confused by is what this is doing:

('0' + hours[hour]).slice(-2)

This is taking a number (like 9), turning it into a 0-prepended string ("09"), and then taking the last two characters. The effect is to 0-pad the numbers to two digits long.

The rest is just nested loops to loop over minutes, hours and AM/PM.

Denise Draper
  • 1,027
  • 10
  • 24
  • But, for my requirement, which is generating times between 9 and 5, would this still work? What part or what logic should I work on to get that thing going? – DeA Feb 14 '17 at 21:58
  • I don't see why not. Why don't you run it and see what happens? – Denise Draper Feb 14 '17 at 22:08
2

What he's doing is adding in times some strings which represents time instants (actually one string every 5 minutes between 9AM to 5PM - I guess you've slightly modified the original example).
The string format is HH:MM 'AM'/'PM'.

If you only want to go to 5.30PM, you'd do

var times = []
  , hours = [9, 10, 11, 12, 1, 2, 3, 4, 5]
  , prop = null
  , hour = null
  , min = null
  , frequencyInMin = 30; 

  for (hour in hours) {
    /* We want to stop at 5.30PM, so the exclusive bound changes when 5 is reached */
    var maxMinute = (hour === 5) ? 35 : 60;

    /* In our case, we know the hours before 12 are 'AM' hours, and the ones after are 'PM' hours */
    var amOrPm = (hour >= 9 && hour < 12) ? 'AM' : 'PM';

    /* We create a string every <frequencyInMin> minutes, from 9AM, to 5.30PM */
    for (min = 0; min < maxMinute; min += frequencyInMin) {
      times.push(('0' + hours[hour]).slice(-2) + ':' + ('0' + min).slice(-2) + " " + amOrPm);
    }
  }

So when it comes to the very last loop, it won't go after 5.30 PM.

ValLeNain
  • 2,232
  • 1
  • 18
  • 37
  • You're right, I tried to play around with it and was looking at all options, but what he's actually doing is going through the entire array, attaching "AM" to it and going through the entire array and attaching "PM" to it. But what I intend to do, I feel is slightly more complicated – DeA Feb 14 '17 at 21:56
  • what's the format you want for the string ? Do you want one string every 5 minutes or at another frequency ? – ValLeNain Feb 14 '17 at 21:57
  • The same format as that snippet is printing right now, "9:00AM" at 30 minute intervals – DeA Feb 14 '17 at 21:59
  • I've updated my example, so you can see how to change the frequency. – ValLeNain Feb 14 '17 at 22:02
  • No, your code starts off at 9 am and after 11:30am instead of going to 12:00pm, it goes back to 12:am – DeA Feb 14 '17 at 22:02
  • you're right, the loop over `periods` was not working here. I've updated again. Note that this code is very specific to your case and would need some refactoring to be more generic. – ValLeNain Feb 14 '17 at 22:06
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/135722/discussion-between-vallenain-and-dea). – ValLeNain Feb 14 '17 at 22:07
1

Step by step you're doing the following: Variable declaration:

var times = []
   , periods = ['AM', 'PM']
   , hours = [9, 10, 11, 12, 1, 2, 3, 4, 5]
   , prop = null
   , hour = null
   , min = null;

For each element in periods array list

for (prop in periods) {

For each hour in hours array list

  for (hour in hours) {

For each minute in a minute (0 to 60) as 5 min step

for (min = 0; min < 60; min += 5) {

Push a string which contains a built hour

  times.push(

Set a string with 0 plus a value to make hours cero padding (012 -> 12 & 05 -> 05)

('0' + hours[hour]).slice(-2) + 

Hour delimeter

':' + 

Same as before, sets min as cero padding (a minute built as 015 will be 15 and 05 will slice the las 2 elements, taking 05 as result)

('0' + min).slice(-2) + 

Space between HH:mm and AM/PM indicator

" " + 

Meridian indicator as the string last piece

periods[prop]);
    }
  }
}

Finally, your doing something like this:

times = ['09:00 AM', '09:05 AM', '09:10 AM', ... , '05:55 AM', '09:00 PM', '09:05 PM', ... , '05:55 PM'] 

(with 216 array length)

If you want to generate the an array with hours between 12 AM to 11:30 PM then you need to split the iterations (first do AM hours which will only have the 12 hour) and then the same with the 1,2,3,4,5,6,7,8,9,10 and 11 hours to PM period.

SerCrAsH
  • 440
  • 5
  • 14
  • Thank you for that explanation. That was very well written. If I just wanted a stretch of times between 9 to 5, would I split the iteration at 12 instead of AM and PM? – DeA Feb 14 '17 at 22:07
  • It would be recomended unless you want to have AM / PM hours of each value in hours list – SerCrAsH Feb 14 '17 at 22:08