Java создать дату для dayOfWeek и время без конкретной даты, то есть действительно для любого понедельника - PullRequest
0 голосов
/ 27 сентября 2018

Как я могу создать общую дату (то есть не привязанную к какой-либо фактической yyMMdd, но похожую на:

val START = LocalTime.of(startHour, startMinute)
val END = LocalTime.of(endHour, endMinute)

Однако я дополнительно хочу включить dayOfWeek.

Мое намерение состоит в том, чтобы рассчитать перекрытие временных интервалов, то есть для двух заданных (начало, конец) временных отметок, которые я хочу рассчитать для перекрытия с указанным днем ​​недели и временем (то есть, как часы работы).

edit

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

id,start,end
1,2018-01-01 08:00, 2018-01-01 08:00 || opening hours 8-10, duration: 1
2,2018-01-01 10:00, 2018-01-01 12:00 || opening hours 8-10, duration: 0
3,2018-01-02 10:00, 2018-01-02 12:00 || opening hours 10-15, duration 2

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

После создания объекта (где у меня в настоящее время есть мой, вероятно, поскольку я не могу комбинировать dayOfWeek и Time в общем виде)

Я бы использовал isBefore/isAfter пару раз, а затем вычислил бы продолжительность перекрытия.

Ответы [ 3 ]

0 голосов
/ 27 сентября 2018

Один простой подход заключается в использовании карты enum для этих «стандартных» интервалов.

Предполагается, что для вычисления перекрытия используется следующий метод:

static int calculateOverlap(LocalTime expectedStartTime, LocalTime expectedEndTime, 
        LocalTime actualStartTime, LocalTime actualEndTime) {
    //calculate overlap...
}

Вы можете посмотреть значение втаким образом (используя Pair для простоты, вы можете использовать пользовательский класс с двумя LocalTime полями):

Map<DayOfWeek, Pair<LocalTime, LocalTime>> openingHours = 
          new EnumMap<>(DayOfWeek.class);

openingHours.put(DayOfWeek.MONDAY, 
          Pair.of(LocalTime.of(8, 0), LocalTime.of(16, 0)));
openingHours.put(DayOfWeek.TUESDAY, 
          Pair.of(LocalTime.of(9, 0), LocalTime.of(17, 0)));
//...entries for other weekdays

А затем найдите его, используя:

MyEvent mondayEvent = ...

Pair<LocalTime, LocalTime> mondayHours = officialHours.get(DayOfWeek.MONDAY);
int overlap = calculateOverlap(mondayHours.getLeft(), mondayHours.getRight(),
        mondayEvent.getStart(), mondayEvent.getEnd());
0 голосов
/ 01 ноября 2018

My lib Time4J (v5.0) предлагает следующее готовое решение для всей вашей бизнес-задачи:

DayPartitionRule rule =
    new DayPartitionBuilder()
        .addWeekdayRule(
            Weekday.MONDAY,
            ClockInterval.between(PlainTime.of(8, 0), PlainTime.of(10, 0)))
        .addWeekdayRule(
            Weekday.TUESDAY,
            ClockInterval.between(PlainTime.of(10, 0), PlainTime.of(15, 0)))
        .build();
Map<Integer, TimestampInterval> events = new HashMap<>();
events.put(
    1,
    TimestampInterval.between(
        PlainTimestamp.of(2018, 1, 1, 8, 0),
        PlainTimestamp.of(2018, 1, 1, 9, 0)));
events.put(
    2,
    TimestampInterval.between(
        PlainTimestamp.of(2018, 1, 1, 10, 0),
        PlainTimestamp.of(2018, 1, 1, 12, 0)));
events.put(
    3,
    TimestampInterval.between(
        PlainTimestamp.of(2018, 1, 2, 10, 0),
        PlainTimestamp.of(2018, 1, 2, 12, 0)));
events.forEach(
    (id, interval) -> System.out.println(
        "Event: " + id + " => "
            + Duration.formatter(ClockUnit.class, "#h:mm").format(
                interval
                    .streamPartitioned(rule)
                    .map(i -> i.getDuration(ClockUnit.HOURS, ClockUnit.MINUTES))
                    .collect(Duration.summingUp())
                    .with(Duration.STD_CLOCK_PERIOD)
            )));

Вывод:

Событие: 1 => 1: 00

Событие: 2 => 0: 00

Событие: 3 => 2: 00

Алгоритм использует диапазон-пакет Time4J и по-прежнему работает должным образом, если у вас есть более одного тактового интервала в день недели или если интервал ввода превышает один день (который требует суммирования длительностей).

Кстати, я предполагаю, что ваша первая интервальная строка «2018-01-01 08:00, 2018-01-01 08:00» содержит опечатку, поэтому я настроил время окончания на 9 утра (в результатеожидаемая продолжительность одного часа).

0 голосов
/ 27 сентября 2018

Просто используйте перечисление DayOfWeek, встроенное в Java.Он предлагает семь предопределенных объектов, по одному на каждый день недели, например DayOfWeek.MONDAY.

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

public class Shift {
    DayOfWeek dayOfWeek ;
    LocalTime startTime , stopTime ;
}

Добавьте метод, который преобразует это в реальные моменты.

public ZonedDateTime startAtDate( LocalDate ld , ZoneId z ) {
    LocalDate LocalDate = ld.with( TemporalAdjustors.previousOrSame( this.dayOfWeek ) ) ;
    ZonedDateTime zdt = ZonedDateTime.of( localDate , this.startTime , z ) ;
    return zdt ;
}

Скорее всего, вы захотите добавить библиотеку ThreeTen-Extra в ваш проект.Он предлагает классы, такие как Interval и LocalDateTime, которые могут оказаться полезными.Эти классы предлагают несколько методов сравнения, таких как abuts , перекрытия и т. Д.

Похоже, что в библиотеке отсутствует LocalTimeRange, поэтому может потребоваться выполнитьсвоя.Возможно, даже пожертвовать такой класс для этого проекта.


О java.time

Среда java.time встроена в Java 8 и более поздние версии.Эти классы заменяют проблемные старые устаревшие классы даты и времени, такие как java.util.Date, Calendar, & SimpleDateFormat.

Проект Joda-Time , теперь в режиме обслуживания , рекомендует перейти на классы java.time .

Чтобы узнать больше, см. Oracle Tutorial .И поиск переполнения стека для многих примеров и объяснений.Спецификация: JSR 310 .

Вы можете обмениваться java.time объектами напрямую с вашей базой данных.Используйте драйвер JDBC , совместимый с JDBC 4.2 или более поздней версии.Нет необходимости в строках, нет необходимости в java.sql.* классах.

Где получить классы java.time?

  • Java SE 8 , Java SE 9 , Java SE 10, Java SE 11 и более поздних версий - часть стандартного Java API с связанной реализацией.
    • Java 9 добавляет некоторые незначительные функции и исправления.
  • Java SE 6 и JavaSE 7
    • Большая часть функций java.time перенесена на Java 6 & 7 в ThreeTen-Backport .
  • Android
    • Более поздние версии пакетов Android для реализации java.time классы.
    • Для более ранних версий Android (<26) проект <a href="https://github.com/JakeWharton/ThreeTenABP" rel="nofollow noreferrer"> ThreeTenABP адаптируется ThreeTen-Backport (упомянуто выше).См. Как использовать ThreeTenABP… .
...