生成Java中两个给定日期之间的所有日期

我正在尝试获得一系列日期,而我的输入是’from’/’to’结​​构。 所以我的意见是:

String date1 = "2014-01-01"; String date2 = "2014-05-01"; 

我的输出应该是一个Arraylist,所有日期都在date1和date2之间。 我已经找到了这个,但我只能找到关于2个日期之间差异的问题:

 SimpleDateFormat myFormat = new SimpleDateFormat("dd MM yyyy"); String inputString1 = "23 01 1997"; String inputString2 = "27 04 1997"; try { Date date1 = myFormat.parse(inputString1); Date date2 = myFormat.parse(inputString2); long diff = date2.getTime() - date1.getTime(); System.out.println ("Days: " + TimeUnit.DAYS.convert(diff,TimeUnit.MILLISECONDS)); } catch (ParseException e) { e.printStackTrace(); } 

任何提示或建议? 所有其他问题适用于iOS或SQL。

看看JodaTime: http ://joda-time.sourceforge.net/apidocs/org/joda/time/DateTime.html

 DateTime dateTime1 = new DateTime(date1); DateTime dateTime2 = new DateTime(date2); List allDates = new ArrayList(); while( dateTime1.before(dateTime2) ){ allDates.add( dateTime1.toDate() ); dateTime1 = dateTime1.plusDays(1); } 

如果您不想使用第三方库,可以使用Calendar

