【问题标题】:How can i comparing times correctly in 24h format?如何以 24 小时格式正确比较时间?
【发布时间】:2020-07-08 17:10:49
【问题描述】:

我得到一个像这样的对象:

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,因为我们还处于这个阶段。下一阶段sunriseWed Jul 08 2020 05:17:15 GMT+0200开始,当我经过这个时间标记时应该返回等等。

我该如何解决这个问题?有什么想法吗?

【问题讨论】:

  • 根据我的测试,您的算法在“日出”之前的任何时间都给出了“日出”。一个快速的解决方法是将["nauticalDusk"] 作为第二个参数添加到您的reduce 调用中:jsfiddle.net/khrismuc/46b2p1xo
  • 你看到我的小提琴了吗?它不适合你吗?
  • @ChrisG 感谢您的努力,但这并没有真正帮助我。我想根据当前客户端时间动态获取当前时间阶段...
  • 抱歉,这个小提琴被硬编码以证明它在日出前的一段时间内给出了正确的结果;它不应该按原样使用。我什至插入了使用当前时间作为注释的正确行。我认为这很明显,并且鉴于 times 也被硬编码为仅在 7 月 8 日有效,我认为这不会是一个问题。同样,正如我在之前的评论中所说,您需要做的就是提供 ["nauticalDusk"] 作为 reduce 函数的初始值。
  • @ChrisG 感谢您的回答,如果我不清楚这一点,我很抱歉。你说:你需要做的就是提供 ["nauticalDusk"] 作为初始值......你是什么意思?关于我的功能,我究竟需要改变什么?你能不能用你的小提琴给我看?因为他现在给我的只是航海黄昏在任何时候

标签: javascript arrays json sorting datetime


【解决方案1】:

运行您的代码并将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']最初被分配给累加器。当前值不符合替换初始累加器的条件,因此将其返回。

我认为使用 map 是多余的,而 reduce 效率低下,因为一旦找到合适的值,循环就应该停止。

下面使用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)));

【讨论】:

    猜你喜欢
    • 2017-02-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-07
    • 2020-02-23
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多