Java: How to save a timeline / schedule, full or empty space from time x to y (interval)?

Brief information:

I have a java application that was used to view when certain places (classrooms) are used or not. The user places the location identifier in the search field, and the program displays the corresponding events (classes). The application will display all the relevant information (class name, room number, professor name, day of the week, class time), classes that are in the session (or will be soon) are color-coded, so you can indicate if something will come. The data is taken from the html page I am scraping from (I do not have SQL access).

Everything that works, I use JavaSwing for the user interface. Events are stored as the main object that I made to store it, the only part that matters to my question is that it stores Java Date objects for the start and end of each event.

What I'm trying to do now is add a way to check and display spaces between events (when the classroom is empty). I have all the data that I need (all the time the beginning and the end), but I am having problems actually actually encoding the program to see the spaces.

And if it’s not difficult, I want to implement it as simple as possible without using unnecessary libraries. I don’t want to recreate the wheel, but I would rather hash the code manually, and not just throw in the import and make a couple of calls; half the point of this project is to challenge yourself.

Right now I'm not looking for advice on how to actually display the data, while I'm just trying to logically organize it in an easy-to-use way. It will appear in JTable, but I'm not working on this implementation yet.


My scraper extracts something like <td id=time>10:00AM - 11:15AM</td> from the html table and analyzes it up to two lines 10:00AM and 11:15AM . They are transferred with other data to the course object.

The My Course object has a DateFormat set so that it can interpret incoming strings into numbers.

 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() 

The idea is that I will install two times by setting a window in which I want to check spaces. I want to select an interval of, say, 15 minutes, and find all the gaps in 15 or more minutes during which the classroom is empty, i.e. No classes.

+6
source share
2 answers

I do not have a complete answer, but I have some suggestions.

Timezone

A Date represents date-time in UTC / GMT, i.e. without a time zone offset. Your values ​​are in the time zone. In the end, you will feel better without ignoring this time zone. Adjust your values. As a rule, think, work and store dates in UTC / GMT. Convert to local time as needed for presentation in the user interface.

While java.util.Date does not have a time zone, the Joda-Time DateTime (discussed below) really knows its own time zone and time zone.

Avoid java.util.Date/Calendar

The java.util.Date and Calendar classes bundled with Java are known to be unpleasant. Avoid them.

Instead, use either:

Do not think of Joda-Time as any old "extra library". The first thing I do when creating a new project in my development environment is to add the Joda-Time library. This is just fine. Or juDate / Calendar is just so bad, depending on your perspective.

Enable Launch, End Exclusive

The best way to deal with a time period is to make the initial inclusion and ending exclusive. Write the logic where you test MORE, THAN OR UNIFORMLY, to the beginning and LESS than the end (not testing for peers at the end). I discuss this in yet another answer along with a chart.

Joda time

Joda-Time offers these classes to determine the time span: Period, Duration, and Internal. Clocks and similar classes offer some useful utility methods.

Find spaces

If your goal is to make a list of spaces, time intervals when a class is not assigned to a class, then the obvious way that seems to me is to sort the classes chronologically (and by class), as in the answer of Rob Whiteside . Define the “available” time period when its beginning ends with the previous class, and its end is the beginning of the next class. I have no experience in this area, so there may be a smarter way.

See this question on sorting a list of intervals.

Code example

Here is sample code using Joda-Time 2.3.

Specify the time zone, not rely on the default value ...

 DateTimeZone timeZone = DateTimeZone.forID( "Europe/Paris" ); 

Create three classes as sample data in random order ...

 Interval class_math = new Interval( new DateTime( 2014, 1, 24, 10, 0, 0, timeZone ), new DateTime( 2014, 1, 24, 11, 15, 0, timeZone ) ); Interval class_chemistry = new Interval( new DateTime( 2014, 1, 24, 8, 0, 0, timeZone ), new DateTime( 2014, 1, 24, 9, 15, 0, timeZone ) ); Interval class_french_lit = new Interval( new DateTime( 2014, 1, 24, 13, 0, 0, timeZone ), new DateTime( 2014, 1, 24, 14, 15, 0, timeZone ) ); 

Collect sample data into a list ...

 java.util.List<Interval> classes = new java.util.ArrayList<Interval>( 3 ); classes.add( class_math ); classes.add( class_chemistry ); classes.add( class_french_lit ); System.out.println( "classes unsorted: " + classes ); 

Sorting a list using a custom Comparator (see class definition below) ...

 java.util.Collections.sort( classes, new IntervalStartComparator() ); System.out.println( "classes sorted: " + classes ); 

Create a collection of objects representing each space between the found classes ...

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

The class definition for Comparator used in the code above and taken from this answer by John Skeet ...

 class IntervalStartComparator implements java.util.Comparator<Interval> { @Override public int compare( Interval x, Interval y ) { return x.getStart().compareTo( y.getStart() ); } } 

At startup ...

 classes unsorted: [2014-01-24T10:00:00.000+01:00/2014-01-24T11:15:00.000+01:00, 2014-01-24T08:00:00.000+01:00/2014-01-24T09:15:00.000+01:00, 2014-01-24T13:00:00.000+01:00/2014-01-24T14:15:00.000+01:00] classes sorted: [2014-01-24T08:00:00.000+01:00/2014-01-24T09:15:00.000+01:00, 2014-01-24T10:00:00.000+01:00/2014-01-24T11:15:00.000+01:00, 2014-01-24T13:00:00.000+01:00/2014-01-24T14:15:00.000+01:00] gaps: [2014-01-24T09:15:00.000+01:00/2014-01-24T10:00:00.000+01:00, 2014-01-24T11:15:00.000+01:00/2014-01-24T13:00:00.000+01:00] 

Duration

You said you take care of the breaks for at least 15 minutes. A Duration instance in Joda-Time represents milliseconds between the start and end points of an interval.

Here is some unverified code outside my head.

Renamed the “gap” var from above to “gapInterval” to remind you that this is Interval .

Note that Minutes is a class. The "Minutes" var shown below is an instance of a non- integer primitive ("int"). A call to the getMinutes method displays an int primitive.

 Duration duration = gapInterval.toDuration(); Minutes minutes = duration.toStandardMinutes(); // "Standard" means ignoring time zone anomalies such as Daylight Saving Time (DST). int mins = minutes.getMinutes(); boolean isGapSignificant = ( mins >= 15 ); 

ISO 8601

String outputs you see that they are not arbitrary. This is ISO 8601 . This convenient standard defines string representations of single values ​​for date and time , as well as the <start>/<end> time interval .

This standard also defines a string representation of durations that may be useful to you in the PnYnMnDTnHnMnS format, for example, "P3Y6M4DT12H30M5S", which means "three years, six months, four days, twelve hours, thirty minutes and five seconds." Or in short, as in your case, the class can be PT1H15M for one and a quarter hours.

Joda-Time uses ISO 8601 by default for most of all, both for inputs and outputs.

+1
source

Sorting is probably the key to your problem.

Presumably you have a large collection of all the courses you have cleared. First, you will need to pull all the courses specified by a specific location into a new list. You want this list to be sorted by course date. Check out various sorted collections (e.g. TreeSet ). You may also need to use a “comparator” to make sure your courses are sorted by date.

Once you have this list, it is just a matter of iterating over it and finding spaces.

+2
source

All Articles