此计算所需的测试用例是:
Today Marriage Days between
2000-01-01 ????-01-01 0
2000-01-01 ????-01-02 1
2000-01-01 ????-01-31 30
2000-01-01 ????-12-31 365 since 2000 is a leap year
2001-01-01 ????-12-31 364 since 2001 is not a leap year
2000-02-28 ????-03-01 2 since 2000 is a leap year
2000-12-31 ????-01-01 1
2000-12-01 ????-11-30 364 since 2001 is not a leap year
1999-12-01 ????-11-30 365 since 2000 is not a leap year
这些测试用例给出了做什么的提示。
- 取结婚日期
- 试试当年的那个日期
- 如果是过去,请选择明年的那个日期。
- 计算今天和那个日期之间的天数
第 4 步将处理闰年。
我建议写这个方法:
int daysUntilNextAnniversary(LocalDate today, LocalDate anniversary) {
...
}
anniversary这个词已经承载了周年纪念的年份无关紧要的信息,与上面的测试用例相符。
那么你就可以像这样轻松使用它了:
int days = daysUntilNextAnniversary(LocalDate.now(), marriage);
if (1 <= days && days <= 30) {
...
}
以下是上述测试用例的测试代码:
package de.roland_illig.so;
import static org.junit.Assert.assertEquals;
import java.time.LocalDate;
import org.junit.Test;
public class AnnivTest {
// Interesting test cases are:
//
// Marriage:
// - Jan 01 in leap year
// - Feb 29 in leap year
// - Dec 31 in leap year
// - Jan 01 in year after leap year
//
// Today:
// - Jan 01 in leap year
// - Feb 28 in leap year
// - Feb 28 in year before leap year
// - Feb 29 in leap year
// - Dec 31 in leap year
// - Dec 31 in year before leap year
//
// Ideally the test would test every combination of marriage and today.
@Test
public void daysUntilNextAnniversary() {
test("2000-01-01", "01-01", 0);
test("2000-01-01", "01-02", 1);
test("2000-01-01", "01-31", 30);
test("2000-01-01", "12-31", 365); // since 2000 is a leap year
test("2001-01-01", "12-31", 364); // since 2001 is not a leap year
test("2000-02-28", "03-01", 2); // since 2000 is a leap year
test("2000-12-31", "01-01", 1);
test("2000-12-01", "11-30", 364); // since 2001 is not a leap year
test("1999-12-01", "11-30", 365); // since 2000 is not a leap year
// Ensures that the marriage is not moved to Feb 28 just
// because the current year doesn't have Feb 29. This happens
// when an intermediate result is 2019-02-29, which is corrected
// to 2019-02-28.
test("2019-12-31", "02-29", 60);
// In a non-leap-year, Feb 28 and Feb 29 are merged into one day.
test("2019-02-28", "02-29", 0);
}
private void test(String today, String marriage, int expectedDays) {
int actual = Anniv.daysUntilNextAnniversary(
LocalDate.parse(today),
LocalDate.parse("1996-" + marriage));
assertEquals(expectedDays, actual);
}
}
这是计算的实际代码:
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));
}
}
如您所见,测试代码比实际应用程序代码长得多。在处理日期计算时,这是必要的。当不同的时区发挥作用时更是如此。和闰秒。以及其他日历异常。