我有六个int
个变量:currentMonth
,currentDay
,monthFrom
,dayFrom
,monthUntil
和dayUntil
。我需要检查今天的月份和日期是否在变量的范围内。
例如,如果currentMonth = 1
,currentDay = 2
,monthFrom = 11
,dayFrom =
24
,monthUntil = 3
和dayUntil = 3
日期在区间和方法中应该回归真实。
我不知道怎么做。除了使用ifs检查每个可能的结果之外还有其他选择吗?
答案 0 :(得分:5)
我建议使用java.time.MonthDay
来表示所涉及的每个值。然后,您需要考虑两种替代情况:
from
在until
之前或之前,在这种情况下,您需要对from <= current && current <= until
进行测试。from
晚于until
,在这种情况下,您需要执行current <= until || current >= from
所以:
public static boolean isBetween(
int currentMonth, int currentDay,
int fromMonth, int fromDay,
int untilMonth, int untilDay)
{
MonthDay current = MonthDay.of(currentMonth, currentDay);
MonthDay from = MonthDay.of(fromMonth, fromDay);
MonthDay until = MonthDay.of(untilMonth, untilDay);
if (from.compareTo(until) <= 0)
{
return from.compareTo(current) <= 0 &&
current.compareTo(until) <= 0;
}
else
{
return current.compareTo(until) <= 0 ||
current.compareTo(from) >= 0;
}
}
两个返回语句可以合并,但它可能更简单。
(这与Marvin的测试用例代码结果相同。)
答案 1 :(得分:3)
只需使用日历进行快速检查:
注意:请务必import java.util.GregorianCalendar;
public static boolean isDateInRange(int month, int day,
int monthFrom, int dayFrom,
int monthUntil, int dayUntil) {
int yearRoll = 0;
int currentRoll = 0;
if (monthUntil < monthFrom) yearRoll = -1; // Ensures date is calculated correctly.
if (month >= monthFrom && yearRoll < 0) currentRoll = -1;
GregorianCalendar testDate = new GregorianCalendar(currentRoll, month, day);
GregorianCalendar startDate = new GregorianCalendar(yearRoll, monthFrom, dayFrom);
GregorianCalendar endDate = new GregorianCalendar(0, monthUntil, dayUntil);
// This makes it pass if its between OR EQUAL to the interval.
// Remove if you only want to pass dates explicitly BETWEEN intervals.
if (testDate.compareTo(startDate) == 0 || testDate.compareTo(endDate) == 0) {
return true;
}
return !(testDate.before(startDate) || testDate.after(endDate));
}
这也将考虑到二月份是在十一月到三月之间的事实。由于11月是前一年的一部分,它将把from
日期推迟一年,以确保通过。
然而,它没有考虑到的事实是2月份在闰年上有额外的一天。为了增加额外的精度,你需要多年的整数。您可以执行以下操作:
public static boolean isDateInRange(int year, int month, int day,
int yearFrom, int monthFrom, int dayFrom,
int yearUntil, int monthUntil, int dayUntil) {
GregorianCalendar testDate = new GregorianCalendar(year, month, day);
GregorianCalendar startDate = new GregorianCalendar(yearFrom, monthFrom, dayFrom);
GregorianCalendar endDate = new GregorianCalendar(yearUntil, monthUntil, dayUntil);
return !(testDate.before(startDate) || testDate.after(endDate));
}
这是一个带有你给出的日期值的实现,再加上一些:
public static void main(String[] args) {
System.out.println(isDateInRange(1, 2,
11, 24,
3, 3));
System.out.println(isDateInRange(11, 25,
11, 24,
3, 3));
System.out.println(isDateInRange(1, 2,
1, 1,
3, 3));
System.out.println(isDateInRange(1, 22,
1, 21,
1, 25));
}
结果是:
true
true
true
true
也适用于@Marvin的测试。
答案 2 :(得分:2)
您可以从输入中创建LocalDate
个对象,让java进行检查。唯一的困难是确定所有这些日期应该落入哪些年份。
import java.time.LocalDate;
public class DateBetween {
public static void main(String[] args) {
System.out.println(isBetween(1, 2, 11, 24, 3, 3)); // true
System.out.println(isBetween(4, 4, 1, 20, 6, 3)); // true
System.out.println(isBetween(1, 1, 2, 3, 7, 8)); // false
System.out.println(isBetween(11, 4, 2, 3, 7, 8)); // false
System.out.println(isBetween(2, 29, 2, 3, 7, 8)); // true
System.out.println(isBetween(2, 29, 11, 24, 3, 3)); // true
System.out.println(isBetween(1, 1, 1, 1, 1, 1)); // true
}
private static boolean isBetween(int currentMonth, int currentDay, int monthFrom, int dayFrom, int monthUntil,
int dayUntil) {
// Default to 2000 so that Feb 29st will be valid.
int currentYear = 2000;
LocalDate dateFrom = LocalDate.of(currentYear, monthFrom, dayFrom);
LocalDate dateUntil = LocalDate.of(currentYear, monthUntil, dayUntil);
if (dateFrom.isAfter(dateUntil)) {
// Assume dateUntil is in the next year (e.g. for 11/24/2000 -
// 6/3/2001)
dateUntil = dateUntil.plusYears(1);
}
// Day to check in current year (for non-overlapping ranges)
LocalDate currentDateThisYear = LocalDate.of(currentYear, currentMonth, currentDay);
// Day to check in next year (for overlapping ranges)
LocalDate currentDateNextYear = currentDateThisYear.plusYears(1);
if (!(currentDateThisYear.isBefore(dateFrom) || currentDateThisYear.isAfter(dateUntil))) {
return true;
} else if (!(currentDateNextYear.isBefore(dateFrom) || currentDateNextYear.isAfter(dateUntil))) {
return true;
}
// Neither of the days to check are in the range
return false;
}
}
如果dateUntil
位于dateFrom
之后,该方法会将currentYear
视为明年。对于重叠范围,检查当前以及下一年的“当前”日期,例如,在“11月1日”(2017年)至“3月1日”(2018年)的范围内,您可能需要查看“12月24日”或“1月1日”。
如果您还可以提供yearFrom
,yearUntil
和 Category cat = db.Categories
.Include(c => c.Items.Select(s => s.Specifications))
.FirstOrDefault(c => c.Id == 1);
,这显然会变得更加轻松。
答案 3 :(得分:0)
这是黑客攻击。
当你没有多年的约会时,我不想同时使用GregorianCalendar
和LocalDate
,因为它们会迫使你挑选一年。特别是2月29日,这不仅仅是你能想到的任何一年。
首先,我想让你考虑一下,有没有办法可以解决你的日期问题,以及为什么你有约会int
的日期和日历类可供选择?如果将年份组件添加到您的日期没有意义,我仍然认为您可以始终将它们存储为MonthDay
而不是两个int
。在Android上,你必须权衡依赖于ThreeTenABP的成本,当然,在我看来,在这种情况下,我似乎是一个面向未来的成本:让我们希望有一个带有java.time
的Android版Java 8迟早。
与此同时,如果您不想使用MonthDay
,这里的解决方案根本没有任何库类。假装一个月内有32天,并计算每个日期的日期数。它作为日期编号没有意义,但它将具有我们想要的便利属性:日期编号与日历中的日期顺序相同。
public static boolean isBetween(int currentMonth, int currentDay,
int monthFrom, int dayFrom,
int monthUntil, int dayUntil) {
final int daysInMonth = 32; // just imagine; pick any number >= 31
int current = currentMonth * daysInMonth + currentDay;
int from = monthFrom * daysInMonth + dayFrom;
int until = monthUntil * daysInMonth + dayUntil;
if (until < from) { // until is in the following year
return current >= from || current <= until;
} else {
return current >= from && current <= until;
}
}
请根据您的具体要求调整<
和<=
等的使用。
缺点之一(除了棘手或默默无闻)之外,你根本就没有输入验证。我可以毫无意义地调用isBetween(55, -45, 83, 98, -29, 84)
,它将返回false或true,但没有任何迹象表明任何事情都不正确。
链接:在ThreeTenABP中获取适用于Android的java.time
课程。