本问题已经有最佳答案,请猛点这里访问。
从用户每次完成任务开始,我就有一系列独特的日期。我想检查数组中的日期是否连续,包括今天的日期。
如果数组包含日期:"2017/6/2, 2017/6/3, 2017/6/4, 2017/6/5",那么根据今天的日期为2017/6/5,函数将返回4,因为从今天开始(包括今天)有4个连续的日期。
如果数组包含日期"2017/6/2, 2017/6/3, 2017/6/4",那么它将返回0,因为数组不包含今天的日期。否则,计数将在非连续日期中断。
List dateList = new ArrayList();
int count = 0;
Date todayDate = new Date();
for (int i=0; i
// Check if dates within the array are consecutive from todayDate, if so then increment count by 1.
}
日期列表排序了吗?
计算两个日期之间的差异并遍历列表,如果任何地方都为false,则约定失败。
是的,它是经过排序的,并且只包含唯一的日期。
你可以使用Joda时间:1。对列表中的日期进行排序。2。在列表3中找到"今天"。从今天开始,用函数:Days.daysBetween(indexDay.withTimeAtStartOfDay() , (index+n/-n)Day.withTimeAtStartOfDay() ).getDays()检查索引,看看是否是2个序列日。
@KingFisherPhooc Jodatime正在停产,取而代之的是更新的API。在Joda的网站上,它说注意到Joda时间被认为是一个很大程度上"完成"的项目。没有计划进行重大改进。如果使用JavaSE 8,请迁移到JavaTimes(JSR-310)。如果使用Java>=8,则使用新的EDCOX1和1的API,而对于Java
如果使用Java 8,请考虑使用新的JavaTimeAPI。与旧的API相比,它更容易、更少被窃听和更少出错。
如果您使用的是Java
尽管您也可以使用jodatime,但它已经被新的API中断并替换了,我不建议用joda启动新的项目吗?即使在Joda的网站上,它也说:"请注意,Joda时间被认为是一个很大程度上"完成"的项目。没有计划进行重大改进。如果使用JavaSE 8,请迁移到JavaTimes(JSR-310)。
由于您只想比较日期(日/月/年),而不想比较时间(小时/分钟/秒),所以最好的选择是使用LocalDate类。对于Java 8,这个类是在EDCOX1×1的封装中,在三端口后端,包是EDOCX1×2。但是类和方法的名称是相同的。
代码如下:
public int count(List dateList, LocalDate today) {
if (!dateList.contains(today)) { // today is not in the list, return 0
return 0;
}
int count = 0;
LocalDate prev = dateList.get(0); // get first date from list
for (int i = 1; i < dateList.size(); i++) {
LocalDate next = dateList.get(i);
if (prev.plusDays(1).equals(next)) {
// difference between dates is one day
count++;
} else {
// difference between dates is not 1
// Do what? return 0? throw exception?
}
prev = next;
}
return count + 1; // didn't count the first element, adding 1
}
号
测试此方法:
List dateList = new ArrayList<>();
dateList.add(LocalDate.of(2017, 6, 2));
dateList.add(LocalDate.of(2017, 6, 3));
dateList.add(LocalDate.of(2017, 6, 4));
dateList.add(LocalDate.of(2017, 6, 5));
LocalDate today = LocalDate.now();
System.out.println(count(dateList, today)); // 4
另一个测试(当今天不在列表中时)
List dateList = new ArrayList<>();
dateList.add(LocalDate.of(2017, 6, 2));
dateList.add(LocalDate.of(2017, 6, 3));
dateList.add(LocalDate.of(2017, 6, 4));
LocalDate today = LocalDate.now();
System.out.println(count(dateList, today)); // 0
。
笔记:
由于没有规定在不连续的日子里该怎么做(返回0或抛出异常),我留下了这部分评论。但是将它添加到代码中应该很简单
如果你想把java.util.Date转换成LocalDate的话,你可以这样做(使用这个答案的代码,如果你有任何问题,在这个链接中有完整的解释):
public LocalDate convert(Date date) {
return date.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
}
// if your Date has no toInstant method, try this:
public LocalDate convert(Date date) {
return Instant.ofEpochMilli(date.getTime()).atZone(ZoneId.systemDefault()).toLocalDate();
}
我知道你想连续检查几天(所以日期之间相差一天)。但是如果你想检查上一个日期是否在下一个日期之前(不管多少天),你可以把if (prev.plusDays(1).equals(next))改为if (prev.isBefore(next))。
我不确定是不是这样,但是如果你愿意,你也可以直接把一个String解析成一个LocalDate(所以你不需要创建很多Date对象),使用DateTimeFormatter:
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy/M/d");
LocalDate d = LocalDate.parse("2017/6/2", formatter); // 2017-06-02
。
嗨,谢谢你的详细回答。我正在使用JDK1.8.0 U91,但是我似乎无法导入localDate类或java.time类。你知道为什么吗?
@Ryan.h-你已经为Android标记了这个问题。虽然您可能使用JDK 1.8,但Android不包括EDCOX1和0个类(以及Java API的许多其他部分)。Android有它自己的API,它主要基于Java 1.7。
我错过了那个小细节。我已经编辑了答案并包含了Android的threetenabp的信息(这样你就可以使用threeten backport)。@泰德霍普,谢谢你提醒我!
@我已经更新了答案,提供了更多关于缺失类的信息(以及如何在android中使用threeten backport)和其他一些小细节,希望能有所帮助。
谢谢你的澄清。我已经添加了backport,但它无法识别toInstant()方法。试图找出原因!
@Ryan.h我已经更新了答案(而不是date.toInstant(),你可以使用Instant.ofEpochMilli(date.getTime())——稍长一点,但相当。
现在我意识到,在Java 8中引入了EDCOX1×1的方法,以及EDCOX1和0个类。因此,如果一个不可用,另一个也不可用。
是的,我也得出了同样的结论!谢谢你的帮助,回答得很好。需要添加的一件事是androidthreeten.init(this);在onCreate中调用以使其全部工作:)
在后端口中有一个DateTimeUtils类,它具有与遗留类之间的转换。我想你是在追DateTimeUtils.toInstant(Date)。
如果我理解正确的要求,您有一组按日期排序的Date对象,并且保证在同一天内不会有两个Date对象,但可能有两天的间隔。您的目标是返回最大子数组的长度,该数组只包含连续的天数,并且还包含当前日期,或者如果没有此类子数组,则返回0。当前日期可能落在该子数组的任何位置,不一定是在开始或结束时。
目前还不清楚你是否需要支持跨越年份界限,但我想是这样。我还假设列表中的所有Date对象都属于同一时区,也就是运行设备的时区。如果不是这样的话,您应该参考这个答案了解更多关于测试两个Date对象是否在同一天引用的信息。
如果使用Calendar对象而不是Date对象,那么这样做相当简单。您不需要任何第三方库,因为Date和Calendar都是标准Android API的一部分。我建议分两个阶段执行此操作:首先在数组中搜索当前日期,然后在两个方向上扫描日期或数组边界中的间隙。然后数一数你能朝哪个方向走多远。
public int getDateSpanCount(List dateList) {
final int n = dateList.size();
final Calendar today = Calendar.getInstance();
final Calendar other = Calendar.getInstance();
int count = 0;
// First search for today in the date array
int posToday = -1;
for (int i=0; i
other.setTime(dateList.get(i));
if (areSameDay(today, other)) {
posToday = i;
break;
}
}
// If today is in the list, count the size of the sub-array containing today
if (posToday >= 0) {
count++; // count today, at least
final Calendar probe = Calendar.getInstance();
// scan backwards from position of today's date
for (int prevPos = posToday - 1; prevPos >= 0; prevPos--) {
final Date prev = dateList.get(prevPos);
probe.setTime(prev);
other.add(Calendar.DAY_OF_YEAR, -1);
if (areSameDay(probe, other)) {
count++;
other.setTime(prev);
} else {
break;
}
}
// reset the other time
other.setTime(today.getTime());
// scan forward from position of today's date
for (int nextPos = posToday + 1; nextPos < n; nextPos++) {
final Date next = dateList.get(nextPos);
probe.setTime(next);
other.add(Calendar.DAY_OF_YEAR, 1);
if (areSameDay(probe, other)) {
count++;
other.setTime(next);
} else {
break;
}
}
}
return count;
}
/** Test whether two Calendar objects are set to the same day */
private static boolean areSameDay(Calendar c1, Calendar c2) {
// see discussion above if dates may not all be for the local time zone
return c1.get(Calendar.YEAR) == c2.get(Calendar.YEAR) &&
c1.get(Calendar.DAY_OF_YEAR) == c2.get(Calendar.DAY_OF_YEAR);
}
。
谢谢你的回复。研究你解决问题的方法真的很有趣!很有魅力。这个不需要依赖性的答案显然更可取。在Aresameday方法中,我认为如果我没有弄错的话,cal1和cal2应该是c1和c2!
@是的,cal1和cal2是错误的。谢谢你接电话。
当然,在添加对第三方库的依赖之前,我已经三思而后行了,但threetenabp似乎很有前途:java.time/jsr-310迟早会出现在Android上。
@奥列夫-看来你是对的。java.time包出现在Android o预览版的api文档中。谷歌很可能最终会推出一个兼容库来支持以前的API级别的java.time端口。
有很多方法可以写得更清楚:
使用新的日期API;
使用图书馆;
但是,在这种情况下,使用旧的日期类,我会这样做:
public static void main(String[] args) {
long millisInDay = TimeUnit.DAYS.toMillis(1);
List dates = Arrays.asList(new Date("2017/6/2"), new Date("2017/6/3"), new Date("2017/6/4"), new Date("2017/6/5"));
System.out.println(getSequentialNumber(millisInDay, dates));
}
private static int getSequentialNumber(long millisInDay, List dates) {
int count = 0;
Date now = setMidnight(Calendar.getInstance().getTime());
for (int i = dates.size() - 1; i >= 0; i--) {
Date date = setMidnight(dates.get(i));
if (date.getTime() == now.getTime()) {
count++;
}
now.setTime(now.getTime() - millisInDay);
}
return count;
}
private static Date setMidnight(Date date) {
Calendar calendar = Calendar.getInstance();
calendar.setTime(date);
calendar.set(Calendar.MINUTE, 0);
calendar.set(Calendar.MILLISECOND, 0);
calendar.set(Calendar.HOUR, 0);
calendar.set(Calendar.SECOND, 0);
calendar.set(Calendar.HOUR_OF_DAY, 0);
return calendar.getTime();
}