88

I want a list of dates between start date and end date.

The result should be a list of all dates including the start and end date.

Eric Leschinski
  • 146,994
  • 96
  • 417
  • 335
Arivu2020
  • 2,485
  • 7
  • 25
  • 24
  • 1
    [LocalDate.datesUntil()](https://docs.oracle.com/en/java/javase/13/docs/api/java.base/java/time/LocalDate.html#datesUntil(java.time.LocalDate)) – ZhekaKozlov Feb 01 '20 at 04:10
  • 1
    For those using groovy (using LocalDate): `(fromDate..toDate).each { println it }` – lepe Oct 03 '21 at 09:32

23 Answers23

58

java.time Package

If you are using Java 8, there is a much cleaner approach. The new java.time package in Java 8 incorporates the features of the Joda-Time API.

Your requirement can be solved using the below code:

String s = "2014-05-01";
String e = "2014-05-10";
LocalDate start = LocalDate.parse(s);
LocalDate end = LocalDate.parse(e);
List<LocalDate> totalDates = new ArrayList<>();
while (!start.isAfter(end)) {
    totalDates.add(start);
    start = start.plusDays(1);
}
edwardmlyte
  • 15,937
  • 23
  • 58
  • 83
Yadu Krishnan
  • 3,492
  • 5
  • 41
  • 80
  • FYI, this exact same code would work using the [Joda-Time library](http://www.joda.org/joda-time/) for those who cannot move to Java 8 yet. While java.time is not a drop-in replacement for Joda-Time, in this particular case the code happens to be the same. – Basil Bourque May 29 '14 at 18:44
  • You could set the initial capacity of the list by passing to the `ArrayList` constructor the number of days elapsed. `int initialCapacity = java.lang.Math.toIntExact( ChronoUnit.DAYS.between( start , end ) ) ;` – Basil Bourque Nov 25 '16 at 09:05
  • 3
    Note that Java 9 makes this use of `LocalDate` even easier with `Stream`, eliminating the need to build your own `while` loop. See [the Answer by Hochschild](http://stackoverflow.com/a/35892853/642706). – Basil Bourque Feb 20 '17 at 21:50
  • What if i want to find and separate out Weekdays and Weekend using this? How do i do it? – justarandomguy Jun 05 '20 at 09:28
  • LocalDate has a method to get DayOfWeek. Check that out. – Yadu Krishnan Jun 05 '20 at 09:54
55

Back in 2010, I suggested to use Joda-Time for that.

Note that Joda-Time is now in maintenance mode. Since 1.8 (2014), you should use java.time.

Add one day at a time until reaching the end date:

int days = Days.daysBetween(startDate, endDate).getDays();
List<LocalDate> dates = new ArrayList<LocalDate>(days);  // Set initial capacity to `days`.
for (int i=0; i < days; i++) {
    LocalDate d = startDate.withFieldAdded(DurationFieldType.days(), i);
    dates.add(d);
}

It wouldn't be too hard to implement your own iterator to do this as well, that would be even nicer.

Community
  • 1
  • 1
Albert
  • 2,125
  • 1
  • 19
  • 24
  • 1
    For alternative, see the [answer by Krishnan](http://stackoverflow.com/a/23932946/642706) on this same question. – Basil Bourque May 29 '14 at 19:05
  • 14
    **TIP** Simplify that code with a call to [`plusDays`](http://www.joda.org/joda-time/apidocs/org/joda/time/LocalDate.html#plusDays(int)). So this `LocalDate d = startDate.withFieldAdded(DurationFieldType.days(), i);` becames this `LocalDate d = startDate.plusDays(i);` – Basil Bourque Oct 26 '14 at 08:27
  • FYI, the [*Joda-Time*](http://www.joda.org/joda-time/) project is now in [maintenance mode](https://en.wikipedia.org/wiki/Maintenance_mode), with the team advising migration to the [*java.time*](http://docs.oracle.com/javase/10/docs/api/java/time/package-summary.html) classes. See [Tutorial by Oracle](https://docs.oracle.com/javase/tutorial/datetime/TOC.html). – Basil Bourque Apr 30 '18 at 21:20
  • The list doesn't contain end date, change i < days to i <= days – tutak Aug 20 '18 at 09:13
  • Could someone please update it with the current java.time api? It keeps confusing people (they keep coming with jodatime questions in 2019). – Andrey Tyukin Jan 10 '19 at 10:32
46

Get the number of days between dates, inclusive.

public static List<Date> getDaysBetweenDates(Date startdate, Date enddate)
{
    List<Date> dates = new ArrayList<Date>();
    Calendar calendar = new GregorianCalendar();
    calendar.setTime(startdate);

    while (calendar.getTime().before(enddate))
    {
        Date result = calendar.getTime();
        dates.add(result);
        calendar.add(Calendar.DATE, 1);
    }
    return dates;
}
Eric Leschinski
  • 146,994
  • 96
  • 417
  • 335
Jules Rogerson
  • 461
  • 3
  • 2
  • 3
    In general case the final list will not include the `fechaFinal` (ending date) when you are using `before()` method (which is equal to < operation). Instead the <= operation should be used. Since there is no equivalent method in `Calendar` class, you should increase the end date a bit. – Alex Semeniuk Jul 25 '13 at 12:16
  • Incrementing end date by 1 does not provide a full proof solution until we reset time information of enddate to 0 – Saurabh Mishra Feb 03 '15 at 10:02
  • 1
    If using midnight as the `enddate` the last day won't show up. Comparing time since epoch will fix this: `while (calendar.getTime().getTime() <= enddate.getTime())` – Ricardo Teixeira Aug 25 '15 at 14:00
  • FYI, the troublesome old date-time classes such as [`java.util.Date`](https://docs.oracle.com/javase/10/docs/api/java/util/Date.html), [`java.util.Calendar`](https://docs.oracle.com/javase/10/docs/api/java/util/Calendar.html), and `java.text.SimpleDateFormat` are now [legacy](https://en.wikipedia.org/wiki/Legacy_system), supplanted by the [*java.time*](https://docs.oracle.com/javase/10/docs/api/java/time/package-summary.html) classes built into Java 8 and later. See [*Tutorial* by Oracle](https://docs.oracle.com/javase/tutorial/datetime/TOC.html). – Basil Bourque Apr 30 '18 at 21:20
35

Streams

Edit: Joda-Time is now deprecated, changed the answer to use Java 8 instead.

Here is the Java 8 way, using streams.

List<LocalDate> daysRange = Stream.iterate(startDate, date -> date.plusDays(1)).limit(numOfDays).collect(Collectors.toList());
Amit Goldstein
  • 827
  • 9
  • 18
  • 5
    numofDays can be found as long numofDays = ChronoUnit.DAYS.between(startDate, endDate); – Chetan Sharma Sep 01 '17 at 08:44
  • 1
    If you are using Java 8 and later, there is no need to be using the *Joda-Time* library. The [*Joda-Time*](http://www.joda.org/joda-time/) project is now in [maintenance mode](https://en.wikipedia.org/wiki/Maintenance_mode), with the team advising migration to the [*java.time*](http://docs.oracle.com/javase/10/docs/api/java/time/package-summary.html) classes built into Java 8 and later. See [Tutorial by Oracle](https://docs.oracle.com/javase/tutorial/datetime/TOC.html). See the [Answer by Hochschild](https://stackoverflow.com/a/42344215/642706). – Basil Bourque Apr 30 '18 at 21:22
  • Why do I need to add +1 to numOfDays to get the endDate into list also? – pipilam Apr 24 '19 at 13:41
  • @pipilam you don't add +1 to numOfDays, you add 1 to the day you are iterating on – Amit Goldstein Apr 28 '19 at 04:13
17

please find the below code.

List<Date> dates = new ArrayList<Date>();

String str_date ="27/08/2010";
String end_date ="02/09/2010";

DateFormat formatter ; 

formatter = new SimpleDateFormat("dd/MM/yyyy");
Date  startDate = (Date)formatter.parse(str_date); 
Date  endDate = (Date)formatter.parse(end_date);
long interval = 24*1000 * 60 * 60; // 1 hour in millis
long endTime =endDate.getTime() ; // create your endtime here, possibly using Calendar or Date
long curTime = startDate.getTime();
while (curTime <= endTime) {
    dates.add(new Date(curTime));
    curTime += interval;
}
for(int i=0;i<dates.size();i++){
    Date lDate =(Date)dates.get(i);
    String ds = formatter.format(lDate);    
    System.out.println(" Date is ..." + ds);
}

output:

Date is ...27/08/2010
Date is ...28/08/2010
Date is ...29/08/2010
Date is ...30/08/2010
Date is ...31/08/2010
Date is ...01/09/2010
Date is ...02/09/2010

javanna
  • 59,145
  • 14
  • 144
  • 125
bidyot
  • 171
  • 1
  • 2
  • 2
    This wont work around the end of daylight saving time since that day has 25 hours. You will get the next day repeated. Example for Germany: Date is ...30/10/2010 | Date is ...31/10/2010 | Date is ...31/10/2010 | Date is ...01/11/2010 (Simple solution: add some hours (12) to the start date) – user85421 Aug 26 '10 at 19:49
12

Recommending date streams

In Java 9, you can use following new method, LocalDate::datesUntil:

LocalDate start = LocalDate.of(2017, 2, 1);
LocalDate end = LocalDate.of(2017, 2, 28);

Stream<LocalDate> dates = start.datesUntil(end.plusDays(1));
List<LocalDate> list = dates.collect(Collectors.toList());

The new method datesUntil(...) works with an exclusive end date, hence the shown hack to add a day.

Once you have obtained a stream you can exploit all the features offered by java.util.stream- or java.util.function-packages. Working with streams has become so simple compared with earlier approaches based on customized for- or while-loops.


Or if you look for a stream-based solution which operates on inclusive dates by default but can also be configured otherwise then you might find the class DateInterval in my library Time4J interesting because it offers a lot of special features around date streams including a performant spliterator which is faster than in Java-9:

PlainDate start = PlainDate.of(2017,  2, 1);
PlainDate end = start.with(PlainDate.DAY_OF_MONTH.maximized());
Stream<PlainDate> stream = DateInterval.streamDaily(start, end);

Or even simpler in case of full months:

Stream<PlainDate> februaryDates = CalendarMonth.of(2017, 2).streamDaily();
List<LocalDate> list = 
    februaryDates.map(PlainDate::toTemporalAccessor).collect(Collectors.toList());
Basil Bourque
  • 303,325
  • 100
  • 852
  • 1,154
Meno Hochschild
  • 42,708
  • 7
  • 104
  • 126
5

With java 8

public Stream<LocalDate> getDaysBetween(LocalDate startDate, LocalDate endDate) {
    return IntStream.range(0, (int) DAYS.between(startDate, endDate)).mapToObj(startDate::plusDays);
}
Thermech
  • 4,371
  • 2
  • 39
  • 60
4

Something like this should definitely work:

private List<Date> getListOfDaysBetweenTwoDates(Date startDate, Date endDate) {
    List<Date> result = new ArrayList<Date>();
    Calendar start = Calendar.getInstance();
    start.setTime(startDate);
    Calendar end = Calendar.getInstance();
    end.setTime(endDate);
    end.add(Calendar.DAY_OF_YEAR, 1); //Add 1 day to endDate to make sure endDate is included into the final list
    while (start.before(end)) {
        result.add(start.getTime());
        start.add(Calendar.DAY_OF_YEAR, 1);
    }
    return result;
}
Alex Semeniuk
  • 1,865
  • 19
  • 28
3

With Lamma it looks like this in Java:

    for (Date d: Dates.from(2014, 6, 29).to(2014, 7, 1).build()) {
        System.out.println(d);
    }

and the output is:

    Date(2014,6,29)
    Date(2014,6,30)
    Date(2014,7,1)
Max
  • 2,065
  • 24
  • 20
3
 public static List<Date> getDaysBetweenDates(Date startDate, Date endDate){
        ArrayList<Date> dates = new ArrayList<Date>();
        Calendar cal1 = Calendar.getInstance();
        cal1.setTime(startDate);

        Calendar cal2 = Calendar.getInstance();
        cal2.setTime(endDate);

        while(cal1.before(cal2) || cal1.equals(cal2))
        {
            dates.add(cal1.getTime());
            cal1.add(Calendar.DATE, 1);
        }
        return dates;
    }
Linh
  • 57,942
  • 23
  • 262
  • 279
  • The terrible `Calendar` class is now legacy, supplanted by the modern *java.time* classes with the adoption of JSR 310. – Basil Bourque Sep 20 '19 at 16:18
2

One solution would be to create a Calendar instance, and start a cycle, increasing it's Calendar.DATE field until it reaches the desired date. Also, on each step you should create a Date instance (with corresponding parameters), and put it to your list.

Some dirty code:

    public List<Date> getDatesBetween(final Date date1, final Date date2) {
    List<Date> dates = new ArrayList<Date>();

    Calendar calendar = new GregorianCalendar() {{
        set(Calendar.YEAR, date1.getYear());
        set(Calendar.MONTH, date1.getMonth());
        set(Calendar.DATE, date1.getDate());
    }};

    while (calendar.get(Calendar.YEAR) != date2.getYear() && calendar.get(Calendar.MONTH) != date2.getMonth() && calendar.get(Calendar.DATE) != date2.getDate()) {
        calendar.add(Calendar.DATE, 1);
        dates.add(new Date(calendar.get(Calendar.YEAR), calendar.get(Calendar.MONTH), calendar.get(Calendar.DATE)));
    }

    return dates;
}
George
  • 8,368
  • 12
  • 65
  • 106
2

As of Java 9, you can use the datesUntil method on LocalDate:

public List<LocalDate> getDatesBetween(
  LocalDate startDate, LocalDate endDate) {
  
    return startDate.datesUntil(endDate)
      .collect(Collectors.toList());
}
M. Justin
  • 14,487
  • 7
  • 91
  • 130
prachi
  • 113
  • 1
  • 8
  • This solution was already covered in the Answer by Hochschild. – Basil Bourque Sep 20 '19 at 16:19
  • The `datesUntil` method excludes the end date. Since the question asked to also include it, a date should be added to it: `startDate.datesUntil(endDate.plusDays(1))`. – M. Justin Nov 14 '22 at 17:09
2

The LocalDateRange class in the ThreeTen-Extra library represents a range of dates, and can be used for this purpose:

LocalDateRange.ofClosed(startDate, endDate).stream().toList();
M. Justin
  • 14,487
  • 7
  • 91
  • 130
1

With Joda-Time , maybe it's better:

LocalDate dateStart = new LocalDate("2012-01-15");
LocalDate dateEnd = new LocalDate("2012-05-23");
// day by day:
while(dateStart.isBefore(dateEnd)){
    System.out.println(dateStart);
    dateStart = dateStart.plusDays(1);
}

It's my solution.... very easy :)

mfruizs
  • 770
  • 14
  • 20
1
List<Date> dates = new ArrayList<Date>();
String str_date = "DD/MM/YYYY";
String end_date = "DD/MM/YYYY";
DateFormat formatter = new SimpleDateFormat("dd/MM/yyyy");
Date startDate = (Date)formatter.parse(str_date); 
Date endDate = (Date)formatter.parse(end_date);
long interval = 1000 * 60 * 60; // 1 hour in milliseconds
long endTime = endDate.getTime() ; // create your endtime here, possibly using Calendar or Date
long curTime = startDate.getTime();

while (curTime <= endTime) {
    dates.add(new Date(curTime));
    curTime += interval;
}
for (int i = 0; i < dates.size(); i++){
    Date lDate = (Date)dates.get(i);
    String ds = formatter.format(lDate);    
    System.out.println("Date is ..." + ds);
    //Write your code for storing dates to list
}
Upendra
  • 683
  • 6
  • 23
1

Like as @folone, but correct

private static List<Date> getDatesBetween(final Date date1, final Date date2) {
    List<Date> dates = new ArrayList<>();
    Calendar c1 = new GregorianCalendar();
    c1.setTime(date1);
    Calendar c2 = new GregorianCalendar();
    c2.setTime(date2);
    int a = c1.get(Calendar.DATE);
    int b = c2.get(Calendar.DATE);
    while ((c1.get(Calendar.YEAR) != c2.get(Calendar.YEAR)) || (c1.get(Calendar.MONTH) != c2.get(Calendar.MONTH)) || (c1.get(Calendar.DATE) != c2.get(Calendar.DATE))) {
        c1.add(Calendar.DATE, 1);
        dates.add(new Date(c1.getTimeInMillis()));
    }
    return dates;
}
Krzysztof Szewczyk
  • 1,752
  • 1
  • 21
  • 25
1

You can also look at the Date.getTime() API. That gives a long to which you can add your increment. Then create a new Date.

List<Date> dates = new ArrayList<Date>();
long interval = 1000 * 60 * 60; // 1 hour in millis
long endtime = ; // create your endtime here, possibly using Calendar or Date
long curTime = startDate.getTime();
while (curTime <= endTime) {
  dates.add(new Date(curTime));
  curTime += interval;
}

and maybe apache commons has something like this in DateUtils, or perhaps they have a CalendarUtils too :)

EDIT

including the start and enddate may not be possible if your interval is not perfect :)

extraneon
  • 23,575
  • 2
  • 47
  • 51
1

This is simple solution for get a list of dates

import java.io.*;
import java.util.*;
import java.text.SimpleDateFormat;  
public class DateList
{

public static SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");

 public static void main (String[] args) throws java.lang.Exception
 {

    Date dt = new Date();
    System.out.println(dt);

        List<Date> dates = getDates("2017-01-01",dateFormat.format(new Date()));
        //IF you don't want to reverse then remove Collections.reverse(dates);
         Collections.reverse(dates);
        System.out.println(dates.size());
    for(Date date:dates)
    {
        System.out.println(date);
    }
 }
 public static List<Date> getDates(String fromDate, String toDate)
 {
    ArrayList<Date> dates = new ArrayList<Date>();

    try {

        Calendar fromCal = Calendar.getInstance();
        fromCal.setTime(dateFormat .parse(fromDate));

        Calendar toCal = Calendar.getInstance();
        toCal.setTime(dateFormat .parse(toDate));

        while(!fromCal.after(toCal))
        {
            dates.add(fromCal.getTime());
            fromCal.add(Calendar.DATE, 1);
        }


    } catch (Exception e) {
        System.out.println(e);
    }
    return dates;
 }
}
Hardik Dudhaiya
  • 249
  • 3
  • 9
  • FYI, the troublesome old date-time classes such as [`java.util.Date`](https://docs.oracle.com/javase/8/docs/api/java/util/Date.html), [`java.util.Calendar`](https://docs.oracle.com/javase/8/docs/api/java/util/Calendar.html), and `java.text.SimpleTextFormat` are now [legacy](https://en.wikipedia.org/wiki/Legacy_system), supplanted by the [java.time](https://docs.oracle.com/javase/8/docs/api/java/time/package-summary.html) classes. See [Tutorial by Oracle](https://docs.oracle.com/javase/tutorial/datetime/TOC.html). This work is *much* more easily accomplished using the modern classes. – Basil Bourque Jul 17 '17 at 00:01
0

A tail-recursive version:

public static void datesBetweenRecursive(Date startDate, Date endDate, List<Date> dates) {
    if (startDate.before(endDate)) {
        dates.add(startDate);
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(startDate);
        calendar.add(Calendar.DATE, 1);
        datesBetweenRecursive(calendar.getTime(), endDate, dates);
    }
}
Lluis Martinez
  • 1,963
  • 8
  • 28
  • 42
0

Enhancing one of the above solutions. As adding 1 day to end date sometimes adds an extra day beyond the end date.


    public static List getDaysBetweenDates(Date startdate, Date enddate)
    {
        List dates = new ArrayList();
        Calendar startDay = new GregorianCalendar();
        calendar.setTime(startdate);
        Calendar endDay = new GregorianCalendar();
        endDay.setTime(enddate);
        endDay.add(Calendar.DAY_OF_YEAR, 1);
        endDay.set(Calendar.HOUR_OF_DAY, 0);
        endDay.set(Calendar.MINUTE, 0);
        endDay.set(Calendar.SECOND, 0);
        endDay.set(Calendar.MILLISECOND, 0);

        while (calendar.getTime().before(endDay.getTime())) {
            Date result = startDay.getTime();
            dates.add(result);
            startDay.add(Calendar.DATE, 1);
        }
        return dates;
    }

Saurabh Mishra
  • 1,511
  • 1
  • 11
  • 7
0

Here is my method for getting dates between two dates, including / w.o. including business days. It also takes source and desired date format as parameter.

public static List<String> getAllDatesBetweenTwoDates(String stdate,String enddate,String givenformat,String resultformat,boolean onlybunessdays) throws ParseException{
        DateFormat sdf;
        DateFormat sdf1;
        List<Date> dates = new ArrayList<Date>();
        List<String> dateList = new ArrayList<String>();
          SimpleDateFormat checkformat = new SimpleDateFormat(resultformat); 
          checkformat.applyPattern("EEE");  // to get Day of week
        try{
            sdf = new SimpleDateFormat(givenformat);
            sdf1 = new SimpleDateFormat(resultformat);
            stdate=sdf1.format(sdf.parse(stdate));
            enddate=sdf1.format(sdf.parse(enddate));

            Date  startDate = (Date)sdf1.parse( stdate); 
            Date  endDate = (Date)sdf1.parse( enddate);
            long interval = 24*1000 * 60 * 60; // 1 hour in millis
            long endTime =endDate.getTime() ; // create your endtime here, possibly using Calendar or Date
            long curTime = startDate.getTime();
            while (curTime <= endTime) {
                dates.add(new Date(curTime));
                curTime += interval;
            }
            for(int i=0;i<dates.size();i++){
                Date lDate =(Date)dates.get(i);
                String ds = sdf1.format(lDate);   
                if(onlybunessdays){
                    String day= checkformat.format(lDate); 
                    if(!day.equalsIgnoreCase("Sat") && !day.equalsIgnoreCase("Sun")){
                          dateList.add(ds);
                    }
                }else{
                      dateList.add(ds);
                }

                //System.out.println(" Date is ..." + ds);

            }


        }catch(ParseException e){
            e.printStackTrace();
            throw e;
        }finally{
            sdf=null;
            sdf1=null;
        }
        return dateList;
    }

And the method call would be like :

public static void main(String aregs[]) throws Exception {
        System.out.println(getAllDatesBetweenTwoDates("2015/09/27","2015/10/05","yyyy/MM/dd","dd-MM-yyyy",false));
    }

You can find the demo code : Click Here

ThmHarsh
  • 601
  • 7
  • 7
0
List<LocalDate> totalDates = new ArrayList<>();
popularDatas(startDate, endDate, totalDates);
System.out.println(totalDates);

private void popularDatas(LocalDate startDate, LocalDate endDate, List<LocalDate> datas) {
    if (!startDate.plusDays(1).isAfter(endDate)) {
        popularDatas(startDate.plusDays(1), endDate, datas);
    } 
    datas.add(startDate);
}

Recursive solution

Gleidosn
  • 193
  • 1
  • 6
0

This will add all dates between two dates and It will add current dates and then new dates will be added based on loop condition.

private void onDateSet(){
    Calendar endDate = Calendar.getInstance(),startDate = Calendar.getInstance();
    startDate.set(currentYear,currentMonthOfYear,currentDayOfMonth);
    endDate.set(inputYear,inputMonthOfYear,inputDayOfMonth);
    datesToAdd(startDate,endDate);
    }

    //call for get dates list
    private List<Date> datesToAdd(Calendar startDate,Calendar endDate){
                    List<Dates> datesLists = new List<>();
                    while (startDate.get(Calendar.YEAR) != endDate.get(Calendar.YEAR) ||   
                           startDate.get(Calendar.MONTH) != endDate.get(Calendar.MONTH) ||
                           startDate.get(Calendar.DAY_OF_MONTH) != endDate.get(Calendar.DAY_OF_MONTH)) {

                             datesList.add(new Date(startDate.get(Calendar.YEAR), startDate.get(Calendar.MONTH), startDate.get(Calendar.DATE));

                             startDate.add(Calendar.DATE, 1);//increas dates

                         }
                         return datesList;
                }
ankurdayalsingh
  • 260
  • 2
  • 9
  • FYI, this code uses troublesome old date-time classes that are now legacy, supplanted by the java.time classes. – Basil Bourque Nov 22 '17 at 05:19
  • I didn't use java.time classes. I used import java.util.Calendar; import java.util.Date; I am using Java 8 all are working properly. – ankurdayalsingh Nov 22 '17 at 09:41
  • **Do *not* use `Calendar` and `Date`.** They are now replaced by the java.time classes. Those old classes are confusing, poorly designed, and flawed. Sun, Oracle, and the JCP community all agreed to replace those legacy classes with the java.time classe; see [JSR 310](https://jcp.org/en/jsr/detail?id=310). Suggesting `Date` and `Calendar` in 2017 is ill-advised. – Basil Bourque Nov 22 '17 at 15:53