001/*
002 * Copyright (c) 2023 Chris K Wensel <[email protected]>. All Rights Reserved.
003 *
004 * This Source Code Form is subject to the terms of the Mozilla Public
005 * License, v. 2.0. If a copy of the MPL was not distributed with this
006 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
007 */
008
009package clusterless.commons.temporal;
010
011import java.time.Duration;
012import java.time.temporal.Temporal;
013import java.time.temporal.TemporalUnit;
014
015import static java.time.temporal.ChronoField.MINUTE_OF_DAY;
016import static java.time.temporal.ChronoUnit.MINUTES;
017
018/**
019 * Breaks a day into the number of intervals requested.
020 * <p/>
021 * Fourths is a 15-minute duration, there are 4 Fourths in an hour, and 96 Fourths in a day.
022 * <p/>
023 * Sixths is a 10-minute duration, there are 6 Sixths in an hour, and 144 Sixths in a day.
024 * <p/>
025 * Twelfths is a 5-minute duration, there are 12 Twelfths in an hour, and 288 Twelfth in a day.
026 */
027public enum IntervalUnit implements TemporalUnit {
028    FOURTHS("Fourths", Duration.ofMinutes(15)),
029    SIXTHS("Sixths", Duration.ofMinutes(10)),
030    TWELFTHS("Twelfths", Duration.ofMinutes(5));
031
032    private final String name;
033    private final Duration duration;
034
035    IntervalUnit(String name, Duration estimatedDuration) {
036        this.name = name;
037        this.duration = estimatedDuration;
038    }
039
040    @Override
041    public Duration getDuration() {
042        return duration;
043    }
044
045    @Override
046    public boolean isDurationEstimated() {
047        return false;
048    }
049
050    @Override
051    public boolean isDateBased() {
052        return false;
053    }
054
055    @Override
056    public boolean isTimeBased() {
057        return true;
058    }
059
060    @Override
061    public boolean isSupportedBy(Temporal temporal) {
062        return temporal.isSupported(MINUTE_OF_DAY);
063    }
064
065    @SuppressWarnings("unchecked")
066    @Override
067    public <R extends Temporal> R addTo(R temporal, long amount) {
068        switch (this) {
069            case FOURTHS:
070                return (R) temporal.plus(15 * amount, MINUTES);
071            case SIXTHS:
072                return (R) temporal.plus(10 * amount, MINUTES);
073            case TWELFTHS:
074                return (R) temporal.plus(5 * amount, MINUTES);
075            default:
076                throw new IllegalArgumentException();
077        }
078    }
079
080    @Override
081    public long between(Temporal temporal1Inclusive, Temporal temporal2Exclusive) {
082        if (temporal1Inclusive.getClass() != temporal2Exclusive.getClass()) {
083            return temporal1Inclusive.until(temporal2Exclusive, this);
084        }
085        switch (this) {
086            case FOURTHS:
087                return temporal1Inclusive.until(temporal2Exclusive, MINUTES) / 15;
088            case SIXTHS:
089                return temporal1Inclusive.until(temporal2Exclusive, MINUTES) / 10;
090            case TWELFTHS:
091                return temporal1Inclusive.until(temporal2Exclusive, MINUTES) / 5;
092            default:
093                throw new IllegalArgumentException();
094        }
095    }
096
097    @Override
098    public String toString() {
099        return name;
100    }
101}