4

I want to define a unit Time for example, 12 minutes or 25 minutes, for know how many unit Times there are between 2 LocalTime in Java.

For Example, if I defined 15 minutes like unit time, between 8:00 and 10:00, I should get 8 times.

Brayme Guaman
  • 175
  • 2
  • 12
  • `LocalDate` only stores dates, not times, so there is no "between 8:00 and 10:00" when using `LocalDate` – Andreas Mar 15 '19 at 20:13
  • SOrry is localTime – Brayme Guaman Mar 15 '19 at 20:14
  • 2
    Did you **read the documentation**, i.e. the javadoc of [`LocalTime`](https://docs.oracle.com/javase/8/docs/api/java/time/LocalTime.html), to see if there is any methods that can help with that? What did you try? --- *Hint: see `until`* – Andreas Mar 15 '19 at 20:14
  • I try this: ChronoUnit.MINUTES.between(start, end) but the problem is that ChronoUnito only have unitTime already defined, but I need specify my own unit time. – Brayme Guaman Mar 15 '19 at 20:16
  • 2
    "ChronoUnito only have unitTime already defined" then use multiplication and division. If you have X minutes between 2 dates, then you have X/20 "20 minute" intervals. – kajacx Mar 15 '19 at 20:23

3 Answers3

6

You can use Duration class to get the duration between two LocalTime values. Then you can calculate the custom time units yourself:

int minutesUnit = 15;
LocalTime startTime = LocalTime.of(8, 0);
LocalTime endTime = LocalTime.of(10, 0);
Duration duration = Duration.between(startTime, endTime);
long unitsCount = duration.toMinutes() / minutesUnit;
System.out.println(unitsCount);

This prints 8.

If you have different time units you could break the duration down to millis and calculate the result:

long millisUnit = TimeUnit.MINUTES.toMillis(15);
// ...
long unitsCount = duration.toMillis() / millisUnit;
Samuel Philipp
  • 10,631
  • 12
  • 36
  • 56
4
    Duration unit = Duration.ofMinutes(15);

    LocalTime start = LocalTime.of(8, 0);
    LocalTime end = LocalTime.of(10, 0);

    long howMany = Duration.between(start, end).dividedBy(unit);

    System.out.println("" + howMany + " units");

Output:

8 units

Since Java 9 Duration has had a dividedBy(Duration) method, just what you need here.

The limitation is it gives you only whole units. Had the unit been 25 minutes, the result would be 4 (not 4.8) units.

Ole V.V.
  • 81,772
  • 15
  • 137
  • 161
3

You can implement a custom TemporalUnit that is based on an arbitrary (positive) Duration. You can then use it like you use any built-in ChronoUnit, e.g.

LocalTime start = LocalTime.parse("08:00");
LocalTime end   = LocalTime.parse("10:00");

DurationUnit min15 = DurationUnit.ofMinutes(15);
System.out.println(min15.between(start, end)); // prints: 8
System.out.println(start.until(end, min15));   // prints: 8
System.out.println(start.plus(3, min15));      // prints: 08:45
DurationUnit min7 = DurationUnit.ofMinutes(7);
System.out.println(min7.between(start, end)); // prints: 17
System.out.println(start.until(end, min7));   // prints: 17
System.out.println(start.plus(3, min7));      // prints: 08:21

Custom TemporalUnit:

public final class DurationUnit implements TemporalUnit {

    private static final int SECONDS_PER_DAY = 86400;
    private static final long NANOS_PER_SECOND =  1000_000_000L;
    private static final long NANOS_PER_DAY = NANOS_PER_SECOND * SECONDS_PER_DAY;

    private final Duration duration;

    public static DurationUnit of(Duration duration)   { return new DurationUnit(duration); }
    public static DurationUnit ofDays(long days)       { return new DurationUnit(Duration.ofDays(days)); }
    public static DurationUnit ofHours(long hours)     { return new DurationUnit(Duration.ofHours(hours)); }
    public static DurationUnit ofMinutes(long minutes) { return new DurationUnit(Duration.ofMinutes(minutes)); }
    public static DurationUnit ofSeconds(long seconds) { return new DurationUnit(Duration.ofSeconds(seconds)); }
    public static DurationUnit ofMillis(long millis)   { return new DurationUnit(Duration.ofMillis(millis)); }
    public static DurationUnit ofNanos(long nanos)     { return new DurationUnit(Duration.ofNanos(nanos)); }

    private DurationUnit(Duration duration) {
        if (duration.isZero() || duration.isNegative())
            throw new IllegalArgumentException("Duration may not be zero or negative");
        this.duration = duration;
    }

    @Override
    public Duration getDuration() {
        return this.duration;
    }

    @Override
    public boolean isDurationEstimated() {
        return (this.duration.getSeconds() >= SECONDS_PER_DAY);
    }

    @Override
    public boolean isDateBased() {
        return (this.duration.getNano() == 0 && this.duration.getSeconds() % SECONDS_PER_DAY == 0);
    }

    @Override
    public boolean isTimeBased() {
        return (this.duration.getSeconds() < SECONDS_PER_DAY && NANOS_PER_DAY % this.duration.toNanos() == 0);
    }

    @Override
    @SuppressWarnings("unchecked")
    public <R extends Temporal> R addTo(R temporal, long amount) {
        return (R) this.duration.multipliedBy(amount).addTo(temporal);
    }

    @Override
    public long between(Temporal temporal1Inclusive, Temporal temporal2Exclusive) {
        return Duration.between(temporal1Inclusive, temporal2Exclusive).dividedBy(this.duration);
    }

    @Override
    public String toString() {
        return this.duration.toString();
    }

}
Andreas
  • 154,647
  • 11
  • 152
  • 247