如何使用java日期和时间创建日历事件?

时间:2018-03-11 10:32:11

标签: java date jodatime

我想用Java创建时间事件。

例如:3月1日之前 st 到3月31日 st 我想创建一些具有开始和结束日期的事件,如:

  • 事件1:3月3日至3月5日
  • 活动2:3月6日至3月10日
  • 活动2:3月13日至3月25日

等等。

这些事件不应重叠,且事件不应包含3月1日 st 和3月31日 st

我如何使用Java日期和时间或Joda-Time来做到这一点? 我有一个基本的想法,创建一个包含四个变量的类,如下所示:

monthStart
monthEnd
eventStart
eventEnd

1 个答案:

答案 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 )并创建你的事件间隔,然后使用上面的方法(enclosesoverlaps)相应地。

Plain Java

使用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有方法isBeforeisAfter来检查另一个日期是在日期之前还是之后,并且它还有equals方法来确定2个日期是相同的。知道2个事件是否重叠的逻辑也可以通过仅使用这些方法来实现,而“它留给读者的练习”: - )

如果您使用的是Java 7或更低版​​本,则可以使用threeten backport,其中也包含LocalDate类。

Threeten Extra

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 classesLocalDateInterval,您需要将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
}