Skip to content

Commit

Permalink
Addressing review comments. Add methods that return durations.
Browse files Browse the repository at this point in the history
  • Loading branch information
chipkent committed Dec 6, 2023
1 parent bfb96fb commit f25ebce
Show file tree
Hide file tree
Showing 4 changed files with 193 additions and 9 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -211,14 +211,23 @@ public long standardBusinessNanos() {
return standardBusinessDay.businessNanos();
}

/**
* Length of a standard business day.
*
* @return length of a standard business day
*/
public Duration standardBusinessDuration() {
return standardBusinessDay.businessDuration();
}

/**
* Business day schedules for all holidays. A holiday is a date that has a schedule that is different from the
* schedule for a standard business day or weekend.
*
* @return a map of holiday dates and their calendar days
*/
public Map<LocalDate, CalendarDay<Instant>> holidays() {
return Collections.unmodifiableMap(holidays);
return holidays;
}

/**
Expand Down Expand Up @@ -1451,6 +1460,58 @@ public long diffNonBusinessNanos(final ZonedDateTime start, final ZonedDateTime
return diffNonBusinessNanos(start.toInstant(), end.toInstant());
}

/**
* Returns the amount of business time between two times.
*
* @param start start of a time range
* @param end end of a time range
* @return the amount of business time between {@code start} and {@code end}
* @throws RequirementFailure if any input is null
* @throws InvalidDateException if the dates are not in the valid range
*/
public Duration diffBusinessDuration(final Instant start, final Instant end) {
return Duration.ofNanos(diffBusinessNanos(start, end));
}

/**
* Returns the amount of business time between two times.
*
* @param start start of a time range
* @param end end of a time range
* @return the amount of business time between {@code start} and {@code end}
* @throws RequirementFailure if any input is null
* @throws InvalidDateException if the dates are not in the valid range
*/
public Duration diffBusinessDuration(final ZonedDateTime start, final ZonedDateTime end) {
return Duration.ofNanos(diffBusinessNanos(start, end));
}

/**
* Returns the amount of non-business time between two times.
*
* @param start start of a time range
* @param end end of a time range
* @return the amount of non-business time between {@code start} and {@code end}
* @throws RequirementFailure if any input is null
* @throws InvalidDateException if the dates are not in the valid range
*/
public Duration diffNonBusinessDuration(final Instant start, final Instant end) {
return Duration.ofNanos(diffNonBusinessNanos(start, end));
}

/**
* Returns the amount of non-business time between two times.
*
* @param start start of a time range
* @param end end of a time range
* @return the amount of non-business time between {@code start} and {@code end}
* @throws RequirementFailure if any input is null
* @throws InvalidDateException if the dates are not in the valid range
*/
public Duration diffNonBusinessDuration(final ZonedDateTime start, final ZonedDateTime end) {
return Duration.ofNanos(diffNonBusinessNanos(start, end));
}

/**
* Returns the amount of business time in standard business days between two times.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,7 @@
import io.deephaven.base.verify.RequirementFailure;
import org.jetbrains.annotations.NotNull;

import java.time.Instant;
import java.time.LocalDate;
import java.time.LocalTime;
import java.time.ZoneId;
import java.time.*;
import java.time.temporal.ChronoUnit;
import java.time.temporal.Temporal;
import java.util.*;
Expand Down Expand Up @@ -111,6 +108,16 @@ public long businessNanos() {
return businessTimeRanges.stream().map(TimeRange::nanos).reduce(0L, Long::sum);
}

/**
* Gets the length of the business day. If the business day has multiple business time ranges, only the time during
* the ranges is counted.
*
* @return length of the day
*/
public Duration businessDuration() {
return Duration.ofNanos(businessNanos());
}

/**
* Amount of business time in nanoseconds that has elapsed on the given day by the specified time.
*
Expand All @@ -135,6 +142,16 @@ public long businessNanosElapsed(final T time) {
return elapsed;
}

/**
* Amount of business time that has elapsed on the given day by the specified time.
*
* @param time time
* @return business time that has elapsed on the given day by the specified time
*/
public Duration businessDurationElapsed(final T time) {
return Duration.ofNanos(businessNanosElapsed(time));
}

