【问题标题】:find closest date from array obj/property js从数组 obj/property js 中查找最接近的日期
【发布时间】:2021-09-27 00:30:30
【问题描述】:

我正在尝试从数组中获取最近的日期,并在倒数计时器中使用它以及对象相关的属性,如事件。

我已经设法做到了这一点,从网上四处查看,但我的代码只从数组中提取最后一个条目,而不是最近的日期。

如果有人可以帮助或推动我朝着正确的方向前进,那就太好了。

<p id="demo"></p>
<p id="celebration"></p>

<script>
  // Get today's date and time
  var now = new Date().getTime();

  var data = [
    {
      date: "04/10/2021",
      event: "event 1",
    },
    {
      date: "08/15/2022",
      event: "event 2",
    },
    {
      date: "09/15/2021",
      event: "event 3",
    },
    {
      date: "01/12/2025",
      event: "event 4",
    },
  ];

  var closest = data.reduce((a, b) => (a.date - now < b.date - now ? a : b));

  console.log(closest.date);

  // Set the date we're counting down to
  var countDownDate = new Date(closest.date);

  // Update the count down every 1 second
  var x = setInterval(function () {
    var now = new Date().getTime();
    // Find the distance between now and the count down date
    var distance = countDownDate - now;

    // Time calculations for days, hours, minutes and seconds
    var days = Math.floor(distance / (1000 * 60 * 60 * 24));
    var hours = Math.floor(
      (distance % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60)
    );
    var minutes = Math.floor((distance % (1000 * 60 * 60)) / (1000 * 60));
    var seconds = Math.floor((distance % (1000 * 60)) / 1000);

    // Display the result in the element with id="demo"
    document.getElementById("demo").innerHTML =
      days + "d " + hours + "h " + minutes + "m " + seconds + "s ";

    document.getElementById("celebration").innerHTML = closest.event;
    // If the count down is finished, write some text
    if (distance < 0) {
      clearInterval(x);
      document.getElementById("demo").innerHTML = "EXPIRED";
      document.getElementById("celebration").innerHTML = "None";
    }
  }, 1000);
</script>

【问题讨论】:

  • 数组中具有date 属性的对象是字符串。要将它们视为日期,您需要先解析它们
  • 如果有expired日期怎么办。你还想要那个还是下一个没有过期的?
  • 嗨 @decpk 是的,如果数组中的某个日期已经过去(过期),我不想显示它并转到下一个
  • 然后就简单的排序,得到第一个没有过期的数据

标签: javascript arrays date object properties


【解决方案1】:

您要做的第一件事是确保您有一种方法可以将您的美国格式日期转换为 javascript Date 实例:

const usFormattedDate = "08/15/2022"

const parseUSDate = str => {
  const parts = str.split("/");
  return new Date(Date.UTC(
    parseInt(parts[2],10),
    parseInt(parts[0],10)-1,
    parseInt(parts[1],10)));
}

console.log(parseUSDate(usFormattedDate))

为什么不简单地使用Date 构造函数或Date.parse 方法呢?正如docs 所说:

注意:由于浏览器的差异和不一致,强烈建议不要使用 Date 构造函数(和 Date.parse(),其工作方式相同)解析日期字符串。

然后您可以使用此代码来解析您的 date 属性 - 但您可能只想对每个对象执行一次,而不是每次比较两次

const parseUSDate = str => {
  const parts = str.split("/");
  return new Date(Date.UTC(
    parseInt(parts[2], 10),
    parseInt(parts[0], 10) - 1,
    parseInt(parts[1], 10)));
}

var now = new Date().getTime();

var data = [{
    date: "04/10/2021",
    event: "event 1",
  },
  {
    date: "08/15/2022",
    event: "event 2",
  },
  {
    date: "09/15/2021",
    event: "event 3",
  },
  {
    date: "01/12/2025",
    event: "event 4",
  },
];

var closest = data
  .map(x => ({ ...x, date: parseUSDate(x.date) })) // Convert date to an actual date
  .filter(x => x.date > now)                       // remove records in the past
  .reduce((a, b) => (a.date - now < b.date - now ? a : b));

console.log(closest);

请注意,以这种方式完成(转换date 属性)不需要此行:

var countDownDate = new Date(closest.date);

很简单

var countDownDate = closest.date;

【讨论】:

  • 非常感谢您这样做并解释它。我没有考虑到它会显示过去最接近的日期。您将如何编辑它以使其在已过期(过去)时不显示日期,然后移至下一个最接近的日期
  • @mike 在mapreduce 之间使用filter(x =&gt; x.date &gt; now) - 查看更新的答案
【解决方案2】:

你可以sort它并找到第一个没有过期的元素

  const sorted = data.sort((a, b) => new Date(a.date) - new Date(b.date))
  const closest = sorted.find(o => new Date(o.date) - now > 0)

<p id="demo"></p>
<p id="celebration"></p>

<script>
  // Get today's date and time
  var now = new Date().getTime();

  var data = [{
      date: "04/10/2021",
      event: "event 1",
    },
    {
      date: "08/15/2022",
      event: "event 2",
    },
    {
      date: "09/15/2021",
      event: "event 3",
    },
    {
      date: "01/12/2025",
      event: "event 4",
    },
  ];

  // var closest = data.reduce( ( a, b ) => ( new Date(a.date) - now < new Date(b.date) - now ? a : b ) );
  const sorted = data.sort((a, b) => new Date(a.date) - new Date(b.date))
  const closest = sorted.find(o => new Date(o.date) - now > 0)

  // Set the date we're counting down to
  var countDownDate = new Date(closest.date);

  // Update the count down every 1 second
  var x = setInterval(function() {
    var now = new Date().getTime();
    // Find the distance between now and the count down date
    var distance = countDownDate - now;

    // Time calculations for days, hours, minutes and seconds
    var days = Math.floor(distance / (1000 * 60 * 60 * 24));
    var hours = Math.floor(
      (distance % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60)
    );
    var minutes = Math.floor((distance % (1000 * 60 * 60)) / (1000 * 60));
    var seconds = Math.floor((distance % (1000 * 60)) / 1000);

    // Display the result in the element with id="demo"
    document.getElementById("demo").innerHTML =
      days + "d " + hours + "h " + minutes + "m " + seconds + "s ";

    document.getElementById("celebration").innerHTML = closest.event;
    // If the count down is finished, write some text
    if (distance < 0) {
      clearInterval(x);
      document.getElementById("demo").innerHTML = "EXPIRED";
      document.getElementById("celebration").innerHTML = "None";
    }
  }, 1000);
</script>

【讨论】:

  • @mike Note: Parsing of date strings with the Date constructor (and Date.parse(), which works the same way) is strongly discouraged due to browser differences and inconsistencies. - 见docs
  • @Jamiec 用什么代替 Date 构造函数
  • @decpk 看到我的回答。或者类似 date-fns 的东西
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-01-19
  • 2019-07-09
  • 1970-01-01
  • 2018-06-04
  • 1970-01-01
  • 1970-01-01
  • 2023-02-07
相关资源
最近更新 更多