org.darkware.wpman.util.TimeWindow.java Source code

Java tutorial

Introduction

Here is the source code for org.darkware.wpman.util.TimeWindow.java

Source

/*******************************************************************************
 * Copyright (c) 2016. darkware.org and contributors
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 ******************************************************************************/

package org.darkware.wpman.util;

import org.apache.commons.lang3.RandomUtils;

import java.time.Duration;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.temporal.ChronoUnit;
import java.time.temporal.TemporalAmount;

/**
 * A {@code TimeWindow} is a helper object for generating {@link LocalDateTime} or {@link Duration} objects which
 * fall within a given span of time.
 *
 * @author jeff
 * @since 2016-04-11
 */
public class TimeWindow {
    /**
     * Calculates the next time when a given hour and minute occur, based from the current time.
     *
     * @param hour The hour to search for.
     * @param minute The minute to search for.
     * @return A {@code DateTime} corresponding to the hour and minute declared which is explicitly after
     * the current time.
     */
    public static LocalDateTime nextTime(final int hour, final int minute) {
        return TimeWindow.nextTime(LocalDateTime.now(), hour, minute);
    }

    /**
     * Calculates the next time when a given hour and minute occur, based from the given start time.
     *
     * @param after The time to start searching from.
     * @param hour The hour to search for.
     * @param minute The minute to search for.
     * @return A {@code DateTime} corresponding to the hour and minute declared which is explicitly after
     * the start time.
     */
    public static LocalDateTime nextTime(final LocalDateTime after, final int hour, final int minute) {
        LocalTime time = LocalTime.of(hour, minute);
        LocalDate afterDate = after.toLocalDate();
        if (!time.isAfter(after.toLocalTime()))
            afterDate = afterDate.plus(1, ChronoUnit.DAYS);
        return time.atDate(afterDate);
    }

    private LocalDateTime earliest;
    private LocalDateTime latest;

    /**
     * Creates a new time window with the declared start and stop times.
     *
     * @param earliest The earliest allowed time in the window.
     * @param latest The latest allowed time in the window.
     */
    public TimeWindow(final LocalDateTime earliest, final LocalDateTime latest) {
        super();

        this.earliest = earliest;
        this.latest = latest;
    }

    /**
     * Creates a new time window with the declared start and a given duration.
     *
     * @param earliest The earliest allowed time in the window.
     * @param duration The length of the window.
     */
    public TimeWindow(final LocalDateTime earliest, final TemporalAmount duration) {
        this(earliest, earliest.plus(duration));
    }

    /**
     * Creates a new time window the with declared start and stop times. This particular method uses an
     * admittedly bizarre combination of parameters which marginally improves the performance of the form
     * that takes two hour (or hour-minute) specifications.
     *
     * @param earliest The earliest allowed time in the window.
     * @param latestHour The latest allowed time in the window, as the next hour after the start.
     * @param latestMinute The minutes past the latest hour allowed.
     */
    protected TimeWindow(final LocalDateTime earliest, final int latestHour, final int latestMinute) {
        this(earliest, TimeWindow.nextTime(earliest, latestHour, latestMinute));
    }

    /**
     * Creates a new time window based on the declared hour and minute pairs. The time specifications are
     * interpreted as starting on the first time after the present matching the hour and minute, and ending at
     * the first time after the start which matches the ending hour and minute.
     *
     * @param earliestHour The hour of the start time for the window.
     * @param earliestMinute The minutes past the hour for the start time of the window.
     * @param latestHour The hour of the end time for the window.
     * @param latestMinute The minutes past the hour for the end time of the window.
     */
    public TimeWindow(final int earliestHour, final int earliestMinute, final int latestHour,
            final int latestMinute) {
        this(TimeWindow.nextTime(earliestHour, earliestMinute), latestHour, latestMinute);
    }

    /**
     * Creates a new time window based on the declared hours. This is equivalent to calling
     * {@link #TimeWindow(int, int, int, int)} with the minutes set to 0.
     *
     * @param earliestHour The hour of the start time for the window.
     * @param latestHour The hour of the end time for the window.
     * @see #TimeWindow(int, int, int, int)
     */
    public TimeWindow(final int earliestHour, final int latestHour) {
        this(earliestHour, 0, latestHour, 0);
    }

    /**
     * Fetch the earliest moment in this time window.
     *
     * @return A {@code DateTime} representing the earliest possible time in this window.
     */
    public LocalDateTime getEarliestMoment() {
        return this.earliest;
    }

    /**
     * Fetch the latest moment in this time window.
     *
     * @return A {@code DateTime} representing the latest possible time in this window.
     */
    public LocalDateTime getLatestMoment() {
        return this.latest;
    }

    /**
     * Fetch a random moment falling somewhere inside this time window.
     *
     * @return A {@code DateTime} representing a random moment which is explicitly between the earliest
     * and latest moments in the window.
     */
    public LocalDateTime getRandomMoment() {
        long durationSeconds = this.earliest.until(this.latest, ChronoUnit.SECONDS);
        return this.earliest.plus(RandomUtils.nextLong(0, durationSeconds), ChronoUnit.SECONDS);
    }

    /**
     * Fetch a time offset to a random moment within the time window.
     *
     * @return A number of seconds to a moment that is within the time window.
     */
    public Duration getRandomOffset() {
        return Duration.between(LocalDateTime.now(), this.getRandomMoment());
    }
}