Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/powershell/12.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 从日期列表中获取下一个生日_Java_Android_Date - Fatal编程技术网

Java 从日期列表中获取下一个生日

Java 从日期列表中获取下一个生日,java,android,date,Java,Android,Date,我对日期计算有问题。 这里是我的处境;我有一张生日的清单,如下所示: List<Date> birthdays = getAllBirthdays(); //getAllBirthdays() returns full list of dates List birthdays=getAllBirthdays()//getAllBirthdays()返回日期的完整列表 现在来计算下三个生日。我读了很多关于日期的书,并且在我的项目中实现了joda time,所以我也尝试使用DateT

我对日期计算有问题。 这里是我的处境;我有一张生日的清单,如下所示:

List<Date> birthdays = getAllBirthdays(); //getAllBirthdays() returns full list of dates
List birthdays=getAllBirthdays()//getAllBirthdays()返回日期的完整列表

现在来计算下三个生日。我读了很多关于日期的书,并且在我的项目中实现了joda time,所以我也尝试使用DateTime对象进行计算,但没有找到一个好的解决方案,这很有效。有人能帮我做一个基本结构或其他吗?

有几种方法可以解决这个问题。一种方法是为自己创建一个出生月份和年份的排序索引,这样您就可以快速找到给定日期的以下生日

你需要意识到的第一件事是“下一个”生日不应该考虑年份。如果你只是对日期进行排序或比较,那么这一年将给你无效的日期。有一种方法可以绕过这个问题,为生日创建一个键,该键唯一地标识生日,而不考虑年份。更具体地说,您需要一个可以按“时间顺序”排序的键。例如:

localdated1=LocalDate.parse(“1980-10-31”);
int key1=d1.getMonthValue()*100+d1.getDayOfMonth();
localdated2=LocalDate.parse(“2001-10-31”);
int key2=d2.getMonthValue()*100+d2.getDayOfMonth();
key1==key2
现在您已经有了一种生成密钥的方法,您将需要生成一个到生日的密钥映射。通过使用groupingBy收集器,您可以很容易地做到这一点

函数键=(d)->d.getMonthValue()*100+d.getDayOfMonth();
Map lookup=birthdays.stream().collect(Collectors.groupingBy(key));
请注意,我们收集的生日与列表中的生日相同,因为可能在同一天、同一年或不同年有多个生日

最后,你会想办法找到下三个生日。一种方法是对键进行排序,搜索下一个条目的位置,然后读取以下两个条目。因为这是一个可排序的键列表,所以我们可以创建键的索引,对其进行排序,并使用二进制搜索来查找下一个条目。因此,让我们创建索引:

List searchIndex=lookup.keySet().stream().sorted().collect(Collectors.toList());
因此,现在我们可以使用
searchIndex
查找与输入日期的键最近的键。然后,我们可以使用该键从
查找中查找该键的生日列表

通过查看索引中的下两个键,我们可以得到以下两个日期。但是请注意,当到达索引末尾时,您将希望换行到索引的开头。例如,如果您在12月31日搜索接下来的三个生日,您将希望它在1月份继续检查

List birthdays=getAllBirthdays();
函数键=(d)->d.getMonthValue()*100+d.getDayOfMonth();
Map lookup=birthdays.stream().collect(Collectors.groupingBy(key));
List searchIndex=lookup.keySet().stream().sorted().collect(Collectors.toList());
int index=Collections.binarySearch(searchIndex,key.apply(LocalDate.now());
//如果索引不包含当前MMdd,请查找正索引
如果(指数<0){
指数=-指数-1;
}
对于(int i=0;i<3;++i){
//绕到今年年初
如果(索引>=searchIndex.size()){
指数=0;
}
System.out.println(lookup.get(searchIndex.get(index++));
}

我在上面的代码中使用了
java.util.LocalDate
,但是您也可以轻松地使用
joda的LocalDate
。这两种方法都比使用java.util.Date更可取,因为您的问题根本不清楚。但我要试试看

java.time Joda Time项目现在处于维护模式。它的创建者和领导者Stephen Colebourne继续领导JSR 310的工作,并将其java.time实现内置到java 8和更高版本中

MonthDay
听起来你的年度生日清单应该包含
MonthDay
类的物品。这个类表示一个月和一个月中的一天,没有年份和时区

List< MonthDay > birthdays = new ArrayList<>() ;
birthdays.add( MonthDay.of( Month.MARCH , 27 ) ) ;
birthdays.add( MonthDay.of( Month.DECEMBER , 13 ) ) ;
循环列表。将每个
MonthDay
与我们当前的月日
md
进行比较

if( md.isAfter( mdCurrent ) ) {
    …
}
如果在后面,则应用数字生成
LocalDate

if( md.isAfter( mdCurrent ) ) {
    int y = Year.now( z ).getValue() ;
    LocalDate ld = md.atYear( y ) ;
}

定义一个自定义的比较器,根据到生日的时间来比较日期,考虑到日期可能是今年或明年。使用比较器进行排序。以排序列表的前三个元素为例。快乐编码。(我不是在为您编写代码,希望您从未期望我们这样做。)

还要查看是否可以将
LocalDate
MonthDay
对象填充到列表中,而不是
Date
对象。A
Date
尽管类名不代表日期,但该类的设计很差,而且很早就过时了
LocalDate
MonthDay
是来自java.time的类,它是现代java日期和时间API,比像
date
这样的旧类更易于使用

if( md.isAfter( mdCurrent ) ) {
    int y = Year.now( z ).getValue() ;
    LocalDate ld = md.atYear( y ) ;
}
问题:我可以在Android上使用java.time吗? 是的,java.time在较旧和较新的Android设备上运行良好。它至少需要Java6

  • 在Java8和更高版本以及更新的Android设备上(API级别26),现代API是内置的
  • 在Java6和Java7中,获取三个后端口,即现代类的后端口(三个十用于JSR310;参见底部的链接)
  • 在(较旧的)Android上使用Android版本的ThreeTen Backport。它叫ThreeTenABP。并确保从带有子包的
    org.threeten.bp
    导入日期和时间类
链接
  • 解释如何使用java.time