Java:如何从时间x到y(间隔)存储时间线/时间表,位置满或空?

Cha*_*ava 6 java time object intervals

一些简短的背景:

我有一个java应用程序,用于查看某些位置(教室)何时使用.用户将位置标识符放入搜索框,程序显示匹配的任何事件(类).该应用程序将显示所有相关信息(班级名称,房间号,教授姓名,星期几,课程时间),会话中(或即将成为)的课程采用颜色编码,以便您可以告诉-a - 如果有任何事情发生的话.数据来自我正在抓取的html页面(我没有SQL访问权限).

到目前为止,一切都有效,我正在使用JavaSwing进行UI.事件存储为我保存它的基本对象,对我的问题唯一重要的部分是它存储到Java Date对象的每个事件的开始和结束时间.

我现在要做的是添加一种方法来检查并显示事件之间的差距(当教室为空时).我拥有我需要的所有数据(所有开始和结束时间),但是我无法想出一种方法来实际编写程序来查看差距.

如果这还不够具备挑战性:我想尽可能简单地实现它,而不是使用任何额外的库.我不想重新创建轮子,但是我宁愿手动散列代码,而不仅仅是输入一个导入和几个方法调用; 这个项目的一半要点是挑战自己.

目前我并不是在寻找有关如何实际显示数据的建议,因为现在我只是尝试以可用的方式对其进行逻辑组织.它最终将显示在JTable中,但我还没有开始实现该实现.


我刮刀从HTML表像拉<td id=time>10:00AM - 11:15AM</td>并解析出两个字符串10:00AM11:15AM.这些与其他数据一起传递给我的Course对象.

我的Course对象有一个DateFormat设置,因此它可以将传入的字符串解释为日期.

