以MM / DD / YYY格式JavaScript查找下一个最接近的日期

时间:2016-05-29 00:50:04

标签: javascript arrays sorting date

我有一个格式为MM / DD / YYYY的日期数组。我需要从今天开始找到未来的最近日期。今天说是2016年1月22日,然后2016年2月19日将返回。

Num Int

我已经尝试过将子串,以使月,日,年分开,并尝试根据这些值进行排序,但肯定必须有更好的方法。

9 个答案:

答案 0 :(得分:7)

不需要排序算法。您只需要迭代一次,找到最接近或等于今天的日期。

<强>伪代码

closest <- infinity
foreach date in dates:
    if (date >= now and date < closest) then
        closest <- d
return closest

<强>的JavaScript

var dates = [
  '2/3/2015',
  '7/5/2015',
  '1/21/2016',
  '2/19/2016',
  '7/1/2016',
  '10/22/2019',
   '08/12/2019'
];

var now = new Date();
var closest = Infinity;

dates.forEach(function(d) {
   var date = new Date(d);
   if (date >= now && (date < new Date(closest)|| date < closest)) {
      closest = d;
   }
});

console.log(closest);

答案 1 :(得分:2)

就个人而言,我会使用一个非常好的Moment.JS库这样的库来处理所有可怕的日期复杂性。

它有一个不同的方法:

http://momentjs.com/docs/#/displaying/difference/

e.g。

var a = moment([2007, 0, 29]);
var b = moment([2007, 0, 28]);
a.diff(b) // 86400000

然后,对于Math.min(),列表中每个日期的差异将是微不足道的。

还有一个片刻。如果所有日期都在未来,那么可能会完全缩短这一点:

http://momentjs.com/docs/#/get-set/min/

答案 2 :(得分:1)

一个天真的实现是将每个日期解析为字符串并按升序对它们进行排序。然后,删除过去的任何日期,并获取剩余日期数组的第一个子项。见jsbin example

var dates = [
  '2/3/2015',
  '7/5/2015',
  '1/21/2016',
  '2/19/2016',
  '7/1/2016'
];

// parse each string as a Date object and sort them in ascending order
function sortDates(dates) {
  return dates.map(function(date) {
    return new Date(date).getTime();
  }).sort(function(a, b) {
    return a - b;
  });
}

var orderedDates = sortDates(dates);

// remove any dates in the past, and get the first child of the array of remaining dates
var nextDate = orderedDates.filter(function(date) {
  return (Date.now() - date) > 0;
})[0];

请记住,这取决于您传递给Date对象的日期字符串的格式(换句话说,是{1}} 1月12日或12月1日?JavaScript会将其解析为1月12日。

答案 3 :(得分:1)

这实际上取决于您的日期和数据结构(原始示例中显示的那些对我来说不是那么好)。

从其他答案......

以Josh为例,您还可以指定一个指向您正在使用的日期的指针,或者只是移出已排序的日期队列以使其正常工作,但它确实会为您的代码添加噪音,破坏了目的。

Frederik.L答案是非常漂亮的代码,但它仍然需要多次执行,所以我不推荐它。

反馈警告

我在评论中得到了反馈,Date.parse可能表现不一致。我将转向传递日期解析回调函数,并在回调中演示Date.UTC用于特定于OP的日期格式。在定义自己的回调时请小心,请不要复制粘贴。

建议

我建议使用Date函数,即Date.parse;但也可以尝试在不需要应用程序级排序的情况下对数据源进行排序。然后,您可以使用array.shift()或类似的方式存储一次并逐步执行数组;

理想情况下也是YYYY-MM-DD

  • 四位数年份
  • 两位数月份
  • 两位数日
  • ...(从最少发生到大多数发生继续)

示例代码

var dates = [
    '2/3/2015',
    '7/5/2015',
    '7/1/2016',
    '1/21/2016',
    '2/19/2016'
]; // unsorted garbage dates

var DateList = function( dateList, getDate ) {
    var sortedDates = dateList.sort( function(a, b) {
        return getDate(a) - getDate(b);
    });
    this.next = function() {
        var dt = sortedDates.shift();
        sortedDates.push(dt); // comment to remove cyclical nature
        return dt;
    }
};

// specific implementation parser for this format
var getDisgustingDateFormat = function(dStr) {
    var dParts = dStr.split('/');
    return new Date(Date.UTC(dParts[2],dParts[0],dParts[1]));
};
var dl = new DateList( dates, getDisgustingDateFormat );

用法

dl.next(); // "2/3/2015"
dl.next(); // "7/5/2015"
dl.next(); // "1/21/2016"
dl.next(); // "2/19/2016"
dl.next(); // "7/1/2016"
dl.next(); // "2/3/2015"

