我想用Java创建时间事件。
例如:3月1日之前 st 到3月31日 st 我想创建一些具有开始和结束日期的事件,如:
等等。
这些事件不应重叠,且事件不应包含3月1日 st 和3月31日 st 。
我如何使用Java日期和时间或Joda-Time来做到这一点? 我有一个基本的想法,创建一个包含四个变量的类,如下所示:
monthStart
monthEnd
eventStart
eventEnd
答案 0 :(得分:1)
另一种方法是使用Time4J API,并使用DateInterval
创建PlainDate
作为开始日期和结束日期:
// March 1st and 31st
PlainDate start = PlainDate.of(2018, 3, 1);
PlainDate end = PlainDate.of(2018, 3, 31);
DateInterval interval = DateInterval.between(start, end);
通过此操作,您可以检查事件是否在此间隔内:
// Event1: March 3 to March 5
PlainDate eventStart = PlainDate.of(2018, 3, 3);
PlainDate eventEnd = PlainDate.of(2018, 3, 5);
DateInterval event1 = DateInterval.between(eventStart, eventEnd);
if (interval.encloses(event1)) {
// event1 is inside interval
}
您还可以检查2个事件是否重叠:
// Event2: March 3 to March 5
eventStart = PlainDate.of(2018, 3, 6);
eventEnd = PlainDate.of(2018, 3, 10);
DateInterval event2 = DateInterval.between(eventStart, eventEnd);
if (event1.overlaps(event2)) {
// events 1 and 2 overlap
}
你的算法将是:创建完整的间隔(例如从3月1日 st 到3月31日 st )并创建你的事件间隔,然后使用上面的方法(encloses
和overlaps
)相应地。
使用Java的API,假设你有Java 8,它就是类似的。唯一的区别是Java没有Interval
类,您必须手动比较日期:
// March 1st and 31st
LocalDate start = LocalDate.of(2018, 3, 1);
LocalDate end = LocalDate.of(2018, 3, 31);
// Event1: March 3 to March 5
LocalDate eventStart = LocalDate.of(2018, 3, 3);
LocalDate eventEnd = LocalDate.of(2018, 3, 5);
// check if event1 is inside start and end dates
if (start.isBefore(eventStart) && eventEnd.isBefore(end)) {
// event is inside March 1st and 31st
}
LocalDate
有方法isBefore
和isAfter
来检查另一个日期是在日期之前还是之后,并且它还有equals
方法来确定2个日期是相同的。知道2个事件是否重叠的逻辑也可以通过仅使用这些方法来实现,而“它留给读者的练习”: - )
如果您使用的是Java 7或更低版本,则可以使用threeten backport,其中也包含LocalDate
类。
在this API中,有一个Interval
class,但它仅适用于Instant
,而不适用于LocalDate
。
您可以对此进行一些解决方法并假设您的日期是UTC,然后使用Interval
。我创建了一个辅助方法来进行这种转换:
public Instant toInstant(LocalDate date) {
// convert to midnight in UTC
return date.atStartOfDay(ZoneOffset.UTC).toInstant();
}
然后使用它来创建间隔:
// March 1st and 31st
Instant start = toInstant(LocalDate.of(2018, 3, 1));
Instant end = toInstant(LocalDate.of(2018, 3, 31));
Interval interval = Interval.of(start, end);
// Event1: March 3 to March 5
Instant eventStart = toInstant(LocalDate.of(2018, 3, 3));
Instant eventEnd = toInstant(LocalDate.of(2018, 3, 5));
Interval event1 = Interval.of(eventStart, eventEnd);
if (interval.encloses(event1)) {
// event1 is inside interval
}
// Event2: March 3 to March 5
eventStart = toInstant(LocalDate.of(2018, 3, 6));
eventEnd = toInstant(LocalDate.of(2018, 3, 10));
Interval event2 = Interval.of(eventStart, eventEnd);
if (event1.overlaps(event2)) {
// events 1 and 2 overlap
}
这是一种解决方法,因为它人为地将日期设置为UTC午夜。但是,由于我们只关心日,月和年,这应该可以解决问题(或者您也可以下载额外的三个代码并创建另一个与Interval
一起使用的LocalDate
类,并以此为基础原始代码。)
Joda-Time已停产,该团队建议迁移到java.time
API。签入Joda-Time's website,那里有一个警告说:
请注意,Joda-Time被认为是一个很大程度上“完成”的项目。没有计划重大改进。如果使用Java SE 8,请迁移到java.time(JSR-310)
如果您使用Java 6或7,我建议使用三个backport。对于Java> = 8,使用带有三个额外或time4j的java.time
。只有你仍然使用Java 5,那么最好的选择是使用Joda-Time(实际上,理想的是升级到更新的Java版本,但无论如何)。
在Joda-Time,there are similar classes:LocalDate
和Interval
,您需要将LocalDate
转换为DateTime
(假设UTC中的午夜)为了处理间隔(类似于我们上面转换为Instant
):
DateTime start = new LocalDate(2018, 3, 1).toDateTimeAtStartOfDay(DateTimeZone.UTC);
DateTime end = new LocalDate(2018, 3, 31).toDateTimeAtStartOfDay(DateTimeZone.UTC);
Interval interval = new Interval(start, end);
DateTime eventStart = new LocalDate(2018, 3, 3).toDateTimeAtStartOfDay(DateTimeZone.UTC);
DateTime eventEnd = new LocalDate(2018, 3, 5).toDateTimeAtStartOfDay(DateTimeZone.UTC);
Interval event1 = new Interval(eventStart, eventEnd);
// contains accepts the same start or end dates, it needs additional checks to make sure dates are different
if (interval.contains(event1)
&& event1.getStart().isAfter(interval.getStart())
&& event1.getEnd().isBefore(interval.getEnd())) {
// interval contains event1, and start and end dates are not the same
}
eventStart = new LocalDate(2018, 3, 6).toDateTimeAtStartOfDay(DateTimeZone.UTC);
eventEnd = new LocalDate(2018, 3, 10).toDateTimeAtStartOfDay(DateTimeZone.UTC);
Interval event2 = new Interval(eventStart, eventEnd);
if (event1.overlaps(event2)) {
// events 1 and 2 overlap
}