Как правильно сравнить время в 24-часовом формате? - PullRequest
0 голосов
/ 08 июля 2020

Я получаю объект с такими временами:

const times = {
   "sunrise": "Wed Jul 08 2020 05:17:15 GMT+0200", //this is a date object not a string
   "goldenHourEnd:" "Wed Jul 08 2020 06:12:13 GMT+0200",
   "morning": "Wed Jul 08 2020 08:04:20 GMT+0200",
   "solarNoon": "Wed Jul 08 2020 13:35:04 GMT+0200",
   "evening": "Wed Jul 08 2020 19:05:48 GMT+0200",
   "goldenHour": "Wed Jul 08 2020 20:57:55 GMT+0200",
   "sunset": "Wed Jul 08 2020 21:52:53 GMT+0200",
   "nauticalDusk": "Wed Jul 08 2020 23:57:10 GMT+0200"
};

В настоящий момент я использую эту функцию для получения текущей фазы на основе текущего времени клиента:

function getCurrentTimePhase(object) {
  return Object.entries(object)
  .map(([k, v]) => [ k, Date.now() - Date.parse(v) ])
  .reduce((pre, cur) => cur[1] < pre[1] && cur[1] > 0 ? cur : pre)[0];
}

Проблема в том, что функция не всегда возвращает текущий временной интервал. Например:

//current client time is Wed Jul 08 2020 01:31:04 GMT+0200
const currentPhase = getCurrentTimePhase(times);
console.log(currentPhase); //output: solarNoon

Функция будет возвращена solarNoon. На самом деле функция должна быть возвращена nauticalDusk, потому что мы все еще находимся на этой стадии. Следующая фаза sunrise начинается с Wed Jul 08 2020 05:17:15 GMT+0200, который должен быть возвращен, когда я перешагну эту временную отметку и т. Д.

Как я могу решить эту проблему? Есть идеи?

1 Ответ

0 голосов
/ 11 июля 2020

Выполняя ваш код и заменяя Date.now() на new Date('Wed Jul 08 2020 01:31:04 GMT+0200'), я получаю «восход». Это связано с тем, что для аккумулятора, передаваемого в reduce , нет начального значения, поэтому передаются первые два элемента Object.entries(times), а ['sunrise', 'Wed Jul 08 2020 05:17:15 GMT+0200'] изначально присваивается аккумулятору. Текущее значение не соответствует критериям для замены начального аккумулятора, поэтому оно возвращается. 1027 * должен остановиться, как только будет найдено подходящее значение.

Следующее использует findIndex для получения первой фазы после прошедшей даты (по умолчанию текущая дата и время), затем переходит к предыдущей фазе. Если нет фазы ни до, ни после даты, используется последняя фаза.

Я также добавил сортировку, чтобы гарантировать, что записи правильно упорядочены.

let times = {
   "sunrise": new Date('Wed Jul 08 2020 05:17:15 GMT+0200'),
   "goldenHourEnd": new Date('Wed Jul 08 2020 06:12:13 GMT+0200'),
   "morning": new Date('Wed Jul 08 2020 08:04:20 GMT+0200'),
   "solarNoon": new Date('Wed Jul 08 2020 13:35:04 GMT+0200'),
   "evening": new Date('Wed Jul 08 2020 19:05:48 GMT+0200'),
   "goldenHour": new Date('Wed Jul 08 2020 20:57:55 GMT+0200'),
   "sunset": new Date('Wed Jul 08 2020 21:52:53 GMT+0200'),
   "nauticalDusk": new Date('Wed Jul 08 2020 23:57:10 GMT+0200')
};

function getCurrentTimePhase(data, date = new Date()) {
  // Ensure phases are sorted by date and time
  let entries = Object.entries(data).sort((a, b) => a[1] - b[1]);
  // Find index of first phase that is after date
  let i = entries.findIndex(phase => date - phase[1] < 0);
  // Return phase prior to the one found
  // If no prior phase, or none found (i == -1), return last phase
  return entries[i <= 0? entries.length - 1 : i-1][0]; 
}

// Test dates
[new Date('Wed Jul 08 2020 01:31:04 GMT+0200'), // Before sunrise, return nauticalDusk
 new Date('Wed Jul 08 2020 06:12:12 GMT+0200'), // After sunrise, before goldenHourEnd, return sunrise
 new Date('Wed Jul 08 2020 13:35:05 GMT+0200'), // After solarNoon, before evening, return solarNoon
 new Date('Wed Jul 08 2020 21:52:54 GMT+0200'), // After sunset, before goldenHourEnd, return sunset
 new Date('Wed Jul 08 2020 23:57:15 GMT+0200')  // After nauticalDusk, return nauticalDusk
].forEach(d => console.log(getCurrentTimePhase(times, d)));
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...