Java 计算一年中两个日期之间的天数
我有“LocalDate”类型的结婚日期列表,我想找到结婚纪念日在未来30天内的人的列表。所有的结婚日期都是在过去的几年里,比如1980年,1990年,2000年 我曾尝试使用ChronoUnit.DAYS.between()函数,但如果日期是今天和未来的日期,它只显示天数Java 计算一年中两个日期之间的天数,java,java-8,Java,Java 8,我有“LocalDate”类型的结婚日期列表,我想找到结婚纪念日在未来30天内的人的列表。所有的结婚日期都是在过去的几年里,比如1980年,1990年,2000年 我曾尝试使用ChronoUnit.DAYS.between()函数,但如果日期是今天和未来的日期,它只显示天数 String str = "2019-04-24"; DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd"); LocalDate da
String str = "2019-04-24";
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
LocalDate date = LocalDate.parse(str, formatter);
LocalDate today = LocalDate.now();
long dd = ChronoUnit.DAYS.between(today, date);
我期待的答案是,如果结婚日期是1990-04-29,那么它应该告诉我这个日期是否在接下来的30天内。也就是说,如果上述日期的周年纪念日在接下来的30天内,或者不在30天内。尝试计算今年的周年纪念日,并找出现在和该日期之间的差异:
String str=“2008-05-20”;
DateTimeFormatter formatter=模式的DateTimeFormatter.of(“yyyy-MM-dd”);
LocalDate=LocalDate.parse(str,格式化程序);
LocalDate today=LocalDate.now();
long dd=ChronoUnit.DAYS.between(今天,日期);
System.err.println(“您的答案是”+dd);
LocalDate ThisYearsannVersary=LocalDate.of(today.getYear(),date.getMonth(),date.getDayOfMonth());
System.err.println(“本周年纪念日为”+本周年纪念日);
dd=时间单位。天数。介于(今天、今年和周日)之间;
System.err.println(“以“+dd+”天为单位”);
输出
YOUR ANSWER WAS -3981
THIS YEARS ANNIVERSARY IS 2019-05-24
WHICH IS IN 36 days
因为你根本不在乎年份:
private static boolean isWithinNext30Days(LocalDate date, LocalDate today) {
int todayYear = today.getYear();
int todayMonth = today.getMonthValue();
int dateMonth = date.getMonthValue();
if (todayMonth > dateMonth) {
date = date.withYear(todayYear + 1);
return today.plusDays(30).isAfter(date) && date.isAfter(today);
}
LocalDate alteredDate = date.withYear(todayYear);
return today.plusDays(30).isAfter(alteredDate) && alteredDate.isAfter(today);
}
此计算所需的测试用例为:
今天是结婚的日子
2000-01-01 ????-01-01 0
2000-01-01 ????-01-02 1
2000-01-01 ????-01-31 30
2000年01月01日12月31日365因为2000年是闰年
因为2001年不是闰年
因为2000年是闰年
2000-12-31 ????-01-01 1
2000年12月01日11月30日364因为2001年不是闰年
1999年12月01日11月30日365因为2000年不是闰年
这些测试用例给出了如何做的提示
int daysUntilNextAnniversary(LocalDate today, LocalDate anniversary) {
...
}
“周年纪念”一词已经包含了与周年纪念无关的信息,这与上面的测试用例相匹配
然后您可以像这样轻松地使用它:
int days = daysUntilNextAnniversary(LocalDate.now(), marriage);
if (1 <= days && days <= 30) {
...
}
下面是计算的实际代码:
package de.roland_illig.so;
import java.time.LocalDate;
import java.time.temporal.ChronoUnit;
public class Anniv {
public static int daysUntilNextAnniversary(LocalDate today, LocalDate anniversary) {
LocalDate d = anniversary.withYear(today.getYear());
if (d.isBefore(today)) {
d = anniversary.withYear(today.getYear() + 1);
}
return Math.toIntExact(ChronoUnit.DAYS.between(today, d));
}
}
如您所见,测试代码比实际应用程序代码长得多。在处理日期计算时,这是必要的。当不同的时区发挥作用时,情况就更糟了。和闰秒。所以,“基本”的概念是,你想把你的日期列表改成与今年相匹配的年份。“捕获”是,如果结果日期在今天之前,则应将年份增加一,这样,如果现在是12月,则将捕获1月发生的所有周年纪念
也许像
LocalDate now = LocalDate.now();
int year = now.getYear();
List<LocalDate> dates = ...;
List<LocalDate> adjusted = new ArrayList<>(10);
for (LocalDate date : dates) {
LocalDate warped = date.withYear(year);
if (warped.isBefore(now)) {
warped = warped.withYear(year + 1);
}
adjusted.add(warped);
}
Input date 2019-04-19
+---------------+---------------+--------------+
| Original Date | Adjusted Date | Within range |
+---------------+---------------+--------------+
| 1996-04-13 | 2020-04-13 | |
| 1986-04-24 | 2019-04-24 | X |
| 1989-04-23 | 2019-04-23 | X |
| 1960-05-11 | 2019-05-11 | X |
| 1986-05-18 | 2019-05-18 | X |
| 1984-04-06 | 2020-04-06 | |
| 1997-05-29 | 2019-05-29 | |
| 2008-03-31 | 2020-03-31 | |
| 2014-04-18 | 2020-04-18 | |
| 1982-04-23 | 2019-04-23 | X |
+---------------+---------------+--------------+
+---------------+---------------+--------------+
| Original Date | Adjusted Date | Within range |
+---------------+---------------+--------------+
| 2001-12-16 | 2020-12-16 | |
| 2005-12-28 | 2019-12-28 | X |
| 1988-12-31 | 2019-12-31 | X |
| 1989-11-13 | 2020-11-13 | |
| 1976-11-13 | 2020-11-13 | |
| 1991-01-09 | 2020-01-09 | X |
| 1963-11-04 | 2020-11-04 | |
| 2001-11-02 | 2020-11-02 | |
| 1980-01-11 | 2020-01-11 | X |
| 1979-11-17 | 2020-11-17 | |
+---------------+---------------+--------------+
所以,使用相同的伪随机生成的日期,我可以得到一个类似于
LocalDate now = LocalDate.now();
int year = now.getYear();
List<LocalDate> dates = ...;
List<LocalDate> adjusted = new ArrayList<>(10);
for (LocalDate date : dates) {
LocalDate warped = date.withYear(year);
if (warped.isBefore(now)) {
warped = warped.withYear(year + 1);
}
adjusted.add(warped);
}
Input date 2019-04-19
+---------------+---------------+--------------+
| Original Date | Adjusted Date | Within range |
+---------------+---------------+--------------+
| 1996-04-13 | 2020-04-13 | |
| 1986-04-24 | 2019-04-24 | X |
| 1989-04-23 | 2019-04-23 | X |
| 1960-05-11 | 2019-05-11 | X |
| 1986-05-18 | 2019-05-18 | X |
| 1984-04-06 | 2020-04-06 | |
| 1997-05-29 | 2019-05-29 | |
| 2008-03-31 | 2020-03-31 | |
| 2014-04-18 | 2020-04-18 | |
| 1982-04-23 | 2019-04-23 | X |
+---------------+---------------+--------------+
+---------------+---------------+--------------+
| Original Date | Adjusted Date | Within range |
+---------------+---------------+--------------+
| 2001-12-16 | 2020-12-16 | |
| 2005-12-28 | 2019-12-28 | X |
| 1988-12-31 | 2019-12-31 | X |
| 1989-11-13 | 2020-11-13 | |
| 1976-11-13 | 2020-11-13 | |
| 1991-01-09 | 2020-01-09 | X |
| 1963-11-04 | 2020-11-04 | |
| 2001-11-02 | 2020-11-02 | |
| 1980-01-11 | 2020-01-11 | X |
| 1979-11-17 | 2020-11-17 | |
+---------------+---------------+--------------+
如果我们将锚定日期更改为类似于2019-12-20的日期,它可能会生成类似于
LocalDate now = LocalDate.now();
int year = now.getYear();
List<LocalDate> dates = ...;
List<LocalDate> adjusted = new ArrayList<>(10);
for (LocalDate date : dates) {
LocalDate warped = date.withYear(year);
if (warped.isBefore(now)) {
warped = warped.withYear(year + 1);
}
adjusted.add(warped);
}
Input date 2019-04-19
+---------------+---------------+--------------+
| Original Date | Adjusted Date | Within range |
+---------------+---------------+--------------+
| 1996-04-13 | 2020-04-13 | |
| 1986-04-24 | 2019-04-24 | X |
| 1989-04-23 | 2019-04-23 | X |
| 1960-05-11 | 2019-05-11 | X |
| 1986-05-18 | 2019-05-18 | X |
| 1984-04-06 | 2020-04-06 | |
| 1997-05-29 | 2019-05-29 | |
| 2008-03-31 | 2020-03-31 | |
| 2014-04-18 | 2020-04-18 | |
| 1982-04-23 | 2019-04-23 | X |
+---------------+---------------+--------------+
+---------------+---------------+--------------+
| Original Date | Adjusted Date | Within range |
+---------------+---------------+--------------+
| 2001-12-16 | 2020-12-16 | |
| 2005-12-28 | 2019-12-28 | X |
| 1988-12-31 | 2019-12-31 | X |
| 1989-11-13 | 2020-11-13 | |
| 1976-11-13 | 2020-11-13 | |
| 1991-01-09 | 2020-01-09 | X |
| 1963-11-04 | 2020-11-04 | |
| 2001-11-02 | 2020-11-02 | |
| 1980-01-11 | 2020-01-11 | X |
| 1979-11-17 | 2020-11-17 | |
+---------------+---------------+--------------+
所以它捕捉的是明年登陆的日期
注意:我随机生成的测试日期在锚定日期的+/-一个月内,以便获得更好的测试数据。我认为您需要将其设置为当前年份,以正确计算结束日期。我认为你根本不需要一年来比较开始日期。@shmosel有什么区别?这只是两边的一个常数。闰日可能会影响30天的计算。所以,你想取“原始”日期,将年份改为今年,并检查日期是否在30天之内?@MadProgrammer不,这不是那么简单。计算也应该在12月生效。@RolandIllig这是真的,但我正试图确定另一个例子的基本要求,婚礼是2009-01-14,今天是2019-12-30。预期输出为15天(因此在30天内)。在你的代码片段中,今年的周年纪念日将是2019-01-14,再过-350天。@allanshivji你应该在12月再次问同样的问题,看看它是否仍然适用于你。是的,这是非常相似的代码。我专注于不在代码中重复我自己。由于神奇的数字30,我担心我可能会在代码中犯一些错误,因为只有30作为测试用例会使选择好的测试用例更加困难。我还希望避免将日期拆分为
(年、月)
元组,因为它们可能与其他日期混淆。变量更少通常意味着代码更容易理解。哦,我想更多地关注通过良好的测试用例开发可靠代码的过程。