160

How can I find out the min and the max date from an array of dates? Currently, I am creating an array like this:

var dates = [];
dates.push(new Date("2011/06/25"))
dates.push(new Date("2011/06/26"))
dates.push(new Date("2011/06/27"))
dates.push(new Date("2011/06/28"))

Is there a built-in function to do this or am I to write my own?

naXa stands with Ukraine
  • 35,493
  • 19
  • 190
  • 259
Legend
  • 113,822
  • 119
  • 272
  • 400

14 Answers14

179

Code is tested with IE,FF,Chrome and works properly:

var dates=[];
dates.push(new Date("2011/06/25"))
dates.push(new Date("2011/06/26"))
dates.push(new Date("2011/06/27"))
dates.push(new Date("2011/06/28"))
var maxDate=new Date(Math.max.apply(null,dates));
var minDate=new Date(Math.min.apply(null,dates));
Andrew D.
  • 8,130
  • 3
  • 21
  • 23
  • 2
    To number convertion applied not for string '2011/06/25', but for new Date('2011/06/25'). Number(new Date('2011/06/25'))===1308949200000. Code is tested in Chrome, IE, FF – Andrew D. Aug 22 '11 at 06:07
  • @RobG - What do you mean by "string dates"? – Andrew D. Aug 22 '11 at 13:46
  • e.g. `dates.push('2011/06/05')`. Using strings the array can be simply sorted and the first and last member values returned and converted to dates if necessary. – RobG Aug 23 '11 at 00:52
  • 12
    @RobG - in the question above array contains Date objects, not "date strings" - response also for Date objects. Using "date strings" is a very bad practic in some cases. Compare next two date strings: "2011/06/05" and "2011/06/05 00:00:00". 1) as strings: ("2011/06/05"==="2011/06/05 00:00:00") : result is false; 2) as Date objects (with convertion to number): Number(new Date("2011/06/05"))===Number(new Date("2011/06/05 00:00:00")) : result is true - is a right result! – Andrew D. Aug 23 '11 at 06:20
  • @AndrewD. If the dateStrings are consistent, say `YYYY/MM/DD HH:MM:SS` and there are a lot of strings involved, would you recommend string comparison or `Number(new Date(dateString))` comparisons? – BlackPanther Aug 04 '16 at 12:49
  • @BlackPanther, I think if all your "date string" has format YYYY/MM/DD HH:MM:SS is no difference how to compare (only difference in algorithm and speed). – Andrew D. Aug 04 '16 at 13:10
  • Thanks Andrew. Good to know. :) – BlackPanther Aug 04 '16 at 13:40
  • 2
    what would be the difference between, Math.max.apply(null,dates) and Math.max(...dates)? – Harshal Jul 09 '21 at 08:51
118

Something like:

var min = dates.reduce(function (a, b) { return a < b ? a : b; }); 
var max = dates.reduce(function (a, b) { return a > b ? a : b; });

