Generate array of times (as strings) for every X m

2020-05-17 04:15发布

I'm trying to create an array of times (strings, not Date objects) for every X minutes throughout a full 24 hours. For example, for a 5 minute interval the array would be:

['12:00 AM', '12:05 AM', '12:10 AM', '12:15 AM', ..., '11:55 PM']

My quick and dirty solution was to use 3 nested for loops:

var times = []
  , periods = ['AM', 'PM']
  , hours = [12, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]
  , 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]);
    }
  }
}

This outputs the desired result but I'm wondering if there's a more elegant solution. Is there a way to do this that's:

  • more readable
  • less time complex

15条回答
乱世女痞
2楼-- · 2020-05-17 04:58

My solution with emphasize on readability. It first creates objects that represent correct times and then formats them to strings. JsFiddle https://jsfiddle.net/6qk60hxs/

var periods = ['AM', 'PM'];
var hours = [12, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11];
var minutes = ["00", "05", 10, 15, 20, 25, 30, 35, 40, 45, 50, 55];


timeObj = add([{}], "p", periods);
timeObj = add(timeObj, "h", hours);
timeObj = add(timeObj, "m", minutes);

times = []
for (t of timeObj) {
  times.push(t.h + ':' + t.m + ' ' + t.p);
}

console.log(times)

function add(tab, prop, val) {
  var result = [];
  for (t of tab) {
    for (v of val) {
      tc = _.clone(t);
      tc[prop] = v;
      result.push(tc);
    }
  }
  return result
}
查看更多
戒情不戒烟
3楼-- · 2020-05-17 05:00

Manipulating with a date as with integer and using single loop:

var interval = 5 * 60 * 1000; //5 minutes 
var period = 24 * 60 * 60 * 1000; //dat period

//just converts any time to desired string
var toString = function toString(time){  
  var h = time.getHours();
  var m = time.getMinutes();
  var p = h >= 12 ? "PM" : "AM";
  h = h || 12;
  h = h > 12 ? h - 12 : h;  
  return ("0" + h).slice(-2) + ":" + ("0" + m).slice(-2) + " " + p;
}

//start time
var time = new Date(2010, 0, 1);

//resulting array
var times = [];

for ( var t = +time; t < +time + period; t += interval){  
  var d = toString(new Date(t));  
  times.push(d);
}
查看更多
Melony?
4楼-- · 2020-05-17 05:00

This is an iteration of Faizan Saiyed's answer.

const startHour = moment().format('k');
const endHour = 22

const arr = () => {
  return Array.from({
  length: endHour - startHour
  }, (v, index) => {
    return [0,15,30,45].map((interval) => {
      return moment({
        hour: index,
        minute: interval
      })
      .add(startHour, 'hours')
      .format('h:mm A')
    })
  }).flat()
}
查看更多
Fickle 薄情
5楼-- · 2020-05-17 05:00
const getTimes = (increment = 2) => {
  const times = [];
  for (let i = 0; i < 24; i++) {
    times.push({
      value: `${i === 0 || i - 12 === 0 ? 12 : i < 12 ? i : i - 12}:00 ${i < 12 ? 'AM' : 'PM'}`,
      label: `${i === 0 || i - 12 === 0 ? 12 : i < 12 ? i : i - 12}:00 ${i < 12 ? 'AM' : 'PM'}`,
    });
    for (let j = 60 / increment; j < 60; j += 60 / increment) {
      times.push({
        value: `${i === 0 || i - 12 === 0 ? 12 : i < 12 ? i : i - 12}:${Math.ceil(j)} ${i < 12 ? 'AM' : 'PM'}`,
        label: `${i === 0 || i - 12 === 0 ? 12 : i < 12 ? i : i - 12}:${Math.ceil(j)} ${i < 12 ? 'AM' : 'PM'}`,
      });
    }
  }
  return times;
};

查看更多
啃猪蹄的小仙女
6楼-- · 2020-05-17 05:08

The following is massively flexible with the help of Moment.js.

This code uses

There's no error handling, so you can pass in stupid parameters, but it gets the point across. :-D

The desiredStartTime parameter takes a time in hh:mm format.

The period parameter accepts any of the moment.duration inputs.
period key

const timelineLabels = (desiredStartTime, interval, period) => {
  const periodsInADay = moment.duration(1, 'day').as(period);

  const timeLabels = [];
  const startTimeMoment = moment(desiredStartTime, 'hh:mm');
  for (let i = 0; i <= periodsInADay; i += interval) {
    startTimeMoment.add(i === 0 ? 0 : interval, period);
    timeLabels.push(startTimeMoment.format('hh:mm A'));
  }

  return timeLabels;
};

/* A few examples */
const theDiv = document.getElementById("times");
let content;

content = JSON.stringify(timelineLabels('18:00', 2, 'hours'))
theDiv.appendChild(document.createTextNode(content));
theDiv.appendChild(document.createElement("p"));

content = JSON.stringify(timelineLabels('06:00', 30, 'm'))
theDiv.appendChild(document.createTextNode(content));
theDiv.appendChild(document.createElement("p"));

content = JSON.stringify(timelineLabels('00:00', 5, 'minutes'))
theDiv.appendChild(document.createTextNode(content));
theDiv.appendChild(document.createElement("p"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.18.1/moment.js"></script>

<div id="times"></div>

查看更多
该账号已被封号
7楼-- · 2020-05-17 05:08

Loops are unnecessary in this case.

ES6

//Array.from, only supported by Chrome 45+, Firefox 32+, Edge and Safari 9.0+
//create an array of the expected interval
let arr = Array.from({
  length: 24 * 60 / 5
}, (v, i) => {
  let h = Math.floor(i * 5 / 60);
  let m = i * 5 - h * 60;
  //convert to 12 hours time
  //pad zero to minute
  if (m < 10) {
    m = '0' + m;
  }
  let label = 'AM';
  if (h > 12) {
    label = 'PM';
    h -= 12;
  }
  if (h === 0) {
    h = 12;
  }
  return h + ':' + m + ' ' + label;
});

document.body.textContent = JSON.stringify(arr);

Wider browser support

var arr = Array.apply(null, {
  length: 24 * 60 / 5
}).map(function(v, i) {
  var h = Math.floor(i * 5 / 60);
  var m = i * 5 - h * 60;
  if (m < 10) {
    m = '0' + m;
  }
  var label = 'AM';
  if (h > 12) {
    label = 'PM';
    h -= 12;
  }
  if (h === 0) {
    h = 12;
  }
  return h + ':' + m + ' ' + label;
});

document.body.textContent = JSON.stringify(arr);

查看更多
登录 后发表回答