如何检查日期是否在java之间的间隔?

时间:2017-04-14 10:38:56

标签: java date

我有六个int个变量:currentMonthcurrentDaymonthFromdayFrommonthUntildayUntil。我需要检查今天的月份和日期是否在变量的范围内。

例如,如果currentMonth = 1currentDay = 2monthFrom = 11dayFrom = 24monthUntil = 3dayUntil = 3日期在区间和方法中应该回归真实。

我不知道怎么做。除了使用ifs检查每个可能的结果之外还有其他选择吗?

4 个答案:

答案 0 :(得分:5)

我建议使用java.time.MonthDay来表示所涉及的每个值。然后,您需要考虑两种替代情况:

  • fromuntil之前或之前,在这种情况下,您需要对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日”。

如果您还可以提供yearFromyearUntil Category cat = db.Categories .Include(c => c.Items.Select(s => s.Specifications)) .FirstOrDefault(c => c.Id == 1); ,这显然会变得更加轻松。

答案 3 :(得分:0)

这是黑客攻击。

当你没有多年的约会时,我不想同时使用GregorianCalendarLocalDate,因为它们会迫使你挑选一年。特别是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课程。