希望这有所帮助(为了清晰起见而更新)

答案 4 :(得分:1)

您可以使用while循环,new Date()

&#13;
&#13;
var dates = ["2/3/2015","7/5/2015","1/21/2016","2/19/2016","7/1/2016"]
, d = "1/22/2016", n = -1, res = null;

while (++n < dates.length && new Date(dates[n]) < new Date(d));
res = dates[n] || d;
console.log(res)
&#13;
&#13;
&#13;

答案 5 :(得分:1)

很多答案,还有一个不能伤害。

应始终手动解析日期字符串。库可以提供帮助,但如果您只有一种格式,那么只需要一个简单的功能。

以下使用 reduce 循环遍历日期数组并查找最接近的未来日期。如果将来没有日期,则返回null。

返回的值是数组中的字符串,而不是Date。

function parseMDY(s) {
  var b = (s || '').split(/\D/);
  return new Date(b[2], b[0]-1, b[1])
}

function getClosestDateToToday(arr) {
  var now = new Date();
  now.setHours(23,59,59);
  return arr.reduce(function (acc, s) {
           var d = parseMDY(s);
           return d < now? acc : (acc && d > parseMDY(acc)? acc : s);
         }, null);
}

var dates = ['2/3/2015', '7/5/2015','1/21/2016',
             '2/19/2016','7/1/2016'];

document.write(getClosestDateToToday(dates));

答案 6 :(得分:0)

使用for of和momentjs的该版本如何:

const getClosestFutureDate = (dates) => {
    if (dates.length === 0) {
        return null;
    }

    let minDiff = 0;
    for (const date of dates) {
        minDiff += minDiff + 30;
        var currentDate = moment(date);
        if (currentDate.isAfter(moment()) && currentDate.diff(moment(), "days") <= minDiff) {
            break;
        }
    }
    return currentDate;
};

假设now = 2019-08-21

console.log(getClosestFutureDate(["2019-05-07", "2019-06-01", "2019-07-13", "2019-11-09", "2019-11-10", "2019-11-11"])); 

// 2019-11-09

我是momentjs的粉丝,但是可以很容易地将其重构为仅使用香草Date

答案 7 :(得分:0)

const FindDate = (date, allDate) => {
    // moment().diff only works on moment(). Make sure both date and elements in allDate list is in moment
    let nearestDate = -1; 
    allDate.some(d => {
        const currentDate = moment(d)
        const difference = currentDate.diff(date); // Or date.diff(currentDate) depending on what you're trying to find
        if(difference >= 0){
            nearestDate = d
        }
    });
    console.log(nearestDate)
}

答案 8 :(得分:-3)

Livescript中:

x = 
  * "2/3/2015"
  * "7/5/2015"
  * "1/21/2016"
  * "2/19/2016"
  * "7/1/2016"

sim-unix-ts = (date-str) -> 
  # Simulate unix timestamp like concatenating
  # convert "MM/DD/YYYY" to YYYYMMDD (integer) 
  # so we can simply compare these integers
  [MM, DD, YYYY] = date-str.split "/"
  MM = "0#{MM}".slice -2  # apply zero padding
  DD = "0#{DD}".slice -2  # apply zero padding
  parse-int "#{YYYY}#{MM}#{DD}"

today = sim-unix-ts "2/18/2016"
date-list = [sim-unix-ts(..) for x]

# find next date
next-dates = [.. for date-list when .. > today]
next-date = next-dates.0
next-date-orig = x[date-list.index-of next-date]

alert [next-date, next-date-orig]

..在Javascript中:

var x, simUnixTs, today, dateList, res$, i$, x$, len$, nextDates, y$, nextDate, nextDateOrig;
x = ["2/3/2015", "7/5/2015", "1/21/2016", "2/19/2016", "7/1/2016"];
simUnixTs = function(dateStr){
  var ref$, MM, DD, YYYY;
  ref$ = dateStr.toString().split("/"), MM = ref$[0], DD = ref$[1], YYYY = ref$[2];
  MM = ("0" + MM).slice(-2);
  DD = ("0" + DD).slice(-2);
  return parseInt(YYYY + "" + MM + DD);
};
today = simUnixTs("2/18/2016");
res$ = [];
for (i$ = 0, len$ = x.length; i$ < len$; ++i$) {
  x$ = x[i$];
  res$.push(simUnixTs(x$));
}
dateList = res$;
res$ = [];
for (i$ = 0, len$ = dateList.length; i$ < len$; ++i$) {
  y$ = dateList[i$];
  if (y$ > today) {
    res$.push(y$);
  }
}
nextDates = res$;
nextDate = nextDates[0];
nextDateOrig = x[dateList.indexOf(nextDate)];
alert([nextDate, nextDateOrig]);