java用数组表示日期_关于java:如何从今天的日期开始连续查看日期数组?

本问题已经有最佳答案,请猛点这里访问。

从用户每次完成任务开始,我就有一系列独特的日期。我想检查数组中的日期是否连续,包括今天的日期。

如果数组包含日期:"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();

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值