【问题标题】:how to get a list of dates between two dates in java如何在java中获取两个日期之间的日期列表
【发布时间】:2011-02-10 23:24:01
【问题描述】:

我想要一个开始日期和结束日期之间的日期列表。

结果应该是所有日期的列表,包括开始日期和结束日期。

【问题讨论】:

  • 对于那些使用 groovy(使用 LocalDate)的人:(fromDate..toDate).each { println it }

标签: java date


【解决方案1】:

你可以这样计算的java9特征

public  List<LocalDate> getDatesBetween (
 LocalDate startDate, LocalDate endDate) {

   return startDate.datesUntil(endDate)
     .collect(Collectors.toList());
}
`` 


【讨论】:

  • Hochschild 的回答中已经涵盖了这个解决方案。
【解决方案2】:

编辑:Joda-Time 现已弃用,将答案改为使用 Java 8。

这是使用流的 Java 8 方式。

List<LocalDate> daysRange = Stream.iterate(startDate, date -> date.plusDays(1)).limit(numOfDays).collect(Collectors.toList());

【讨论】:

  • numofDays 可以找到 long numofDays = ChronoUnit.DAYS.between(startDate, endDate);
  • 如果您使用的是 Java 8 及更高版本,则无需使用 Joda-Time 库。 Joda-Time 项目现在位于 maintenance mode,团队建议迁移到 Java 8 及更高版本中内置的 java.time 类。见Tutorial by Oracle。请参阅Answer by Hochschild
  • 为什么我需要在 numOfDays 中添加 +1 才能将 endDate 也加入到列表中?
  • @pipilam 你没有为 numOfDays 添加 +1,而是在你迭代的那一天添加 1
【解决方案3】:

早在 2010 年,我建议使用 Joda-Time

请注意,Joda-Time 现在处于维护模式。从 1.8 (2014) 开始,您应该使用 java.time

一次添加一天,直到结束日期:

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);
}

实现自己的迭代器也不会太难,这样会更好。

【讨论】:

  • 对于替代方案,请参阅同一问题上的answer by Krishnan
  • 提示通过调用 plusDays 来简化代码。所以这个LocalDate d = startDate.withFieldAdded(DurationFieldType.days(), i);变成了这个LocalDate d = startDate.plusDays(i);
  • 仅供参考,Joda-Time 项目现在位于maintenance mode,团队建议迁移到java.time 类。见Tutorial by Oracle
  • 列表不包含结束日期,将 i
  • 有人可以用当前的 java.time api 更新它吗?它一直让人们感到困惑(他们在 2019 年不断提出有关 jodatime 的问题)。
【解决方案4】:

推荐日期流

Java 9,您可以使用以下新方法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());

新方法datesUntil(...) 使用独占结束日期,因此显示的黑客可以添加一天。

获得流后,您可以利用java.util.stream- 或java.util.function-packages 提供的所有功能。 与基于自定义 for 或 while 循环的早期方法相比,使用流变得如此简单。


或者,如果您正在寻找一种基于流的解决方案,该解决方案默认在包含日期运行,但也可以配置为其他方式,那么您可能会发现我的库 Time4J 中的类 DateInterval 很有趣,因为它提供了许多特殊功能围绕日期流,包括比 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);

如果是整月,甚至更简单:

Stream<PlainDate> februaryDates = CalendarMonth.of(2017, 2).streamDaily();
List<LocalDate> list = 
    februaryDates.map(PlainDate::toTemporalAccessor).collect(Collectors.toList());