Tested on Chrome 15.0.854.0 dev

  • `Array.reduce()` not available in IE before IE9. Cool idea though. – jfriend00 Aug 22 '11 at 05:22
  • 1
    Array.reduce() can be implemented with javascript equivalent function – Andrew D. Aug 22 '11 at 05:54
  • Exactly, read about it in [Eloquent Javascript](http://eloquentjavascript.net/chapter6.html): `function foreach(func, array) { for(var i = 0; i != array.length; ++i) { func(array[i]); } } function reduce(combine, base, array) { foreach(function(element) { base = combine(base, element); }, array); return base; }` – blaze Jan 29 '13 at 00:36
  • 2
    IE <9 can die, and indeed, it now accounts for only 9.3% of global browser use as of April 2013. – wprl May 23 '13 at 15:58
  • If there is a null or empty date. min function will not work – مسعود Apr 12 '18 at 08:22
  • 4
    The reduce solution works for string and for Dates objects. – Benoit May 31 '18 at 07:22
68

Same as apply, now with spread :

const maxDate = new Date(Math.max(...dates));

(could be a comment on best answer)

lvd
  • 899
  • 7
  • 6
  • 15
    For TypeScript, to have type compatibility, the dates should be mapped to a number first, `getTime()` can be used for this. `dates.map(d => d.getTime())`. – Mike de Klerk Apr 14 '22 at 09:32
45

_.min and _.max work on arrays of dates; use those if you're using Lodash or Underscore, and consider using Lodash (which provides many utility functions like these) if you're not already.

For example,

_.min([
    new Date('2015-05-08T00:07:19Z'),
    new Date('2015-04-08T00:07:19Z'),
    new Date('2015-06-08T00:07:19Z')
])

will return the second date in the array (because it is the earliest).

Mark Amery
  • 143,130
  • 81
  • 406
  • 459
  • 4
    Doesn't directly answer OP's question. OP is asking if a built-in method is available in JavaScript. So, although _.min & _.max can be used to find min or max dates, but is not what the OP is looking for. Also, consideration of a utility library is an opinionated topic. – detj Mar 30 '16 at 16:50
  • 21
    I respectfully disagree and think this is a useful answer, @detj - the OP's question as currently worded presumes that either there is a built-in function or he has to write his own, but this isn't true. It seems reasonable to me to point out utility libraries as an alternative to either of the OP's proposed solutions. But your reasoning is defensible, and your vote is your own. – Mark Amery Mar 30 '16 at 18:17
  • 1
    Short, concise and works wonderfully for TypeScript as well as it supports Date type. – Kristjan Liiva Feb 23 '21 at 17:30
15

Since dates are converted to UNIX epoch (numbers), you can use Math.max/min to find those:

var maxDate = Math.max.apply(null, dates)
// convert back to date object
maxDate = new Date(maxDate)

(tested in chrome only, but should work in most browsers)

Ricardo Tomasi
  • 34,573
  • 2
  • 55
  • 66
13

**Use Spread Operators| ES6 **

let datesVar = [ 2017-10-26T03:37:10.876Z,
  2017-10-27T03:37:10.876Z,
  2017-10-23T03:37:10.876Z,
  2015-10-23T03:37:10.876Z ]

Math.min(...datesVar);

That will give the minimum date from the array.

Its shorthand Math.min.apply(null, ArrayOfdates);

Rudresh Ajgaonkar
  • 779
  • 1
  • 10
  • 27
  • 1
    If you downvote, please comment. Why is this a bad option? I like the syntax and for small arrays, the performance penalty is negligible. – GijsjanB Mar 06 '18 at 10:20
  • 1
    I was downvoted. Rudresh's answer is a duplicate of mine above. No idea why people don't like this. It's a single line of code versus many lines. –  Mar 15 '18 at 14:37
  • 4
    This returns a number not a date so you have to convert it back to a date. But it is pretty elegant otherwise. – Tomáš Hübelbauer Apr 10 '19 at 10:11
13

ONELINER:

var min= dates.sort((a,b)=>a-b)[0], max= dates.slice(-1)[0];

result in variables min and max, complexity O(nlogn), editable example here. If your array has no-date values (like null) first clean it by dates=dates.filter(d=> d instanceof Date);.

var dates = [];
dates.push(new Date("2011-06-25")); // I change "/" to "-" in "2011/06/25"
dates.push(new Date("2011-06-26")); // because conosle log write dates 
dates.push(new Date("2011-06-27")); // using "-".
dates.push(new Date("2011-06-28"));

var min= dates.sort((a,b)=>a-b)[0], max= dates.slice(-1)[0];

console.log({min,max});
Kamil Kiełczewski
  • 85,173
  • 29
  • 368
  • 345
4
var max_date = dates.sort(function(d1, d2){
    return d2-d1;
})[0];
wong2
  • 34,358
  • 48
  • 134
  • 179
2

if you get max or min date with string type from string date of array,you can try this:

const dates = ["2021-02-05", "2021-05-20", "2021-01-02"]
const min = dates.reduce((acc,date)=>{return acc&&new Date(acc)<new Date(date)?acc:date},'')
const max = dates.reduce((acc,date)=>{return acc&&new Date(acc)>new Date(date)?acc:date},'')
serenas
  • 137
  • 4
  • 10
1

The above answers do not handle blank/undefined values to fix this I used the below code and replaced blanks with NA :

function getMax(dateArray, filler) {
      filler= filler?filler:"";
      if (!dateArray.length) {
        return filler;
      }
      var max = "";
      dateArray.forEach(function(date) {
        if (date) {
          var d = new Date(date);
          if (max && d.valueOf()>max.valueOf()) {
            max = d;
          } else if (!max) {
            max = d;
          }
        }
      });
      return max;
    };
console.log(getMax([],"NA"));
console.log(getMax(datesArray,"NA"));
console.log(getMax(datesArray));

function getMin(dateArray, filler) {
 filler = filler ? filler : "";
  if (!dateArray.length) {
    return filler;
  }
  var min = "";
  dateArray.forEach(function(date) {
    if (date) {
      var d = new Date(date);
      if (min && d.valueOf() < min.valueOf()) {
        min = d;
      } else if (!min) {
        min = d;
      }
    }
  });
  return min;
}

console.log(getMin([], "NA"));
console.log(getMin(datesArray, "NA"));
console.log(getMin(datesArray));

I have added a plain javascript demo here and used it as a filter with AngularJS in this codepen

Samdeesh
  • 905
  • 11
  • 23
1

You can also use date-fns max function if you already have it in your stack:

    import { max } from 'date-fns';
    
    const dates = [
      new Date('2022-01-01'),
      new Date('2023-03-24'),
      new Date('2021-12-31')
    ];
    
    const maxDate = max(...dates);
    
    console.log(maxDate); // Output: Wed Mar 24 2023 00:00:00 GMT-0400 (Eastern Daylight Time)

https://date-fns.org/v2.29.3/docs/max

Karl Adler
  • 15,780
  • 10
  • 70
  • 88
0

This is a particularly great way to do this (you can get max of an array of objects using one of the object properties): Math.max.apply(Math,array.map(function(o){return o.y;}))

This is the accepted answer for this page: Finding the max value of an attribute in an array of objects

0

Using only one loop in typescript you can get min/max date values at the same time:

function minMaxDates(dates: Date[]): {minDate: Date, maxDate: Date} {
    let minDate = new Date(275760, 8, 13);
    let maxDate = new Date(1970, 1, 1);
    dates.map(date => {
        minDate = minDate < date ? minDate : date;
        maxDate = maxDate > date ? maxDate : date;
    });
    return {minDate, maxDate}
};

To call this function:

const {minDate, maxDate} = minMaxDates(dates);

I posted a demo here.

-2

Using Moment, Underscore and jQuery, to iterate an array of dates.

Sample JSON:

"workerList": [{        
        "shift_start_dttm": "13/06/2017 20:21",
        "shift_end_dttm": "13/06/2017 23:59"
    }, {
        "shift_start_dttm": "03/04/2018 00:00",
        "shift_end_dttm": "03/05/2018 00:00"        
    }]

Javascript:

function getMinStartDttm(workerList) {  
    if(!_.isEmpty(workerList)) {
        var startDtArr = [];
        $.each(d.workerList, function(index,value) {                
            startDtArr.push(moment(value.shift_start_dttm.trim(), 'DD/MM/YYYY HH:mm')); 
         });            
         var startDt = _.min(startDtArr);           
         return start.format('DD/MM/YYYY HH:mm');
    } else {
        return '';
    }   
}

Hope it helps.

Siva Anand
  • 2,872
  • 2
  • 18
  • 9