List of usage examples for org.joda.time Interval overlap
public Interval overlap(ReadableInterval interval)
From source file:org.apache.druid.query.aggregation.FilteredAggregatorFactory.java
License:Apache License
@Override public AggregatorFactory optimizeForSegment(PerSegmentQueryOptimizationContext optimizationContext) { if (dimFilter instanceof IntervalDimFilter) { IntervalDimFilter intervalDimFilter = ((IntervalDimFilter) dimFilter); if (intervalDimFilter.getExtractionFn() != null) { // no support for extraction functions right now return this; }//from w w w .j a v a2 s .c om if (!intervalDimFilter.getDimension().equals(ColumnHolder.TIME_COLUMN_NAME)) { // segment time boundary optimization only applies when we filter on __time return this; } Interval segmentInterval = optimizationContext.getSegmentDescriptor().getInterval(); List<Interval> filterIntervals = intervalDimFilter.getIntervals(); List<Interval> excludedFilterIntervals = new ArrayList<>(); List<Interval> effectiveFilterIntervals = new ArrayList<>(); boolean segmentIsCovered = false; for (Interval filterInterval : filterIntervals) { Interval overlap = filterInterval.overlap(segmentInterval); if (overlap == null) { excludedFilterIntervals.add(filterInterval); continue; } if (overlap.equals(segmentInterval)) { segmentIsCovered = true; break; } else { // clip the overlapping interval to the segment time boundaries effectiveFilterIntervals.add(overlap); } } // we can skip applying this filter, everything in the segment will match if (segmentIsCovered) { return delegate; } // we can skip this filter, nothing in the segment would match if (excludedFilterIntervals.size() == filterIntervals.size()) { return new SuppressedAggregatorFactory(delegate); } return new FilteredAggregatorFactory(delegate, new IntervalDimFilter(intervalDimFilter.getDimension(), effectiveFilterIntervals, intervalDimFilter.getExtractionFn(), intervalDimFilter.getFilterTuning()), this.name); } else { return this; } }
From source file:org.apache.druid.query.vector.VectorCursorGranularizer.java
License:Apache License
@Nullable public static VectorCursorGranularizer create(final StorageAdapter storageAdapter, final VectorCursor cursor, final Granularity granularity, final Interval queryInterval) { final DateTime minTime = storageAdapter.getMinTime(); final DateTime maxTime = storageAdapter.getMaxTime(); final Interval storageAdapterInterval = new Interval(minTime, granularity.bucketEnd(maxTime)); final Interval clippedQueryInterval = queryInterval.overlap(storageAdapterInterval); if (clippedQueryInterval == null) { return null; }/*w w w . ja va 2 s . c o m*/ final Iterable<Interval> bucketIterable = granularity.getIterable(clippedQueryInterval); final Interval firstBucket = granularity.bucket(clippedQueryInterval.getStart()); final VectorValueSelector timeSelector; if (firstBucket.contains(clippedQueryInterval)) { // Only one bucket, no need to read the time column. assert Iterables.size(bucketIterable) == 1; timeSelector = null; } else { // Multiple buckets, need to read the time column to know when we move from one to the next. timeSelector = cursor.getColumnSelectorFactory().makeValueSelector(ColumnHolder.TIME_COLUMN_NAME); } return new VectorCursorGranularizer(cursor, bucketIterable, timeSelector); }
From source file:org.apache.druid.segment.incremental.IncrementalIndexStorageAdapter.java
License:Apache License
@Override public Sequence<Cursor> makeCursors(@Nullable final Filter filter, final Interval interval, final VirtualColumns virtualColumns, final Granularity gran, final boolean descending, @Nullable QueryMetrics<?> queryMetrics) { if (index.isEmpty()) { return Sequences.empty(); }/*from w w w. ja v a 2 s. c om*/ final Interval dataInterval = new Interval(getMinTime(), gran.bucketEnd(getMaxTime())); if (!interval.overlaps(dataInterval)) { return Sequences.empty(); } final Interval actualInterval = interval.overlap(dataInterval); Iterable<Interval> intervals = gran.getIterable(actualInterval); if (descending) { intervals = Lists.reverse(ImmutableList.copyOf(intervals)); } return Sequences.simple(intervals) .map(i -> new IncrementalIndexCursor(virtualColumns, descending, filter, i, actualInterval, gran)); }
From source file:org.apache.druid.segment.QueryableIndexStorageAdapter.java
License:Apache License
@Nullable private Interval computeCursorInterval(final Granularity gran, final Interval interval) { final DateTime minTime = getMinTime(); final DateTime maxTime = getMaxTime(); final Interval dataInterval = new Interval(minTime, gran.bucketEnd(maxTime)); if (!interval.overlaps(dataInterval)) { return null; }//from w w w.j a v a 2s .c om return interval.overlap(dataInterval); }
From source file:org.estatio.dom.valuetypes.AbstractInterval.java
License:Apache License
/** * Gets the overlap between this interval and another interval. * //w w w . ja v a 2 s . c o m * @param otherInterval * @return */ @SuppressWarnings("unchecked") public T overlap(final T otherInterval) { if (otherInterval == null) { return null; } if (otherInterval.isInfinite()) { return (T) this; } if (this.isInfinite()) { return otherInterval; } final Interval thisAsInterval = asInterval(); final Interval otherAsInterval = otherInterval.asInterval(); Interval overlap = thisAsInterval.overlap(otherAsInterval); if (overlap == null) { return null; } return newInterval(overlap); }
From source file:org.hawkular.metrics.api.jaxrs.influx.query.translate.ToIntervalTranslator.java
License:Apache License
/** * Return the interval described by the where clause. * * @param whereClause the Influx query where clause * @return an {@link org.joda.time.Interval} or null if the where clause does define a proper interval (i.e. * <code>time > '2012-08-15' and time < '1998-08-15'</code> *//*from w w w .j ava2 s .c o m*/ public Interval toInterval(BooleanExpression whereClause) { if (whereClause instanceof GtBooleanExpression) { return getIntervalFromGtExpression((GtBooleanExpression) whereClause); } else if (whereClause instanceof LtBooleanExpression) { return getIntervalFromLtExpression((LtBooleanExpression) whereClause); } AndBooleanExpression and = (AndBooleanExpression) whereClause; Interval left; Interval right; if (and.getLeftExpression() instanceof GtBooleanExpression) { left = getIntervalFromGtExpression((GtBooleanExpression) and.getLeftExpression()); } else { left = getIntervalFromLtExpression((LtBooleanExpression) and.getLeftExpression()); } if (and.getRightExpression() instanceof GtBooleanExpression) { right = getIntervalFromGtExpression((GtBooleanExpression) and.getRightExpression()); } else { right = getIntervalFromLtExpression((LtBooleanExpression) and.getRightExpression()); } return left.overlap(right); }
From source file:org.kalypso.ogc.sensor.filter.filters.interval.IntervalValuesOperation.java
License:Open Source License
private IntervalData overlapSourcePart(final Interval targetInterval, final IntervalData sourceData) { final Interval sourceInterval = sourceData.getInterval(); final long sourceDuration = sourceInterval.toDurationMillis(); final Interval sourcePart = targetInterval.overlap(sourceInterval); if (sourcePart == null) return null; final double sourcePartDuration = sourcePart.toDurationMillis(); /*/*from www . j a v a 2s.co m*/ * The partial source interval gets only a part of the original value, depending on how much it covers the original * source interval */ final double factor = sourcePartDuration / sourceDuration; // FIXME: performance hot spot... final TupleModelDataSet[] clonedValues = TupleModelDataSet.clone(sourceData.getDataSets()); for (final TupleModelDataSet clone : clonedValues) { clone.setValue(((Number) clone.getValue()).doubleValue() * factor); } return new IntervalData(sourcePart, clonedValues); }
From source file:org.kalypso.ui.rrm.internal.calccase.CatchmentModelHelper.java
License:Open Source License
/** * This function compares the validity ranges of the generators. * * @param compareGenerator/*from ww w . j ava 2 s .co m*/ * The compare generator. * @param generators * All generators the compare generator will be compared against. If the compare generator is contained, it * will be ignored. * @return <ul> * <li>True: The validity range of the compare generator does not overlap the validity ranges of the other * generators.</li> * <li>False: The validity range of the compare generator overlaps one validity range of the other generators. * </li> * </ul> */ private static boolean compareGeneratorValidityOverlap(final IRainfallGenerator compareGenerator, final IRainfallGenerator[] generators) { /* No generators available, to compare to. */ if (generators.length == 0) return true; /* The interval of the compare generator. */ final Interval compareInterval = new Interval(new DateTime(compareGenerator.getValidFrom()), new DateTime(compareGenerator.getValidTo())); /* Check if the interval overlaps one of the other intervals. */ for (final IRainfallGenerator generator : generators) { /* Do not compare the compare generator with itself. */ if (compareGenerator.getId().equals(generator.getId())) continue; /* The interval of the generator. */ final Interval interval = new Interval(new DateTime(generator.getValidFrom()), new DateTime(generator.getValidTo())); if (compareInterval.overlaps(interval)) { final Interval overlapInterval = compareInterval.overlap(interval); final Duration overlapDuration = overlapInterval.toDuration(); final long standardMinutes = overlapDuration.getStandardMinutes(); if (standardMinutes > 0) return false; } } return true; }
From source file:org.kalypso.ui.rrm.internal.calccase.MultiCatchmentModelRunner.java
License:Open Source License
/** * This function runs the linear sum generator. * // ww w. j a v a 2 s.c o m * @param prefix * This prefix is used when writing the timeseries. * @param simulation * The simulation. * @param control * The na control. * @param model * The na model. * @param generator * The rainfall generator. * @param targetLink * The target link. * @param parameterType * The parameter type. * @param hash * The hash. * @param monitor * A progress monitor. */ private void runGenerator(final String prefix, final RrmSimulation simulation, final NAControl control, final NaModell model, final ILinearSumGenerator generator, final QName targetLink, final String parameterType, final CatchmentTimeseriesHash hash, final IProgressMonitor monitor) throws Exception { try { /* Monitor. */ monitor.beginTask( String.format(Messages.getString("MultiCatchmentModelRunner_7"), generator.getDescription()), //$NON-NLS-1$ 1000); monitor.subTask(Messages.getString("MultiCatchmentModelRunner_8")); //$NON-NLS-1$ /* This object can calculate some values. */ final LinearSumCatchmentModelInfo linearInfo = new LinearSumCatchmentModelInfo(simulation, control, model, generator, targetLink, parameterType); /* Get the timestep and timestamp. */ final Period timestep = linearInfo.getTimestep(); final LocalTime timestamp = linearInfo.getTimestamp(); /* HINT: The range is the adjusted simulation range. */ final DateRange simulationRange = linearInfo.getSimulationRange(); /* Intersect adjusted simulation range with validity range of generator. */ final Interval simulationInterval = new Interval(new DateTime(simulationRange.getFrom()), new DateTime(simulationRange.getTo())); /* Calculate range of current generator. */ final Interval validityInterval = new Interval(new DateTime(generator.getValidFrom()), new DateTime(generator.getValidTo())); /* Intersect complete simulation with this generator, only this range will be calculated. */ final Interval interval = validityInterval.overlap(simulationInterval); // FIXME: The intersected interval does now NOT cover the extended range (3 steps before, 1 step after). // So the complete result does NOT cover the extended range. final DateRange range = new DateRange(interval.getStart().toDate(), interval.getEnd().toDate()); /* The catchment model runner should be executed with this generic info. */ final ICatchmentModelInfo genericInfo = new GenericCatchmentModelInfo(simulation, control, model, generator, targetLink, parameterType, timestep, timestamp, range, range); /* Create the linear sum catchment model runner. */ final LinearSumCatchmentModelRunner runner = new LinearSumCatchmentModelRunner(prefix); /* Calculate the catchment model. */ runner.executeCatchmentModel(genericInfo, new SubProgressMonitor(monitor, 500)); /* Get the catchments. */ final IFeatureBindingCollection<Catchment> catchments = model.getCatchments(); for (final Catchment catchment : catchments) { /* The feature id of the catchment must be unique. */ final String id = catchment.getId(); /* Get the link of the timeseries. */ ZmlLink link = null; if (parameterType.equals(ITimeseriesConstants.TYPE_RAINFALL)) link = catchment.getPrecipitationLink(); else if (parameterType.equals(ITimeseriesConstants.TYPE_EVAPORATION_LAND_BASED)) link = catchment.getEvaporationLink(); else if (parameterType.equals(ITimeseriesConstants.TYPE_MEAN_TEMPERATURE)) link = catchment.getTemperatureLink(); else throw new IllegalArgumentException(Messages.getString("MultiCatchmentModelRunner_9")); //$NON-NLS-1$ /* Store the timeseries link. */ hash.put(id, link.getTimeseriesLink()); } /* Monitor. */ monitor.worked(500); } finally { /* Monitor. */ monitor.done(); } }
From source file:org.kuali.kpme.tklm.time.rules.shiftdifferential.service.ShiftDifferentialRuleServiceImpl.java
License:Educational Community License
@Override public void processShiftDifferentialRules(TimesheetDocument timesheetDocument, TkTimeBlockAggregate aggregate) { DateTimeZone zone = HrServiceLocator.getTimezoneService().getUserTimezoneWithFallback(); List<List<TimeBlock>> blockDays = aggregate.getDayTimeBlockList(); DateTime periodStartDateTime = timesheetDocument.getCalendarEntry().getBeginPeriodLocalDateTime() .toDateTime(zone);// ww w. j a v a 2 s . com Map<Long, Set<ShiftDifferentialRule>> jobNumberToShifts = getJobNumberToShiftRuleMap(timesheetDocument); // If there are no shift differential rules, we have an early exit. if (jobNumberToShifts.isEmpty()) { return; } // Get the last day of the previous pay period. We need this to determine // if there are hours from the previous pay period that will effect the // shift rule on the first day of the currently-being-processed pay period. // // Will be set to null if not applicable. boolean previousPayPeriodPrevDay = true; Map<Long, List<TimeBlock>> jobNumberToTimeBlocksPreviousDay = getPreviousPayPeriodLastDayJobToTimeBlockMap( timesheetDocument, jobNumberToShifts); // We are going to look at the time blocks grouped by Days. // // This is a very large outer loop. for (int pos = 0; pos < blockDays.size(); pos++) { List<TimeBlock> blocks = blockDays.get(pos); // Timeblocks for this day. if (blocks.isEmpty()) continue; // No Time blocks, no worries. DateTime currentDay = periodStartDateTime.plusDays(pos); Interval virtualDay = new Interval(currentDay, currentDay.plusHours(24)); // Builds our JobNumber to TimeBlock for Current Day List. // // Shift Differential Rules are also grouped by Job number, this // provides a quick way to do the lookup / reference. // We don't need every time block, only the ones that will be // applicable to the shift rules. Map<Long, List<TimeBlock>> jobNumberToTimeBlocks = new HashMap<Long, List<TimeBlock>>(); for (TimeBlock block : blocks) { Long jobNumber = block.getJobNumber(); if (jobNumberToShifts.containsKey(jobNumber)) { List<TimeBlock> jblist = jobNumberToTimeBlocks.get(jobNumber); if (jblist == null) { jblist = new ArrayList<TimeBlock>(); jobNumberToTimeBlocks.put(jobNumber, jblist); } jblist.add(block); } } // Large Outer Loop to look at applying the Shift Rules based on // the current JobNumber. // // This loop will handle previous day boundary time as well as the // current day. // // There is room for refactoring here! for (Map.Entry<Long, Set<ShiftDifferentialRule>> entry : jobNumberToShifts.entrySet()) { Set<ShiftDifferentialRule> shiftDifferentialRules = entry.getValue(); // Obtain and sort our previous and current time blocks. List<TimeBlock> ruleTimeBlocksPrev = null; List<TimeBlock> ruleTimeBlocksCurr = jobNumberToTimeBlocks.get(entry.getKey()); if (ruleTimeBlocksCurr != null && ruleTimeBlocksCurr.size() > 0) { if (jobNumberToTimeBlocksPreviousDay != null) ruleTimeBlocksPrev = jobNumberToTimeBlocksPreviousDay.get(entry.getKey()); if (ruleTimeBlocksPrev != null && ruleTimeBlocksPrev.size() > 0) this.sortTimeBlocksInverse(ruleTimeBlocksPrev); this.sortTimeBlocksNatural(ruleTimeBlocksCurr); } else { // Skip to next job, there is nothing for this job // on this day, and because of this we don't care // about the previous day either. continue; } for (ShiftDifferentialRule rule : shiftDifferentialRules) { Set<String> fromEarnGroup = HrServiceLocator.getEarnCodeGroupService() .getEarnCodeListForEarnCodeGroup(rule.getFromEarnGroup(), timesheetDocument .getCalendarEntry().getBeginPeriodFullDateTime().toLocalDate()); LocalTime ruleStart = new LocalTime(rule.getBeginTime(), zone); LocalTime ruleEnd = new LocalTime(rule.getEndTime(), zone); DateTime shiftEnd = ruleEnd.toDateTime(currentDay); DateTime shiftStart = ruleStart.toDateTime(currentDay); if (shiftEnd.isBefore(shiftStart) || shiftEnd.isEqual(shiftStart)) { shiftEnd = shiftEnd.plusDays(1); } Interval shiftInterval = new Interval(shiftStart, shiftEnd); // Set up buckets to handle previous days time accumulations BigDecimal hoursBeforeVirtualDay = BigDecimal.ZERO; // Check current day first block to see if start time gap from virtual day start is greater than max gap // if so, we can skip the previous day checks. TimeBlock firstBlockOfCurrentDay = null; for (TimeBlock b : ruleTimeBlocksCurr) { if (timeBlockHasEarnCode(fromEarnGroup, b)) { firstBlockOfCurrentDay = b; break; } } // Previous Day :: We have prior block container of nonzero size, and the previous day is active. Interval previousDayShiftInterval = new Interval(shiftStart.minusDays(1), shiftEnd.minusDays(1)); // Blank initialization pointer for picking which interval to pass to applyPremium() Interval evalInterval = null; if (ruleTimeBlocksPrev != null && ruleTimeBlocksPrev.size() > 0 && dayIsRuleActive(currentDay.minusDays(1), rule)) { // Simple heuristic to see if we even need to worry about // the Shift rule for this set of data. if (shiftEnd.isAfter(virtualDay.getEnd())) { // Compare first block of previous day with first block of current day for max gaptitude. TimeBlock firstBlockOfPreviousDay = null; for (TimeBlock b : ruleTimeBlocksPrev) { if (timeBlockHasEarnCode(fromEarnGroup, b)) { firstBlockOfPreviousDay = b; break; } } // Only if we actually have at least one block. // Adding Assumption: We must have both a valid current and previous block. Max Gap can not be more than a virtual day. // If this assumption does not hold, additional logic will be needed to iteratively go back in time to figure out which // blocks are valid. if ((firstBlockOfPreviousDay != null) && (firstBlockOfCurrentDay != null)) { Interval previousBlockInterval = new Interval( firstBlockOfPreviousDay.getEndDateTime().withZone(zone), firstBlockOfCurrentDay.getBeginDateTime().withZone(zone)); Duration blockGapDuration = previousBlockInterval.toDuration(); BigDecimal bgdHours = TKUtils.convertMillisToHours(blockGapDuration.getMillis()); // if maxGap is 0, ignore gaps and assign shift to time blocks within the hours if (rule.getMaxGap().compareTo(BigDecimal.ZERO) == 0 || bgdHours.compareTo(rule.getMaxGap()) <= 0) { // If we are here, we know we have at least one valid time block to pull some hours forward from. // These are inversely sorted. for (int i = 0; i < ruleTimeBlocksPrev.size(); i++) { TimeBlock b = ruleTimeBlocksPrev.get(i); if (timeBlockHasEarnCode(fromEarnGroup, b)) { Interval blockInterval = new Interval( b.getBeginDateTime().withZone(zone), b.getEndDateTime().withZone(zone)); // Calculate Block Gap, the duration between clock outs and clock ins of adjacent time blocks. if (previousBlockInterval != null) { blockGapDuration = new Duration(b.getEndDateTime().withZone(zone), previousBlockInterval.getStart()); bgdHours = TKUtils .convertMillisToHours(blockGapDuration.getMillis()); } // Check Gap, if good, sum hours, if maxGap is 0, ignore gaps if (rule.getMaxGap().compareTo(BigDecimal.ZERO) == 0 || bgdHours.compareTo(rule.getMaxGap()) <= 0) { // Calculate Overlap and add it to hours before virtual day bucket. if (blockInterval.overlaps(previousDayShiftInterval)) { BigDecimal hrs = TKUtils.convertMillisToHours(blockInterval .overlap(previousDayShiftInterval).toDurationMillis()); hoursBeforeVirtualDay = hoursBeforeVirtualDay.add(hrs); } } else { // Time blocks are reverse sorted, we can jump out as soon as the max gap is exceeded. break; } previousBlockInterval = blockInterval; } } } else { // DO NOTHING! } } } } BigDecimal hoursToApply = BigDecimal.ZERO; BigDecimal hoursToApplyPrevious = BigDecimal.ZERO; // If the hours before virtual day are less than or equal to // min hours, we have already applied the time, so we don't // set hoursToApplyPrevious if (hoursBeforeVirtualDay.compareTo(rule.getMinHours()) <= 0) { // we need to apply these hours. hoursToApplyPrevious = hoursBeforeVirtualDay; } // Current Day TimeBlock previous = null; // Previous Time Block List<TimeBlock> accumulatedBlocks = new ArrayList<TimeBlock>(); // TimeBlocks we MAY or MAY NOT apply Shift Premium to. List<Interval> accumulatedBlockIntervals = new ArrayList<Interval>(); // To save recompute time when checking timeblocks for application we store them as we create them. // Iterate over sorted list, checking time boundaries vs Shift Intervals. long accumulatedMillis = TKUtils.convertHoursToMillis(hoursBeforeVirtualDay); boolean previousDayOnly = false; // IF the rule is not active today, but was on the previous day, we need to still look at time blocks. if (!dayIsRuleActive(currentDay, rule)) { if (dayIsRuleActive(currentDay.minusDays(1), rule)) { previousDayOnly = true; } else { // Nothing to see here, move to next rule. continue; } } /* * We will touch each time block and accumulate time blocks that are applicable to * the current rule we are on. */ // These blocks are only used for detail application // We don't want to pass along the previous pay period, // because we don't want to modify the time blocks on that // period. If null is passed, time will be placed on the // first block of the first period if the previous period // block had influence. List<TimeBlock> previousBlocksFiltered = (previousPayPeriodPrevDay) ? null : filterBlocksByApplicableEarnGroup(fromEarnGroup, ruleTimeBlocksPrev); for (TimeBlock current : ruleTimeBlocksCurr) { if (!timeBlockHasEarnCode(fromEarnGroup, current)) { // TODO: WorkSchedule considerations somewhere in here? continue; } Interval blockInterval = new Interval(current.getBeginDateTime().withZone(zone), current.getEndDateTime().withZone(zone)); // Check both Intervals, since the time blocks could still // be applicable to the previous day. These two intervals should // not have any overlap. if (previousDayShiftInterval.overlaps(shiftInterval)) { LOG.error("Interval of greater than 24 hours created in the rules processing."); return; // throw new RuntimeException("Interval of greater than 24 hours created in the rules processing."); } // This block of code handles cases where you have time // that spills to multiple days and a shift rule that // has a valid window on multiple consecutive days. Time // must be applied with the correct shift interval. Interval overlap = previousDayShiftInterval.overlap(blockInterval); evalInterval = previousDayShiftInterval; if (overlap == null) { if (hoursToApplyPrevious.compareTo(BigDecimal.ZERO) > 0) { // we have hours from previous day, and the shift // window is going to move to current day. // Need to apply this now, and move window forward // for current time block. BigDecimal accumHours = TKUtils.convertMillisToHours(accumulatedMillis); this.applyAccumulatedWrapper(accumHours, evalInterval, accumulatedBlockIntervals, accumulatedBlocks, previousBlocksFiltered, hoursToApplyPrevious, hoursToApply, rule); accumulatedMillis = 0L; // reset accumulated hours.. hoursToApply = BigDecimal.ZERO; hoursToApplyPrevious = BigDecimal.ZERO; } // Because of our position in the loop, when we are at this point, // we know we've passed any previous day shift intervals, so we can // determine if we should skip the current day based on the boolean // we set earlier. if (previousDayOnly) { continue; } overlap = shiftInterval.overlap(blockInterval); evalInterval = shiftInterval; } // Time bucketing and application as normal: // if (overlap != null) { // There IS overlap. if (previous != null) { // only check max gap if max gap of rule is not 0 if (rule.getMaxGap().compareTo(BigDecimal.ZERO) != 0 && exceedsMaxGap(previous, current, rule.getMaxGap())) { BigDecimal accumHours = TKUtils.convertMillisToHours(accumulatedMillis); this.applyAccumulatedWrapper(accumHours, evalInterval, accumulatedBlockIntervals, accumulatedBlocks, previousBlocksFiltered, hoursToApplyPrevious, hoursToApply, rule); accumulatedMillis = 0L; // reset accumulated hours.. hoursToApply = BigDecimal.ZERO; hoursToApplyPrevious = BigDecimal.ZERO; } else { long millis = overlap.toDurationMillis(); accumulatedMillis += millis; hoursToApply = hoursToApply.add(TKUtils.convertMillisToHours(millis)); } } else { // Overlap shift at first time block. long millis = overlap.toDurationMillis(); accumulatedMillis += millis; hoursToApply = hoursToApply.add(TKUtils.convertMillisToHours(millis)); } accumulatedBlocks.add(current); accumulatedBlockIntervals.add(blockInterval); previous = current; // current can still apply to next. } else { // No Overlap / Outside of Rule if (previous != null) { BigDecimal accumHours = TKUtils.convertMillisToHours(accumulatedMillis); this.applyAccumulatedWrapper(accumHours, evalInterval, accumulatedBlockIntervals, accumulatedBlocks, previousBlocksFiltered, hoursToApplyPrevious, hoursToApply, rule); accumulatedMillis = 0L; // reset accumulated hours.. hoursToApply = BigDecimal.ZERO; hoursToApplyPrevious = BigDecimal.ZERO; } } } // All time blocks are iterated over, check for remainders. // Check containers for time, and apply if needed. BigDecimal accumHours = TKUtils.convertMillisToHours(accumulatedMillis); this.applyAccumulatedWrapper(accumHours, evalInterval, accumulatedBlockIntervals, accumulatedBlocks, previousBlocksFiltered, hoursToApplyPrevious, hoursToApply, rule); } } // Keep track of previous as we move day by day. jobNumberToTimeBlocksPreviousDay = jobNumberToTimeBlocks; previousPayPeriodPrevDay = false; } }