javascript - Nodejs - Express - 如何计算下一个更接近今天的时间()?
问题描述
考虑到以下数组数据,我需要计算下一个更接近“时间”的小时:
var date = new Date();
var time = date.getHours(); // 17 -> it means 5:00 PM
var minute = date.getMinutes(); // 12
// This is how the data has been saved in the database.
{ id: ‘1’, time: '1:00 AM' }
{ id: ‘1’, time: '2:00 PM' }
{ id: ‘1’, time: '7:00 PM' }
{ id: ‘1’, time: '10:00 PM' }
{ id: ‘1’, time: '8:00 PM' }
{ id: ‘1’, time: '11:00 AM' }
{ id: ‘2’, time: '9:00 AM' }
{ id: ‘2’, time: '6:30 PM' }
{ id: ‘2’, time: '5:00 PM' }
{ id: ‘2’, time: '1:00 PM' }
结果需要是这样的数组:
{id: ‘1’, time: '7:00 PM'}
{id: ‘2’, time: '6:30 PM'}
基本上我需要知道每个 ID 下一个更接近下午 5:12 的时间。
到目前为止,这是我的代码:
function calculateNextPill(items) {
let nextPillArr = [];
let itemData = null;
let item_id = null;
var currentTime = new Date();
var closerTime = new Date();
var newTimes = [];
for(i=0; i<items.length; i++) {
itemData = items[i].itemdata[0];
item_id = items[i]._id;
for (const prop in itemData.pills) {
const pill = itemData.pills[prop];
if (pill != undefined && pill.time != undefined) {
nextPillArr.push({id: item_id, time: pill.time});
}
}
}
nextPillArr.forEach(element => {
var time = element.time;
var scheduleTime = new Date();
var parts = time.match(/(\d+):(\d+) (AM|PM)/);
if (parts) {
var hours = parseInt(parts[1]),
minutes = parseInt(parts[2]),
tt = parts[3];
if (tt === 'PM' && hours < 12) hours += 12;
scheduleTime.setHours(hours, minutes, 0, 0);
var a = moment(currentTime);
var b = moment(scheduleTime);
b.diff(a);
newTimes.push({id: element._id, diff: b.diff(a)});
// here I need to calculate which time is closer for which pill. Not done yet. Need more coffe...
}
});
}
解决方案
首先,您需要一个函数,该函数可以让您每次都获得某种数值,然后您可以使用它来比较这些值。以下函数将为我们提供 24 小时格式的分钟数:
function time_to_numeric(time) {
const [_, h, m, meridian] = time.match(/(\d+):(\d+) (AM|PM)/);
let [hours, min] = [parseInt(h), parseInt(m)];
if (meridian === "PM" && hours !== 12) hours += 12;
if (meridian === "AM" && hours === 12) hours -= 12;
return hours * 60 + min;
}
接下来,我们还需要相同格式的时间now
:
const now = new Date();
const now_numeric = now.getHours() * 60 + now.getMinutes();
使用它,我们现在可以开始查找每个唯一 id 的最接近时间,假设items
是您示例中所有对象的数组。这通过计算以分钟为单位的差异now
并在它较低时交换值来工作。如果某个时间比现在更早发生,我们改为计算第二天与该时间的差。我们为每个 id 保存当前最小值的差值和实际时间:
const closer_times_by_id = items.reduce((acc, {id, time}) => {
const time_numeric = time_to_numeric(time);
let diff = time_numeric - now_numeric;
if (diff < 0) diff = time_numeric + MINUTES_PER_DAY - now_numeric;
const prev_diff = acc[id] && acc[id].diff;
if (prev_diff === undefined || diff < prev_diff) {
acc[id] = { diff, time };
}
return acc;
}, {});
现在我们的closer_times_by_id
会看起来像{'1': {diff: 158, time: '7:00 PM'}, '2': {diff: 38, time: '5:00 PM'}}
. 我们通过以下方式将其映射到数组:
times_arr = Object.entries(closer_times_by_id).map(item => {
const [id, { time }] = item;
return { id, time };
});
在此之后,我们完成并times_arr
包含您的结果。
完整代码:
const MINUTES_PER_DAY = 24 * 60;
// Takes a string like '1:10 PM' and returns the amount of minutes in 24h format
function time_to_numeric(time) {
const [_, h, m, meridian] = time.match(/(\d+):(\d+) (AM|PM)/);
let [hours, min] = [parseInt(h), parseInt(m)];
if (meridian === "PM" && hours !== 12) hours += 12;
if (meridian === "AM" && hours === 12) hours -= 12;
return hours * 60 + min;
}
function closest_items_by_id(items) {
const now = new Date();
const now_numeric = now.getHours() * 60 + now.getMinutes();
// Find closest times for each id, giving preference to times in the
// future in case of ties
// After reducing has finished, closer_times_by_id will be an object like
// {'1': {diff: 158, time: '7:00 PM'}, '2': {diff: 38, time: '5:00 PM'}}
const closer_times_by_id = items.reduce((acc, {id, time}) => {
const time_numeric = time_to_numeric(time);
let diff = time_numeric - now_numeric;
// If time occured earlier than now, calculate diff to time next day
if (diff < 0) diff = time_numeric + MINUTES_PER_DAY - now_numeric;
const prev_diff = acc[id] && acc[id].diff;
if (prev_diff === undefined || diff < prev_diff) {
acc[id] = { diff, time };
}
return acc;
}, {});
// Map closer_times_by_id to desired format
return Object.entries(closer_times_by_id).map(item => {
const [id, { time }] = item;
return { id, time };
});
}
const raw_data = [
{ id: '1', time: '1:00 AM' },
{ id: '1', time: '11:00 AM' },
{ id: '1', time: '2:00 PM' },
{ id: '1', time: '7:00 PM' },
{ id: '1', time: '8:00 PM' },
{ id: '1', time: '10:00 PM' },
{ id: '2', time: '9:00 AM' },
{ id: '2', time: '1:00 PM' },
{ id: '2', time: '1:10 PM' },
{ id: '2', time: '5:00 PM' },
{ id: '2', time: '6:30 PM' },
]
const now = new Date();
console.log(`Time at SO-server: ${now.getHours()}:${now.getMinutes()}`);
console.log(closest_items_by_id(raw_data));
推荐阅读
- ruby-on-rails - 即使我可以看到它们,也不能使用 rails 参数。具体charge_id
- android - libusb 在 Android 4.4.2 中同步传输时返回空包
- firebase - 使用缓存或快照侦听器优化从 Firestore 服务器读取的次数
- sql - 输出的 SQL 查询
- php - 调用未知方法:frontend\models\ContactForm::save()
- pdf - .ttf 文件中的字形间距
- c# - 使用 NLog 或 Serilog 时 .NET Core 3.0 应用程序中的内存泄漏
- c++ - seastar 如何在不同的 cpu 上调用代码?
- php - 修复尝试获取非对象 Laravel 属性的错误
- angular - Angular 2如何扩展具有依赖注入的类