本问题已经有最佳答案,请猛点这里访问。
我正在努力解决以下问题:
在我的应用程序中,我想检查来自LocalDateTime.now()的当前日期时间在一周中的某些特定日期范围内,比如说在星期五到星期日之间。
例子:
日期时间窗口是从星期五20:00到星期日20:00。当我在星期四22:00*检查当前日期时,答案应该是false,但当我在星期六8:00*检查时,答案应该是true。
我可以通过java.timeAPI中的DayOfWeek类,使用compareTo()方法,分别比较小时和分钟来实现这一点,但我想知道是否有更好的方法,特别是当两周的时间跨度超过两周时(例如,下周的星期五到星期一)?
提前感谢您提供任何建议或帮助。
@Spock我认为主题涵盖了两个日期范围的情况,并检查它们是否重叠。我的情况不同。我只有一个日期范围,想检查具体日期是否在该范围内。
@但它提供了许多实现目标所需的概念。
您要查找的是类似于span:sourceforge.net/p/tus/code/head/tree/tjacobs/util/span.java的内容(您可以删除implements PrimaryKey)。
只需使用isafter和isbefore,就可以确定日期是否在两个日期之前和/或之后
作为概念示例
问题是我在阈值中没有一个特定的日期时间,我只有一周中的一天和一天中的时间来使它成为每周通用的和可重复的。所以,如果我能找出那几天的日期,我想会容易得多。
那么?将它们组合成日期/值。问题是知道您是否要从当前日期向后或向前移动(即移动到上一个星期四和下一个星期日)
是的,听起来不错,但是我怎样才能知道下一个结束日和前一个开始日的日期呢?
由于您想将LocalDateTime与DayOfWeek与LocalTime进行比较,或者更确切地说,检查它是否在两个DayOfWeek与LocalTime对之间,辅助类可能很好:
public final class DayOfWeekTimeRange {
private final DayOfWeek fromDay;
private final LocalTime fromTime;
private final DayOfWeek toDay;
private final LocalTime toTime;
private final boolean inverted;
public DayOfWeekTimeRange(DayOfWeek fromDay, LocalTime fromTime, DayOfWeek toDay, LocalTime toTime) {
this.fromDay = fromDay;
this.fromTime = fromTime;
this.toDay = toDay;
this.toTime = toTime;
this.inverted = compare(this.fromDay, this.fromTime, this.toDay, this.toTime) > 0;
}
public boolean inRange(LocalDateTime dateTime) {
return inRange(dateTime.getDayOfWeek(), dateTime.toLocalTime());
}
public boolean inRange(DayOfWeek day, LocalTime time) {
boolean fromOk = compare(day, time, this.fromDay, this.fromTime) >= 0; // Lower-inclusive
boolean toOk = compare(day, time, this.toDay , this.toTime ) < 0; // Upper-exclusive
return (this.inverted ? fromOk || toOk : fromOk && toOk);
}
private static int compare(DayOfWeek day1, LocalTime time1, DayOfWeek day2, LocalTime time2) {
int cmp = day1.compareTo(day2);
if (cmp == 0)
cmp = time1.compareTo(time2);
return cmp;
}
}
试验
// Fri 10:00 PM to Sun 10:00 PM
DayOfWeekTimeRange range = new DayOfWeekTimeRange(DayOfWeek.FRIDAY, LocalTime.of(20,0), DayOfWeek.SUNDAY, LocalTime.of(20,0));
System.out.println(range.inRange(LocalDateTime.of(2015, 11, 12, 22, 0))); // Thu Nov. 12 2015 at 10:00 PM
System.out.println(range.inRange(LocalDateTime.of(2015, 11, 14, 8, 0))); // Sat Nov. 14 2015 at 8:00 AM
System.out.println(range.inRange(LocalDateTime.of(2015, 11, 16, 15, 0))); // Mon Nov. 16 2015 at 3:00 PM
// Fri 10:00 PM to Mon 10:00 PM
range = new DayOfWeekTimeRange(DayOfWeek.FRIDAY, LocalTime.of(20,0), DayOfWeek.MONDAY, LocalTime.of(20,0));
System.out.println(range.inRange(LocalDateTime.of(2015, 11, 12, 22, 0))); // Thu Nov. 12 2015 at 10:00 PM
System.out.println(range.inRange(LocalDateTime.of(2015, 11, 14, 8, 0))); // Sat Nov. 14 2015 at 8:00 AM
System.out.println(range.inRange(LocalDateTime.of(2015, 11, 16, 15, 0))); // Mon Nov. 16 2015 at 3:00 PM
产量2
替代方案
当然,如果你用DayOfWeek和LocalTime做了很多处理,你应该考虑实现你自己的LocalDayOfWeekTime类,把两者结合起来,就像LocalDateTime只是一个LocalDate和LocalTime的组合(这是你自己检查)。
谢谢!这就是我要找的!:)
@超人,你可以投赞成票也可以接受。
注意,这个答案使用半开放的方法,其中时间跨度的开始是包含的,而结束是排他的。这在日期时间工作中很常见。
只有当我们也假设间隔总是小于一周时,这个问题才得到很好的定义。
然后你可以工作1周;例如,如果你用毫秒表示所有的事情,你将工作模块n=1000*60*60*24*7。
现在计算a=checkdate-start(mod n)和b=end-start(mod n)并测试a
您需要为开始和结束选择一个真正的日期,在您的示例中是一个真正的星期五20:00和一个真正的星期六20:00。因为模运算,哪一个不重要。
还要记住,Java%操作符不同于负数的数学模型。所以一定要把它应用到正数上。
你的建议是对的,现在唯一要解决的就是找出那些日子的真实日期。有什么想法吗?我找不到。
例如,周五20:00将是2015年11月9日00:00之后的4天20小时。
我编写了一个测试程序,它需要两个日期时间(范围),然后测试一个日期时间,看它是否在该范围内。
我用了完整的日期,以便你可以跨越一个多星期,如果你想。
以下是测试结果:
Testing for the date range Fri, 13 Nov 2015 20:00 to Sun, 15 Nov 2015 20:00
12 Nov 2015 22:00: false
14 Nov 2015 08:00: true
16 Nov 2015 10:00: false
这是密码。我将日期时间作为字符串输入,以便于使用此代码,
package com.ggl.testing;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
public class DateRangeTesting {
private static final SimpleDateFormat inputDateFormat = new SimpleDateFormat(
"d MMM yyyy H:mm");
private static final SimpleDateFormat outputDateFormat = new SimpleDateFormat(
"EEE, d MMM yyyy H:mm");
private Calendar fromDate;
private Calendar toDate;
public static void main(String[] args) {
DateRangeTesting drTesting = new DateRangeTesting("13 Nov 2015 20:00",
"15 Nov 2015 20:00");
printResult("12 Nov 2015 22:00", drTesting);
printResult("14 Nov 2015 08:00", drTesting);
printResult("16 Nov 2015 10:00", drTesting);
}
private static void printResult(String s, DateRangeTesting drTesting) {
System.out.println(s +":" + drTesting.testDate(s));
}
public DateRangeTesting(String fromDateString, String toDateString) {
this.fromDate = convertInputDate(fromDateString);
this.toDate = convertInputDate(toDateString);
System.out.println(displayRange());
}
private String displayRange() {
StringBuilder builder = new StringBuilder();
builder.append("Testing for the date range");
builder.append(outputDateFormat.format(fromDate.getTime()));
builder.append(" to");
builder.append(outputDateFormat.format(toDate.getTime()));
return builder.toString();
}
public boolean testDate(String dateString) {
Calendar testDate = convertInputDate(dateString);
boolean fromTest = fromDate.compareTo(testDate) <= 0;
boolean toTest = testDate.compareTo(toDate) <= 0;
return fromTest && toTest;
}
private Calendar convertInputDate(String dateString) {
Calendar calendar = Calendar.getInstance();
try {
Date tempDate = inputDateFormat.parse(dateString);
calendar.setTime(tempDate);
} catch (ParseException e) {
e.printStackTrace();
}
return calendar;
}
}
谢谢,这是一个很好的解决办法,除了我不知道确切的日期范围,我只知道一天中的一天和一天中的一个时间,所以我必须不知何故找出那些非法侵入的日期和时间。
@超人:是的,那是另一个要创造的方法。方法签名是什么?例如getdate(calendar.sunday,0),其中0表示当前星期日,1表示下一个星期日,等等。我假设这是基于当前日期。
我明白你的意思。不管怎样,我更喜欢使用新的**Java 8的日期时间API
首先,你需要让你的函数取一个日期时间参数,如果你在里面使用"now()",你将无法测试它。
您的基本想法似乎不错,可以将一周中的某一天用作数组的索引,或者检查范围,如果范围通过了一周的开始/结束时间,则将其设为两个范围或将其反转。