点击这里查看工作演示 。

 public static void main(String[] args) throws Exception { SimpleDateFormat myFormat = new SimpleDateFormat("dd MM yyyy"); String inputString1 = "23 01 1997"; String inputString2 = "27 04 1997"; ArrayList dates = new ArrayList(); try { Date date1 = myFormat.parse(inputString1); Calendar c1 = DateToCalendar(date1); Date date2 = myFormat.parse(inputString2); Calendar c2 = DateToCalendar(date2); while (!areEqualDate(c1, c2)) { dates.add(c1.getTime()); System.out.println (c1.getTime()); c1.add(Calendar.DAY_OF_YEAR, 1); } } catch (ParseException e) { e.printStackTrace(); } // ArrayList dates >> contain all dates between both given days. } private static boolean areEqualDate(Calendar c1, Calendar c2) { if (c1.get(Calendar.YEAR) != c2.get(Calendar.YEAR)) return false; if (c1.get(Calendar.MONTH) != c2.get(Calendar.MONTH)) return false; if (c1.get(Calendar.DAY_OF_YEAR) != c2.get(Calendar.DAY_OF_YEAR)) return false; return true; } public static Calendar DateToCalendar(Date date) { Calendar cal = Calendar.getInstance(); cal.setTime(date); return cal; } 

我喜欢JodaTime,但是这也可以通过使用java.util.Calendar在没有第三方库的情况下完成。 给定一个Calendar对象,可以使用其add方法来增加日期的某些字段,同时遵守日历规则(例如,将1月31日的1天添加到2月1日,而不是1月32日)。

首先按正确的时间顺序将日期分别放入一个Calendar对象中,以便稍后添加正确的方向:

  Calendar cStart = Calendar.getInstance(), cStop = Calendar.getInstance(); if (date1.before(date2)) { cStart.setTime(date1); cStop.setTime(date2); } else { cStart.setTime(date2); cStop.setTime(date1); 

date1date2是您问题中解析的Date对象,为简单起见。

接下来,循环“添加1到每年的日期”指令,直到超出停止日期为止:

 do { System.out.println(pretty(cStart)); cStart.add(Calendar.DAY_OF_YEAR, 1); } while (cStart.before(cStop)); 

最后打印停止日期

  System.out.println(pretty(cStop)); 

pretty()只是通过SDF发送日历的一些迷你方法,就像你用来解析字符串的那个。

此解决方案将打印日期范围,包括开始日期和停止日期,并可能需要围绕边缘情况进行一些调整(如date1==date2 )。 可以轻松调整以排除开始和停止日期。 当然可以交换打印进行聚合。 要从日历中获取Date对象,请使用getTime()方法(返回快照,而不是实时引用)。

可以在此处找到相关(Gregorian)Calendar的文档。

下面是获取 两个字符串 日期之间的日期数组的代码。

 import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Calendar; import java.util.Date; import java.util.GregorianCalendar; import java.util.List; public class DateFormatExample { public static void main(String[] args) { // TODO Auto-generated method stub SimpleDateFormat myFormat = new SimpleDateFormat("yyyy-MM-dd"); SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd"); String date1 = "2014-01-01"; String date2 = "2014-05-01"; try { Date d1 = myFormat.parse(date1); Date d2 = myFormat.parse(date2); List allDates = new ArrayList(); List allDatesString = new ArrayList(); while( d1.before(d2) ){ d1 = addDays(d1, 1); allDates.add(d1); allDatesString.add(formatter.format(d1)); } System.out.println(allDates); System.out.println(allDatesString); } catch (ParseException e) { e.printStackTrace(); } } private static Date addDays(Date d1, int i) { GregorianCalendar cal = new GregorianCalendar(); cal.setTime(d1); cal.add(Calendar.DATE, 1); return cal.getTime(); } } 

如果您使用的是Guava,这个问题有一个非常优雅的解决方案。

Guava有两个简洁的类,例如Range和ContiguousSet ,它们可以完全满足您的需求:第一个操作值范围,第二个操作 – 能够将范围转换为一组离散值。

两者的使用示例(与JodaTime一起):

 LocalDate start = LocalDate.parse("2015-01-01"); LocalDate end = LocalDate.parse("2019-02-01"); Range range = Range.closed(start, end); //Creates a "closed" range, that is both dates are inclusive. There are also options like "openClosed", "closedOpen" and "open" final Set daySet = ContiguousSet.create(range, LocalDateDomain.INSTANCE); //Create a "virtual" set of days in given the range. "virtual" part means that if you create a set of 10 thousand years, it will not eat your memory at all for (LocalDate day : daySet) { //...operation... } 

就个人而言,我更喜欢这种方式,因为它消除了理解封闭/开放范围的一些问题,并使代码更容易阅读和理解,同时不会影响性能。 此外,它适用于任何类型的日期,任何库(您可以将YodaTime交换为Java8日期甚至Java7-基于日期的实现)。

此外,它允许您在交叉点,联合,范围跨度,令人难以置信的快速“包含”等范围内进行一些巧妙的操作。

唯一的缺点是:

  1. 对番石榴的依赖。
  2. 需要创建一个特殊的“DiscreteDomain”类,Guava用它来理解一个日期结束和其他日期的开始。

LocalDateDomain实现的示例,它作为Guava和JodaTime之间的桥梁运行:

 public class LocalDateDomain extends DiscreteDomain { public static final LocalDateDomain INSTANCE = new LocalDateDomain(); @Override public LocalDate next(LocalDate value) { return value.plusDays(1); } @Override public LocalDate previous(LocalDate value) { return value.minusDays(1); } @Override public long distance(LocalDate start, LocalDate end) { return Days.daysBetween(start, end).getDays(); } } 

我已经知道OP不使用Java 8,但这是当前的解决方案 – Java已经过改进,新的java.time API在这方面完成了所有可能的工作:

 //change these values : LocalDate ld1 = LocalDate.ofEpochDay(0); LocalDate ld2 = LocalDate.now(); //do NOT change these: final LocalDate begin = ld1.isBefore(ld2) ? ld1 : ld2; final LocalDate end = ld2.isAfter(ld1) ? ld2 : ld1; for (int i = 0; i < begin.until(end, ChronoUnit.DAYS); i++) { final LocalDate curDate = begin.plusDays(i); System.out.println("current date : " + curDate); } 

这将输出两个日期之间的每个有效日期,而大多数其他解决方案也会给你无效的日期; 事实上:时间计算需要在与时区无关的数据上进行 - 另一方面, 输出可能很好地是时区和/或按时间顺序排列的。 这就是为什么有像java.time.format这样的软件包 - 只需计算你的时间/日期值并为你选择的区域格式化它们......这就是它是如何正确完成的。

如果你需要转换时间输入,那么time-API中也有很多有用的function,我建议你就这个主题做一个全面的教程,一些很好的介绍可能是这个 ,特别是 :

表示时间有两种基本方法。 一种方式代表人类的时间,称为人类时间,例如年,月,日,小时,分钟和秒。 另一方面,机器时间,沿着来自原点的时间线连续测量时间,称为时期,以纳秒分辨率。 Date-Time包提供了丰富的类数组,用于表示日期和时间。 Date-Time API中的某些类用于表示机器时间,而其他类更适合表示人工时间。