我想要一个开始日期和结束日期之间的日期列表。
结果应该是所有日期的列表,包括开始和结束日期。
Answers:
早在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);
}
实现您自己的迭代器也可以做到这一点并不难,那就更好了。
如果您使用的是Java 8,则有一种更简洁的方法。Java 8中新的java.time包合并了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);
}
ArrayList
构造函数传递经过的天数来设置列表的初始容量。int initialCapacity = java.lang.Math.toIntExact( ChronoUnit.DAYS.between( start , end ) ) ;
获取日期之间的天数(含)。
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;
}
fechaFinal
使用before()
方法(等于<操作)时,最终列表将不包含(结束日期)。而是应使用<=操作。由于Calendar
课堂上没有等效的方法,因此您应该稍微增加结束日期。
enddate
最后一天,则不会显示。比较时代以来的时间将解决此问题: while (calendar.getTime().getTime() <= enddate.getTime())
java.util.Date
,java.util.Calendar
和java.text.SimpleDateFormat
现在的遗产,由取代java.time内置到Java 8和更高等级。请参见Oracle教程。
编辑:现在不推荐使用Joda-Time,将答案改为使用Java 8。
这是使用流的Java 8方法。
List<LocalDate> daysRange = Stream.iterate(startDate, date -> date.plusDays(1)).limit(numOfDays).collect(Collectors.toList());
请找到以下代码。
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
在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(...)
的结束日期不限,因此所示的hack增加了一天。
一旦获得流,就可以利用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());
使用Java 8
public Stream<LocalDate> getDaysBetween(LocalDate startDate, LocalDate endDate) {
return IntStream.range(0, (int) DAYS.between(startDate, endDate)).mapToObj(startDate::plusDays);
}
这样的事情肯定应该起作用:
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;
}
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
一种解决方案是创建一个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;
}
您也可以查看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 :)
编辑
如果间隔不完美,则可能无法包括开始日期和结束日期:)
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
}
就像@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
实例?
使用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);
}
这是我的解决方案...。非常简单:)
compareTo
您不使用,则该代码可能更具可读性dateStart.isBefore( dateEnd )
。
这是获取日期列表的简单解决方案
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;
}
}
java.util.Date
,java.util.Calendar
和java.text.SimpleTextFormat
现在的遗产,由取代java.time类。请参见Oracle教程。这项工作是多运用现代类更容易实现。
尾递归版本:
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);
}
}
增强上述解决方案之一。由于有时会在结束日期前增加1天,因此会在结束日期后增加一天。
公共静态列表getDaysBetweenDates(日期开始日期,日期结束日期) { 列出日期= new ArrayList(); 日历startDay = new GregorianCalendar(); calendar.setTime(startdate); 日历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())){ 日期结果= startDay.getTime(); date.add(result); startDay.add(Calendar.DATE,1); } 返回日期; }
这是我获取两个日期之间的日期的方法,包括/包括工作日在内。它还将源和所需日期格式作为参数。
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));
}
您可以找到演示代码:单击此处
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);
}
递归解决方案
这将添加两个日期之间的所有日期,并将添加当前日期,然后根据循环条件添加新日期。
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;
}