7

我正在尝试获取日期数组,而我的输入是“从”/“到”结构。所以我的输入是:

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

我的输出应该是一个包含 date1 和 date2 之间所有日期的 Arraylist。我已经寻找过这个,但我只能找到关于 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 的。

4

6 回答 6

4

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

DateTime dateTime1 = new DateTime(date1);
DateTime dateTime2 = new DateTime(date2);

List<Date> allDates = new ArrayList();

while( dateTime1.before(dateTime2) ){
   allDates.add( dateTime1.toDate() );
   dateTime1 = dateTime1.plusDays(1);
}
于 2015-09-03T09:59:15.627 回答
3

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

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<Date> allDates = new ArrayList<Date>();
            List<String> allDatesString = new ArrayList<String>();
            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();
    }

}
于 2015-09-03T11:27:49.413 回答
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<Date> dates = new ArrayList<Date>();

    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<Date> 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;
}
于 2015-09-03T10:07:49.830 回答
1

我喜欢 JodaTime,但这也可以在没有 3rd 方库的情况下使用java.util.Calendar. 给定一个Calendar对象,可以使用它的add方法来增加日期的某些字段,同时遵守日历规则(例如将 1 天添加到 1 月 31 日让您到 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);

date1并且date2是从您的问题中解析的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可在此处找到。

于 2015-09-03T10:15:30.520 回答
0

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

Guava 有两个简洁的类,例如RangeContiguousSet,它们完全实现了您所需要的:第一个对值范围进行操作,第二个 - 能够将范围转换为一组离散值。

两者的使用示例(连同 JodaTime):

LocalDate start = LocalDate.parse("2015-01-01");
LocalDate end = LocalDate.parse("2019-02-01");
Range<LocalDate> 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<LocalDate> 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 Dates 甚至 Java7-基于日期的实现)。

此外,它还允许您对范围进行一些简洁的操作,例如交集、联合、范围的跨越、令人难以置信的快速“包含”等等。

唯一的缺点是:

  1. 对番石榴的依赖。
  2. 需要创建一个特殊的“DiscreteDomain”类,Guava 使用该类来了解一个日期的结束位置和另一个日期的开始位置。

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

public class LocalDateDomain extends DiscreteDomain<LocalDate> {
    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();
    }
}
于 2015-09-03T11:47:34.430 回答
0

我已经知道 OP 没有使用 Java 8,但这是当前的解决方案 - Java 已经过改进,新的java.timeAPI 在这方面做了所有可以想象的工作:

//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 中也有一些有用的功能,我建议您对该主题进行全面的教程,一些很好的介绍可能是这样,尤其

有两种表示时间的基本方式。一种方式用人类术语表示时间,称为人类时间,例如年、月、日、小时、分钟和秒。另一种方式,机器时间,以纳秒分辨率沿时间线从一个原点(称为纪元)连续测量时间。Date-Time 包提供了丰富的类数组来表示日期和时间。Date-Time API 中的一些类旨在表示机器时间,而其他类更适合表示人类时间。

于 2015-09-03T10:46:01.840 回答