public class Course {

static DateFormat tf = new SimpleDateFormat("h:mma");
private String name;
private String room;
private String instructor;
private Date start;
private Date end;
private String days;

public Course(String n, String r, String in, String st, String ed, String d) throws ParseException{
    name=n;
    room=r;
    instructor=in;
    start=tf.parse(st);
    end=tf.parse(ed);
    days=d;
}

//...basic getters, setters, and a toString()
Run Code Online (Sandbox Code Playgroud)

我的想法是,我会设置两次,设置我要检查间隙的窗口.我想选择一个间隔,比如说15分钟,并找到15分钟或更长时间内教室空置的所有间隙,即没有课程会议.

Bas*_*que 2

我没有完整的答案,但我有一些建议。

\n\n

时区

\n\n

ADate表示 UTC/GMT 格式的日期时间,即没有时区偏移。您的值位于时区。从长远来看,不要忽略该时区,您的情况会更好。调整你的价值观。通常以 UTC/GMT 来思考、工作和存储日期时间。根据需要转换为本地时间以便在用户界面中显示。

\n\n

虽然 java.util.Date 没有时区,但 Joda-Time DateTime(下面讨论)确实知道它自己的时区和时区偏移量。

\n\n

避免 java.util.Date/Calendar

\n\n

与 Java 捆绑在一起的 java.util.Date 和 Calendar 类是出了名的麻烦。避开他们。

\n\n

相反,请使用:

\n\n\n\n

不要将 Joda-Time 视为任何旧的“额外图书馆”。在 IDE 中创建新项目时,我做的第一件事是添加 Joda-Time 库。就是这么好。或者 juDate/Calendar 就那么糟糕,这取决于您的观点。

\n\n

开始包含,结束独家

\n\n

处理时间跨度的最佳方法是使开始具有包容性,使结束具有排他性。编写逻辑,检查开头是否大于或等于以及结尾是否小于(不测试结尾是否等于)。我在另一个答案中结合图表对此进行了更多讨论。

\n\n

乔达时间

\n\n

Joda-Time 提供了这些用于定义时间跨度的类:Period、Duration 和 Internal。Hours 和类似的类提供了一些方便的实用方法。

\n\n

寻找差距

\n\n

如果您的目标是列出一个空白列表,列出教室未分配给班级的时间跨度,那么在我看来,最明显的方法就是按时间顺序(并按教室)对班级进行排序,如 Rob 的回答所示怀特塞德。定义一个“可用”时间跨度,其开头是前一个 class\xe2\x80\x99 结尾,结尾是下一个 class\xe2\x80\x99 开头。我在这方面没有经验,所以可能有更聪明的方法。

\n\n

请参阅有关对间隔列表进行排序的问题。

\n\n

示例代码

\n\n

下面是一些使用 Joda-Time 2.3 的示例代码。

\n\n

指定时区而不是依赖默认\xe2\x80\xa6

\n\n
DateTimeZone timeZone = DateTimeZone.forID( "Europe/Paris" );\n
Run Code Online (Sandbox Code Playgroud)\n\n

创建三个类作为样本数据,顺序任意\xe2\x80\xa6

\n\n
Interval class_math = new Interval( new DateTime( 2014, 1, 24, 10, 0, 0, timeZone ), new DateTime( 2014, 1, 24, 11, 15, 0, timeZone ) );\nInterval class_chemistry = new Interval( new DateTime( 2014, 1, 24, 8, 0, 0, timeZone ), new DateTime( 2014, 1, 24, 9, 15, 0, timeZone ) );\nInterval class_french_lit = new Interval( new DateTime( 2014, 1, 24, 13, 0, 0, timeZone ), new DateTime( 2014, 1, 24, 14, 15, 0, timeZone ) );\n
Run Code Online (Sandbox Code Playgroud)\n\n

将样本数据收集到List\xe2\x80\xa6中

\n\n
java.util.List<Interval> classes = new java.util.ArrayList<Interval>( 3 );\nclasses.add( class_math );\nclasses.add( class_chemistry );\nclasses.add( class_french_lit );\nSystem.out.println( "classes unsorted: " + classes );\n
Run Code Online (Sandbox Code Playgroud)\n\n

使用自定义比较器对列表进行排序(请参阅下面的类定义)\xe2\x80\xa6

\n\n
java.util.Collections.sort( classes, new IntervalStartComparator() );\nSystem.out.println( "classes sorted: " + classes );\n
Run Code Online (Sandbox Code Playgroud)\n\n

创建代表我们找到的类之间的每个间隙的对象集合\xe2\x80\xa6

\n\n
java.util.List<Interval> gaps = new java.util.ArrayList<Interval>();\n\nDateTime gapStart = null, gapStop = null;\nfor ( int i = 0; i < classes.size(); i++ ) {\n    // For each class, take the prior class\' end as the gap\'s beginning, and the next class\' start as the gap\'s ending.\n    Interval session = classes.get( i ); // Cannot name the var "class" because that is a keyword in Java.\n    if ( i == 0 ) { // If first time through, grab the end of the first class as our first gap\'s start.\n        gapStart = session.getEnd();\n        continue;\n    }\n    gapStop = session.getStart();\n    Interval gap = new Interval( gapStart, gapStop );\n    gaps.add( gap );\n    gapStart = session.getEnd();\n}\n\nSystem.out.println( "gaps: " + gaps );\n
Run Code Online (Sandbox Code Playgroud)\n\n

上面代码中使用的比较器的类定义是从 Jon Skeet \xe2\x80\xa6的答案中提取的

\n\n
class IntervalStartComparator implements java.util.Comparator<Interval> {\n\n    @Override\n    public int compare( Interval x, Interval y ) {\n        return x.getStart().compareTo( y.getStart() );\n    }\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

当运行\xe2\x80\xa6时

\n\n
DateTimeZone timeZone = DateTimeZone.forID( "Europe/Paris" );\n
Run Code Online (Sandbox Code Playgroud)\n\n

期间

\n\n

你说过你只关心至少 15 分钟长的间隙。Joda-Time 中的Duration实例表示 Interval 的开始点和停止点之间的毫秒数。

\n\n

这是一些未经测试的即兴代码。

\n\n

将上面的“gap”变量重命名为“gapInterval”以提醒您它是一个Interval实例。

\n\n

请注意,这Minutes是一个类。下面看到的“分钟”变量是一个实例,而不是整数原语(“int”)。调用该getMinutes方法会呈现一个int基元。

\n\n
Interval class_math = new Interval( new DateTime( 2014, 1, 24, 10, 0, 0, timeZone ), new DateTime( 2014, 1, 24, 11, 15, 0, timeZone ) );\nInterval class_chemistry = new Interval( new DateTime( 2014, 1, 24, 8, 0, 0, timeZone ), new DateTime( 2014, 1, 24, 9, 15, 0, timeZone ) );\nInterval class_french_lit = new Interval( new DateTime( 2014, 1, 24, 13, 0, 0, timeZone ), new DateTime( 2014, 1, 24, 14, 15, 0, timeZone ) );\n
Run Code Online (Sandbox Code Playgroud)\n\n

ISO 8601

\n\n

您看到的字符串输出不是任意的。这些是ISO 8601格式。该方便的标准定义了单个日期时间值以及<start>/<end> 时间间隔的字符串表示形式。

\n\n

该标准还定义了可能对您有用的持续时间的字符串表示形式,PnYnMnDTnHnMnS格式为“P3Y6M4DT12H30M5S”,意思是“三年、六个月、四天、十二小时、三十分钟和五秒”。或者更短,就像你的情况一样,一个类可能是PT1H15M一个又一刻钟。

\n\n

Joda-Time 使用 ISO 8601 作为大多数内容的默认值,作为输入和输出。

\n