【讨论】:

    【解决方案5】:

    这将添加两个日期之间的所有日期,它将添加当前日期,然后将根据循环条件添加新日期。

    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;
                    }
    

    【讨论】:

    • 仅供参考,这段代码使用了麻烦的旧日期时间类,这些类现在是遗留的,被 java.time 类所取代。
    • 我没有使用 java.time 类。我使用了 import java.util.Calendar;导入 java.util.Date;我正在使用 Java 8,一切正常。
    • 不要使用CalendarDate它们现在被java.time类所取代。那些旧的类令人困惑、设计不佳且存在缺陷。 Sun、Oracle 和 JCP 社区都同意用 java.time 类替换那些遗留类;见JSR 310。在 2017 年建议 DateCalendar 是不明智的。
    【解决方案6】:

    这是获取日期列表的简单解决方案

    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;
     }
    }
    

    【讨论】:

    【解决方案7】:
    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);
    }
    

    递归解

    【讨论】:

      【解决方案8】:

      使用 java 8

      public Stream<LocalDate> getDaysBetween(LocalDate startDate, LocalDate endDate) {
          return IntStream.range(0, (int) DAYS.between(startDate, endDate)).mapToObj(startDate::plusDays);
      }
      

      【讨论】:

      • 我发现它是最好的解决方案,只是你可以使用 LongStream 而不是 IntStream 来避免强制转换。
      【解决方案9】:
       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;
          }
      

      【讨论】:

      • 可怕的 Calendar 类现在已被遗留,被现代的 java.time 类所取代,并采用了 JSR 310。
      【解决方案10】:

      java.time 包

      如果您使用Java 8,则有一种更简洁的方法。 Java 8 中的新java.time package 包含Joda-Time API 的功能。

      您的要求可以使用以下代码解决:

      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);
      }
      

      【讨论】:

      • 仅供参考,对于那些还不能迁移到 Java 8 的人来说,使用 Joda-Time library 可以使用完全相同的代码。虽然 java.time 不是 Joda-Time 的替代品,但在这种特殊情况下,代码恰好是相同的。
      • 您可以通过将经过的天数传递给ArrayList 构造函数来设置列表的初始容量。 int initialCapacity = java.lang.Math.toIntExact( ChronoUnit.DAYS.between( start , end ) ) ;
      • 请注意,Java 9 使用Stream&lt;LocalDate&gt; 使LocalDate 的这种使用变得更加容易,无需构建自己的while 循环。见the Answer by Hochschild
      • 如果我想用这个找到并分离出工作日和周末怎么办?我该怎么做?
      • LocalDate 有获取 DayOfWeek 的方法。检查一下。
      【解决方案11】:

      这是我在两个日期之间获取日期的方法,包括 / w.o.包括工作日。它还将源和所需的日期格式作为参数。

      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;
          }
      

      方法调用会是这样的:

      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));
          }
      

      您可以找到演示代码:Click Here

      【讨论】:

        【解决方案12】:

        增强上述解决方案之一。因为在结束日期之后添加 1 天有时会在结束日期之后增加一天。

        公共静态列表 getDaysBetweenDates(日期开始日期,日期结束日期) { 列出日期 = new ArrayList(); 日历 startDay = new GregorianCalendar(); 日历.setTime(开始日期); 日历 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); 而(calendar.getTime().before(endDay.getTime())){ 日期结果 = startDay.getTime(); 日期。添加(结果); startDay.add(Calendar.DATE, 1); } 返回日期; }

        【讨论】:

          【解决方案13】:

          获取日期之间的天数,包括日期。

          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;
          }
          

          【讨论】:

          • 一般情况下,当您使用before() 方法(等于fechaFinal(结束日期)。相反,应该使用 Calendar 类中没有等效方法,因此您应该将结束日期增加一点。
          • 结束日期加 1 不能提供完整的证明解决方案,直到我们将结束日期的时间信息重置为 0
          • 如果使用午夜作为enddate 最后一天将不会显示。比较自纪元以来的时间将解决此问题:while (calendar.getTime().getTime() &lt;= enddate.getTime())
          • 仅供参考,麻烦的旧日期时间类,如 java.util.Datejava.util.Calendarjava.text.SimpleDateFormat 现在是 legacy,被 Java 8 及更高版本中内置的 java.time 类所取代.见Tutorial by Oracle
          【解决方案14】:

          尾递归版本:

          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);
              }
          }
          

          【讨论】:

          • 与 Jules Rogerson 的相同,但递归而不是迭代
          【解决方案15】:

          使用 Joda-Time 可能会更好:

          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);
          }
          

          这是我的解决方案....非常简单:)

          【讨论】:

          • 仅供参考,如果您使用 dateStart.isBefore( dateEnd ) 而不是 compareTo,则该代码可能更具可读性。
          【解决方案16】:

          Lamma 在 Java 中看起来像这样:

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

          输出是:

              Date(2014,6,29)
              Date(2014,6,30)
              Date(2014,7,1)
          

          【讨论】:

            【解决方案17】:

            这样的事情肯定会起作用:

            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;
            }
            

            【讨论】:

              【解决方案18】:

              类似于@folone,但正确

              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;
              }
              

              【讨论】:

              • 为什么不使用before()after() 方法来比较两个Calendar 实例?
              【解决方案19】:
              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
              }
              

              【讨论】:

                【解决方案20】:

                请找到下面的代码。

                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);
                }
                

                输出:

                日期是 ...27/08/2010
                日期是 ...28/08/2010
                日期是 ...29/08/2010
                日期是 ...30/08/2010
                日期是 ...31/08/2010
                日期是 ...01/09/2010
                日期是 ...02/09/2010

                【讨论】:

                • 这在夏令时结束时不起作用,因为那天有 25 小时。你会得到第二天重复。德国示例:日期为 ...30/10/2010 |日期是...31/10/2010 |日期是...31/10/2010 |日期是 ...01/11/2010(简单的解决方案:在开始日期上增加几个小时 (12))
                【解决方案21】:

                一种解决方案是创建一个Calendar 实例,然后开始一个循环,增加它的Calendar.DATE 字段,直到达到所需的日期。此外,在每个步骤中,您都应该创建一个 Date 实例(带有相应的参数),并将其放入您的列表中。

                一些脏代码:

                    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;
                }
                

                【讨论】:

                • 您知道您使用的是已弃用的 API 吗?是的。Java 日期处理很烂。
                • 我认为 while 的条件是 OR 而不是 AND
                【解决方案22】:

                您还可以查看Date.getTime() API。这给了一个很长的时间,你可以添加你的增量。然后创建一个新的日期。

                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;
                }
                

                也许 apache commons 在 DateUtils 中有类似的东西,或者他们也有 CalendarUtils :)

                编辑

                如果您的间隔不完美,则可能无法包含开始结束日期:)

                【讨论】:

                  猜你喜欢
                  • 2010-10-05
                  • 2018-09-17
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 2018-01-11
                  • 1970-01-01
                  • 1970-01-01
                  相关资源
                  最近更新 更多