You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用Java Date and Time或Joda-Time创建不重叠日历事件

嘿,这个需求我之前做类似功能时刚好研究过,用Java 8引入的java.time日期时间API就能完美搞定——毕竟现在Joda-Time已经进入维护状态了,官方更推荐用原生的java.time。下面我一步步给你讲怎么实现:

第一步:定义符合要求的Event类

你提到想创建包含四个变量的类,其实不用自己拆分年月日,直接用java.time.LocalDate来封装开始和结束日期更简洁,还能避免手动处理日期逻辑的bug。我们可以给类加校验逻辑,确保事件本身符合规则:

import java.time.LocalDate;

// Java 16+用record更简洁,也可以用普通class
public record Event(String name, LocalDate start, LocalDate end) {
    // 自定义构造器做参数校验
    public Event {
        // 确保开始时间早于结束时间
        if (start.isAfter(end) || start.isEqual(end)) {
            throw new IllegalArgumentException("事件开始时间必须早于结束时间");
        }
        // 确保事件在3月1日(不含)到3月31日(不含)之间
        LocalDate marchStart = LocalDate.of(start.getYear(), 3, 1);
        LocalDate marchEnd = LocalDate.of(start.getYear(), 3, 31);
        if (start.isBefore(marchStart) || end.isAfter(marchEnd)) {
            throw new IllegalArgumentException("事件必须落在3月1日至3月31日之间(不含首尾)");
        }
        if (start.isEqual(marchStart) || end.isEqual(marchEnd)) {
            throw new IllegalArgumentException("事件不能包含3月1日或3月31日");
        }
    }
}
第二步:实现事件管理与重叠校验

接下来需要一个管理类来添加事件,同时校验新事件和已有事件是否重叠。判断两个事件是否重叠的逻辑很简单:如果新事件的开始时间晚于已有事件的结束时间,或者新事件的结束时间早于已有事件的开始时间,就不重叠,反之则重叠。

import java.time.LocalDate;
import java.util.ArrayList;
import java.util.List;

public class EventManager {
    private final List<Event> events = new ArrayList<>();
    private final LocalDate marchStart;
    private final LocalDate marchEnd;

    // 指定年份,针对该年的3月创建事件
    public EventManager(int year) {
        this.marchStart = LocalDate.of(year, 3, 1);
        this.marchEnd = LocalDate.of(year, 3, 31);
    }

    // 添加事件,返回是否添加成功
    public boolean addEvent(Event event) {
        // 二次校验(可选,因为Event构造器已经做了基础校验)
        if (event.start().isBefore(marchStart) || event.end().isAfter(marchEnd)
                || event.start().isEqual(marchStart) || event.end().isEqual(marchEnd)) {
            System.out.println("错误:事件不在允许的时间范围内");
            return false;
        }
        // 检查是否与已有事件重叠
        for (Event existingEvent : events) {
            if (isOverlapping(event, existingEvent)) {
                System.out.println("错误:事件与「" + existingEvent.name() + "」重叠");
                return false;
            }
        }
        events.add(event);
        return true;
    }

    // 判断两个事件是否重叠的工具方法
    private boolean isOverlapping(Event newEvent, Event existingEvent) {
        return !(newEvent.start().isAfter(existingEvent.end()) || newEvent.end().isBefore(existingEvent.start()));
    }

    // 打印所有已添加的事件
    public void printAllEvents() {
        events.forEach(event -> 
            System.out.println(event.name() + ":" + event.start() + " 至 " + event.end())
        );
    }
}
第三步:测试使用

写个主类来验证功能,看看合法事件、重叠事件、违规事件的处理效果:

public class Main {
    public static void main(String[] args) {
        EventManager manager = new EventManager(2024);

        // 添加合法事件,会成功
        manager.addEvent(new Event("Event1", LocalDate.of(2024, 3, 3), LocalDate.of(2024, 3, 5)));
        manager.addEvent(new Event("Event2", LocalDate.of(2024, 3, 6), LocalDate.of(2024, 3, 10)));
        manager.addEvent(new Event("Event3", LocalDate.of(2024, 3, 13), LocalDate.of(2024, 3, 25)));

        // 尝试添加重叠事件,会失败
        manager.addEvent(new Event("Event4", LocalDate.of(2024, 3, 9), LocalDate.of(2024, 3, 12)));

        // 尝试添加包含3月1日的事件,会失败
        manager.addEvent(new Event("Event5", LocalDate.of(2024, 3, 1), LocalDate.of(2024, 3, 2)));

        // 打印最终合法的事件列表
        manager.printAllEvents();
    }
}
关于Joda-Time的实现思路

如果因为项目限制必须用Joda-Time,思路和上面完全一致,只是把java.time.LocalDate换成org.joda.time.LocalDate,核心的isBefore()、isAfter()、isEqual()方法用法几乎一样,事件类和管理类的逻辑可以直接照搬,只是导入的包不同。

额外小提示
  • 如果需要按时间顺序展示事件,可以在添加后对events列表排序:Collections.sort(events, Comparator.comparing(Event::start))
  • 要是需要支持跨年份的3月事件,只需要调整EventManager的初始化逻辑,不用固定年份即可

内容的提问来源于stack exchange,提问作者user8203210

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.20 09:00:48