/**
* Amount of business time in nanoseconds that remains until the end of the day.
*
Expand All @@ -146,6 +163,16 @@ public long businessNanosRemaining(final T time) {
return businessNanos() - businessNanosElapsed(time);
}

/**
* Amount of business time that remains until the end of the day.
*
* @param time time
* @return business time that remains until the end of the day
*/
public Duration businessDurationRemaining(final T time) {
return Duration.ofNanos(businessNanosRemaining(time));
}

/**
* Is this day a business day?
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ protected void setUp() throws Exception {
public void testBusinessGetters() {
assertEquals(schedule, bCalendar.standardBusinessDay());
assertEquals(schedule.businessNanos(), bCalendar.standardBusinessNanos());
assertEquals(schedule.businessDuration(), bCalendar.standardBusinessDuration());
assertEquals(holidays, bCalendar.holidays());
assertEquals(firstValidDate, bCalendar.firstValidDate());
assertEquals(lastValidDate, bCalendar.lastValidDate());
Expand Down Expand Up @@ -1057,6 +1058,60 @@ public void testDiffNonBusinessNanos() {
bCalendar.diffNonBusinessNanos(zdt3.toInstant(), zdt1.toInstant()));
}

public void testDiffBusinessDuration() {
// Same day
final ZonedDateTime zdt1 = LocalDate.of(2023, 7, 3).atTime(9, 27).atZone(timeZone);
final ZonedDateTime zdt2 = LocalDate.of(2023, 7, 3).atTime(12, 10).atZone(timeZone);

assertEquals(Duration.ofNanos(zdt1.until(zdt2, ChronoUnit.NANOS)), bCalendar.diffBusinessDuration(zdt1, zdt2));
assertEquals(Duration.ofNanos(-zdt1.until(zdt2, ChronoUnit.NANOS)), bCalendar.diffBusinessDuration(zdt2, zdt1));
assertEquals(Duration.ofNanos(zdt1.until(zdt2, ChronoUnit.NANOS)),
bCalendar.diffBusinessDuration(zdt1.toInstant(), zdt2.toInstant()));
assertEquals(Duration.ofNanos(-zdt1.until(zdt2, ChronoUnit.NANOS)),
bCalendar.diffBusinessDuration(zdt2.toInstant(), zdt1.toInstant()));

// Multiple holidays
final ZonedDateTime zdt3 = LocalDate.of(2023, 7, 8).atTime(12, 54).atZone(timeZone);
final long target = schedule.businessNanosRemaining(zdt1.toLocalTime()) // 2023-07-03
// 2023-07-04 holiday
// 2023-07-05 weekend WED
+ halfDay.businessNanos() // 2023-07-06 half day
+ schedule.businessNanos() // normal day
+ schedule.businessNanosElapsed(zdt3.toLocalTime());

assertEquals(Duration.ofNanos(target), bCalendar.diffBusinessDuration(zdt1, zdt3));
assertEquals(Duration.ofNanos(-target), bCalendar.diffBusinessDuration(zdt3, zdt1));
assertEquals(Duration.ofNanos(target), bCalendar.diffBusinessDuration(zdt1.toInstant(), zdt3.toInstant()));
assertEquals(Duration.ofNanos(-target), bCalendar.diffBusinessDuration(zdt3.toInstant(), zdt1.toInstant()));
}

public void testDiffNonBusinessDuration() {
// Same day
final ZonedDateTime zdt1 = LocalDate.of(2023, 7, 3).atTime(6, 27).atZone(timeZone);
final ZonedDateTime zdt2 = LocalDate.of(2023, 7, 3).atTime(15, 10).atZone(timeZone);

assertEquals(Duration.ofNanos(DateTimeUtils.diffNanos(zdt1, zdt2) - bCalendar.diffBusinessNanos(zdt1, zdt2)),
bCalendar.diffNonBusinessDuration(zdt1, zdt2));
assertEquals(Duration.ofNanos(-bCalendar.diffNonBusinessNanos(zdt1, zdt2)),
bCalendar.diffNonBusinessDuration(zdt2, zdt1));
assertEquals(Duration.ofNanos(DateTimeUtils.diffNanos(zdt1, zdt2) - bCalendar.diffBusinessNanos(zdt1, zdt2)),
bCalendar.diffNonBusinessDuration(zdt1.toInstant(), zdt2.toInstant()));
assertEquals(Duration.ofNanos(-bCalendar.diffNonBusinessNanos(zdt1, zdt2)),
bCalendar.diffNonBusinessDuration(zdt2.toInstant(), zdt1.toInstant()));

// Multiple holidays
final ZonedDateTime zdt3 = LocalDate.of(2023, 7, 8).atTime(12, 54).atZone(timeZone);

assertEquals(Duration.ofNanos(DateTimeUtils.diffNanos(zdt1, zdt3) - bCalendar.diffBusinessNanos(zdt1, zdt3)),
bCalendar.diffNonBusinessDuration(zdt1, zdt3));
assertEquals(Duration.ofNanos(-bCalendar.diffNonBusinessNanos(zdt1, zdt3)),
bCalendar.diffNonBusinessDuration(zdt3, zdt1));
assertEquals(Duration.ofNanos(DateTimeUtils.diffNanos(zdt1, zdt3) - bCalendar.diffBusinessNanos(zdt1, zdt3)),
bCalendar.diffNonBusinessDuration(zdt1.toInstant(), zdt3.toInstant()));
assertEquals(Duration.ofNanos(-bCalendar.diffNonBusinessNanos(zdt1, zdt3)),
bCalendar.diffNonBusinessDuration(zdt3.toInstant(), zdt1.toInstant()));
}

public void testDiffBusinessDays() {
final ZonedDateTime zdt1 = LocalDate.of(2023, 7, 3).atTime(6, 27).atZone(timeZone);
final ZonedDateTime zdt2 = LocalDate.of(2023, 7, 10).atTime(15, 10).atZone(timeZone);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,7 @@
import io.deephaven.base.testing.BaseArrayTestCase;
import io.deephaven.time.DateTimeUtils;

import java.time.Instant;
import java.time.LocalDate;
import java.time.LocalTime;
import java.time.ZoneId;
import java.time.*;
import java.util.List;
import java.util.Objects;

Expand All @@ -32,14 +29,20 @@ public void testEmpty() {
assertNull(empty.businessEnd());
assertNull(empty.businessEnd());
assertEquals(0L, empty.businessNanos());
assertEquals(Duration.ofNanos(0), empty.businessDuration());
assertEquals(0L, empty.businessNanos());
assertEquals(Duration.ofNanos(0), empty.businessDuration());
assertFalse(empty.isBusinessDay());
assertFalse(empty.isBusinessTime(open1));
assertFalse(empty.isBusinessTime(close1));
assertEquals(0L, empty.businessNanosElapsed(open1));
assertEquals(Duration.ofNanos(0), empty.businessDurationElapsed(open1));
assertEquals(0L, empty.businessNanosElapsed(close1));
assertEquals(Duration.ofNanos(0), empty.businessDurationElapsed(close1));
assertEquals(0L, empty.businessNanosRemaining(open1));
assertEquals(Duration.ofNanos(0), empty.businessDurationRemaining(open1));
assertEquals(0L, empty.businessNanosRemaining(close1));
assertEquals(Duration.ofNanos(0), empty.businessDurationRemaining(close1));
}

public void testSinglePeriod() {
Expand All @@ -50,21 +53,33 @@ public void testSinglePeriod() {
assertEquals(close1, single.businessEnd());
assertEquals(close1, single.businessEnd());
assertEquals(DateTimeUtils.HOUR, single.businessNanos());
assertEquals(Duration.ofNanos(DateTimeUtils.HOUR), single.businessDuration());
assertEquals(DateTimeUtils.HOUR, single.businessNanos());
assertEquals(Duration.ofNanos(DateTimeUtils.HOUR), single.businessDuration());
assertTrue(single.isBusinessDay());
assertTrue(single.isBusinessTime(DateTimeUtils.parseInstant("2017-03-11T10:00:00.000000000 NY")));
assertTrue(single.isBusinessTime(DateTimeUtils.parseInstant("2017-03-11T10:15:00.000000000 NY")));
assertTrue(single.isBusinessTime(DateTimeUtils.parseInstant("2017-03-11T11:00:00.000000000 NY")));
assertFalse(single.isBusinessTime(DateTimeUtils.parseInstant("2017-03-11T11:10:00.000000000 NY")));
assertEquals(0L, single.businessNanosElapsed(DateTimeUtils.parseInstant("2017-03-11T01:00:00.000000000 NY")));
assertEquals(Duration.ofNanos(0),
single.businessDurationElapsed(DateTimeUtils.parseInstant("2017-03-11T01:00:00.000000000 NY")));
assertEquals(DateTimeUtils.MINUTE * 30,
single.businessNanosElapsed(DateTimeUtils.parseInstant("2017-03-11T10:30:00.000000000 NY")));
assertEquals(Duration.ofNanos(DateTimeUtils.MINUTE * 30),
single.businessDurationElapsed(DateTimeUtils.parseInstant("2017-03-11T10:30:00.000000000 NY")));
assertEquals(DateTimeUtils.HOUR,
single.businessNanosElapsed(DateTimeUtils.parseInstant("2017-03-11T13:00:00.000000000 NY")));
assertEquals(Duration.ofNanos(DateTimeUtils.HOUR),
single.businessDurationElapsed(DateTimeUtils.parseInstant("2017-03-11T13:00:00.000000000 NY")));
assertEquals(DateTimeUtils.MINUTE * 30,
single.businessNanosRemaining(DateTimeUtils.parseInstant("2017-03-11T10:30:00.000000000 NY")));
assertEquals(Duration.ofNanos(DateTimeUtils.MINUTE * 30),
single.businessDurationRemaining(DateTimeUtils.parseInstant("2017-03-11T10:30:00.000000000 NY")));
assertEquals(0L,
single.businessNanosRemaining(DateTimeUtils.parseInstant("2017-03-11T13:00:00.000000000 NY")));
assertEquals(Duration.ofNanos(0),
single.businessDurationRemaining(DateTimeUtils.parseInstant("2017-03-11T13:00:00.000000000 NY")));
}

public void testMultiPeriod() {
Expand All @@ -75,26 +90,42 @@ public void testMultiPeriod() {
assertEquals(close2, multi.businessEnd());
assertEquals(close2, multi.businessEnd());
assertEquals(DateTimeUtils.HOUR * 6, multi.businessNanos());
assertEquals(Duration.ofNanos(DateTimeUtils.HOUR * 6), multi.businessDuration());
assertEquals(DateTimeUtils.HOUR * 6, multi.businessNanos());
assertEquals(Duration.ofNanos(DateTimeUtils.HOUR * 6), multi.businessDuration());
assertTrue(multi.isBusinessDay());
assertTrue(multi.isBusinessTime(DateTimeUtils.parseInstant("2017-03-11T10:00:00.000000000 NY")));
assertTrue(multi.isBusinessTime(DateTimeUtils.parseInstant("2017-03-11T10:15:00.000000000 NY")));
assertTrue(multi.isBusinessTime(DateTimeUtils.parseInstant("2017-03-11T11:00:00.000000000 NY")));
assertFalse(multi.isBusinessTime(DateTimeUtils.parseInstant("2017-03-11T11:10:00.000000000 NY")));
assertTrue(multi.isBusinessTime(DateTimeUtils.parseInstant("2017-03-11T12:10:00.000000000 NY")));
assertEquals(0L, multi.businessNanosElapsed(DateTimeUtils.parseInstant("2017-03-11T01:00:00.000000000 NY")));
assertEquals(Duration.ofNanos(0L),
multi.businessDurationElapsed(DateTimeUtils.parseInstant("2017-03-11T01:00:00.000000000 NY")));
assertEquals(DateTimeUtils.MINUTE * 30,
multi.businessNanosElapsed(DateTimeUtils.parseInstant("2017-03-11T10:30:00.000000000 NY")));
assertEquals(Duration.ofNanos(DateTimeUtils.MINUTE * 30),
multi.businessDurationElapsed(DateTimeUtils.parseInstant("2017-03-11T10:30:00.000000000 NY")));
assertEquals(DateTimeUtils.HOUR * 2,
multi.businessNanosElapsed(DateTimeUtils.parseInstant("2017-03-11T13:00:00.000000000 NY")));
assertEquals(Duration.ofNanos(DateTimeUtils.HOUR * 2),
multi.businessDurationElapsed(DateTimeUtils.parseInstant("2017-03-11T13:00:00.000000000 NY")));
assertEquals(DateTimeUtils.HOUR * 2,
multi.businessNanosElapsed(DateTimeUtils.parseInstant("2017-03-11T13:00:00.000000000 NY")));
assertEquals(Duration.ofNanos(DateTimeUtils.HOUR * 2),
multi.businessDurationElapsed(DateTimeUtils.parseInstant("2017-03-11T13:00:00.000000000 NY")));
assertEquals(DateTimeUtils.HOUR * 6,
multi.businessNanosRemaining(DateTimeUtils.parseInstant("2017-03-11T01:00:00.000000000 NY")));
assertEquals(Duration.ofNanos(DateTimeUtils.HOUR * 6),
multi.businessDurationRemaining(DateTimeUtils.parseInstant("2017-03-11T01:00:00.000000000 NY")));
assertEquals(DateTimeUtils.HOUR * 5 + DateTimeUtils.MINUTE * 30,
multi.businessNanosRemaining(DateTimeUtils.parseInstant("2017-03-11T10:30:00.000000000 NY")));
assertEquals(Duration.ofNanos(DateTimeUtils.HOUR * 5 + DateTimeUtils.MINUTE * 30),
multi.businessDurationRemaining(DateTimeUtils.parseInstant("2017-03-11T10:30:00.000000000 NY")));
assertEquals(DateTimeUtils.HOUR * 4,
multi.businessNanosRemaining(DateTimeUtils.parseInstant("2017-03-11T13:00:00.000000000 NY")));
assertEquals(Duration.ofNanos(DateTimeUtils.HOUR * 4),
multi.businessDurationRemaining(DateTimeUtils.parseInstant("2017-03-11T13:00:00.000000000 NY")));


final CalendarDay<Instant> multi2 = new CalendarDay<>(new TimeRange[] {period2, period1});
Expand All @@ -104,20 +135,30 @@ public void testMultiPeriod() {
assertEquals(close2, multi2.businessEnd());
assertEquals(close2, multi2.businessEnd());
assertEquals(DateTimeUtils.HOUR * 6, multi2.businessNanos());
assertEquals(Duration.ofNanos(DateTimeUtils.HOUR * 6), multi2.businessDuration());
assertEquals(DateTimeUtils.HOUR * 6, multi2.businessNanos());
assertEquals(Duration.ofNanos(DateTimeUtils.HOUR * 6), multi2.businessDuration());
assertTrue(multi2.isBusinessDay());
assertTrue(multi2.isBusinessTime(DateTimeUtils.parseInstant("2017-03-11T10:00:00.000000000 NY")));
assertTrue(multi2.isBusinessTime(DateTimeUtils.parseInstant("2017-03-11T10:15:00.000000000 NY")));
assertTrue(multi2.isBusinessTime(DateTimeUtils.parseInstant("2017-03-11T11:00:00.000000000 NY")));
assertFalse(multi2.isBusinessTime(DateTimeUtils.parseInstant("2017-03-11T11:10:00.000000000 NY")));
assertTrue(multi2.isBusinessTime(DateTimeUtils.parseInstant("2017-03-11T12:10:00.000000000 NY")));
assertEquals(0L, multi2.businessNanosElapsed(DateTimeUtils.parseInstant("2017-03-11T01:00:00.000000000 NY")));
assertEquals(Duration.ofNanos(0),
multi2.businessDurationElapsed(DateTimeUtils.parseInstant("2017-03-11T01:00:00.000000000 NY")));
assertEquals(DateTimeUtils.MINUTE * 30,
multi2.businessNanosElapsed(DateTimeUtils.parseInstant("2017-03-11T10:30:00.000000000 NY")));
assertEquals(Duration.ofNanos(DateTimeUtils.MINUTE * 30),
multi2.businessDurationElapsed(DateTimeUtils.parseInstant("2017-03-11T10:30:00.000000000 NY")));
assertEquals(DateTimeUtils.HOUR * 2,
multi2.businessNanosElapsed(DateTimeUtils.parseInstant("2017-03-11T13:00:00.000000000 NY")));
assertEquals(Duration.ofNanos(DateTimeUtils.HOUR * 2),
multi2.businessDurationElapsed(DateTimeUtils.parseInstant("2017-03-11T13:00:00.000000000 NY")));
assertEquals(DateTimeUtils.HOUR * 2,
multi2.businessNanosElapsed(DateTimeUtils.parseInstant("2017-03-11T13:00:00.000000000 NY")));
assertEquals(Duration.ofNanos(DateTimeUtils.HOUR * 2),
multi2.businessDurationElapsed(DateTimeUtils.parseInstant("2017-03-11T13:00:00.000000000 NY")));
}

public void testPeriodsOverlap() {
Expand Down

0 comments on commit f25ebce

Please sign in to comment.