Java: как сохранить временную шкалу/расписание, местоположение полностью или пусто от времени x до y (интервал)?

краткая справка:

у меня есть приложение java, которое используется, чтобы увидеть, когда определенные места (классы) используются или нет. Пользователь помещает идентификатор местоположения в поле поиска и программа отображает любые события (классы), соответствующие. Приложение отобразит всю соответствующую информацию (имя класса, номер #, имя профессора, день недели, время занятий), классы, которые находятся в сессии (или скоро будут), имеют цветовую кодировку, поэтому вы можете сразу сказать, есть ли что-нибудь. Этот данные поступают с html-страницы, с которой я соскабливаю (у меня нет доступа SQL).

все до этого момента работает, я использую JavaSwing для пользовательского интерфейса. События хранятся как базовый объект, который я сделал, чтобы держать его, единственная часть, которая имеет значение для моего вопроса, - это то, что он хранит объекты Java Date для времени начала и окончания каждого события.

то, что я пытаюсь сделать сейчас, это добавить способ проверить и отобразить промежутки между событиями (когда класс пуст). У меня есть все данные мне нужно (все время начала и конца), но у меня возникли проблемы с тем, чтобы на самом деле кодировать программу, чтобы увидеть пробелы.

и если это не достаточно сложно: я хочу реализовать его как можно проще, не используя никаких дополнительных библиотек. Я не хочу воссоздавать колесо, но я бы предпочел хэшировать код вручную, чем просто бросать импорт и пару вызовов методов; половина смысла этого проекта-бросить вызов себе.

пока я не ищу совет о том, как на самом деле отображать данные, пока я просто пытаюсь логически организовать его удобным способом. Он будет отображаться в JTable, но я еще не работаю над этой реализацией.


мой скребок вытаскивает из таблицы html что-то вроде <td id=time>10:00AM - 11:15AM</td> и разбирает его до двух строк 10:00AM и 11:15AM. Они передаются вместе с другими данными моему объекту курса.

мой объект курса имеет набор 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()

идея в том, что я установлю два раза, установив окно, в котором я хочу проверить пробелы. Я хочу выбрать интервал, скажем, 15 минут, и найти все промежутки в 15 или более минут, в течение которых класс пуст, т. е.

2 ответов


у меня нет полного ответа, но у меня есть некоторые предложения.

Часовой Пояс

A Date представляет дату-время в формате UTC / GMT, то есть без смещения часового пояса. Ваши ценности находятся в часовом поясе. В долгосрочной перспективе вам будет лучше не игнорировать этот часовой пояс. Отрегулируйте свои значения. Обычно думайте, работайте и храните дату и время в UTC/GMT. Преобразование в локальное время, необходимое для презентации в пользовательском интерфейсе.

в то время как java.утиль.Дата не имеет часовой пояс, A Joda-Time DateTime (обсуждается ниже) действительно знает свой собственный часовой пояс и смещение часового пояса.

избегайте java.утиль.Дата / Календарь

java.утиль.Классы даты и календаря в комплекте с Java, как известно, хлопотно. Избегать их.

, либо:
  • Joda Времени
  • новая java.время.* пакет на Java 8.
    этот пакет вдохновлен Joda-Time, определяется JSR 310, и заменяет старые связанные классы.

не думайте о Joda-Time как о любой старой "дополнительной библиотеке". Первое, что я делаю при создании нового проекта в моей IDE, - это добавляю библиотеку Joda-Time. Это просто хорошо. Или Джей.u.Дата / календарь - это просто плохо, в зависимости от вашей перспективы.

Start Inclusive, End Exclusive

самый лучший путь отрегулировать пядь времени сделать начало включительным и окончание эксклюзивный. Напишите логику, где вы проверяете больше или равно началу и меньше конца (не проверяя на равенство в конце). Я обсуждаю это больше в еще один ответ вместе с диаграммой.

Joda Времени

Joda-Time предлагает эти классы для определения промежутка времени: периода, продолжительности и внутреннего. Часы и аналогичные классы предлагают некоторые удобные методы утилиты.

Найти Пробелы

если ваша цель составьте список пробелов, промежутков времени, когда класс не назначен классу, тогда очевидным способом мне кажется сортировка классов в хронологическом порядке (и по классу), как в ответ Роба Уайтсайда. Определите "доступный" промежуток времени, где его начало-это конец предыдущего класса, а его конец-начало следующего класса. У меня нет опыта в этой области, поэтому может быть более умный способ.

посмотреть этот вопрос о сортировке a Список интервалов.

Пример Кода

вот пример кода с использованием Joda-Time 2.3.

укажите часовой пояс, а не полагаться на по умолчанию...

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

создайте три класса в качестве образцов данных в произвольном порядке...

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

соберите образцы данных в список...

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

сортировка списка с помощью пользовательского компаратора (см. определение класса ниже)...

java.util.Collections.sort( classes, new IntervalStartComparator() );
System.out.println( "classes sorted: " + 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's beginning, and the next class' start as the gap's 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's 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 );

определение класса для компаратор используется в коде выше и снят с этот ответ Джона Скита...

class IntervalStartComparator implements java.util.Comparator<Interval> {

    @Override
    public int compare( Interval x, Interval y ) {
        return x.getStart().compareTo( y.getStart() );
    }
}

при запуске...

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]

продолжительность

Вы сказали, что вас волнуют только промежутки длиной не менее 15 минут. А продолжительность экземпляр в Joda-Time представляет миллисекунды между начальной и конечной точками Интервал.

вот непроверенные off-the-top-of-my-head код.

переименован " gap "var сверху в "gapInterval", чтобы напомнить вам, что это интервал экземпляра.

отметим, что Minutes - это класс. "Минуты" var, увиденные ниже, являются экземпляром,не целочисленный примитив ("int"). Вызываю getMinutes способ оказывает int примитивно.

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

в строковые выходы, которые вы видите, не являются произвольными. Это ISO 8601 форматы. Этот удобный стандарт определяет строковые представления одиночные значения даты и времени а также <start>/<end> интервал времени.

этот стандарт также определяет строковое представление продолжительностью это может оказаться полезным для вас, в формате PnYnMnDTnHnMnS например, "P3Y6M4DT12H30M5S" означает " три года, шесть месяцев, четыре дней, двенадцать часов, тридцать минут и пять секунд". Или короче, как в вашем случае, класс может быть PT1H15M в течение полутора часов.

Joda-Time использует ISO 8601 по умолчанию для почти всего, как входы, так и выходы.


сортировка, вероятно, является ключом к вашей проблеме здесь.

предположительно, у вас есть большая коллекция всех курсов, которые вы наскребли. Сначала вам нужно будет иметь возможность вытащить все курсы, заданные в определенном месте в новый список. Вы хотите, чтобы этот список был отсортирован по дате курса. Проверьте различные отсортированных коллекций (например,TreeSet). Вероятно, вам также нужно будет использовать "компаратор", чтобы убедиться, что ваши курсы сортируются по их дата.

Как только у вас есть этот список, это просто вопрос итерации по нему и поиска пробелов.