Example usage for org.joda.time DateTime plusDays

List of usage examples for org.joda.time DateTime plusDays

Introduction

In this page you can find the example usage for org.joda.time DateTime plusDays.

Prototype

public DateTime plusDays(int days) 

Source Link

Document

Returns a copy of this datetime plus the specified number of days.

Usage

From source file:org.kitesdk.apps.spi.oozie.CronConverter.java

License:Apache License

public static Instant nextInstant(String cronSchedule, Instant current) {

    DateTime currentTime = new DateTime(current, DateTimeZone.UTC).withSecondOfMinute(0).withMillisOfSecond(0);

    validate(cronSchedule);/*from  www  . ja  va 2 s  .c om*/

    String[] splits = cronSchedule.split(" ");

    String minutePart = splits[0];
    String hourPart = splits[1];
    String dayPart = splits[2];

    // TODO: fold these together like the hour.
    if (isWildCard(minutePart)) {
        return currentTime.plusMinutes(1).toInstant();
    }

    if (isInterval(minutePart)) {

        // Roll minutes forward until we hit a start time
        // that matches the cron interval.
        int interval = getInterval(minutePart);

        DateTime next = currentTime.withSecondOfMinute(0).plusMinutes(1);

        while (!(next.getMinuteOfHour() % interval == 0)) {

            next = next.plusMinutes(1);
        }

        return next.toInstant();
    }

    assert (isConstant(minutePart));

    // The minute part must be a constant, so
    // simply get the value.
    int minute = Integer.parseInt(minutePart);

    // The schedule is based on hours.
    if (!isConstant(hourPart)) {

        int hourModulus = isWildCard(hourPart) ? 1 : getInterval(hourPart);

        DateTime next = currentTime.withMinuteOfHour(minute);

        while (next.isBefore(current) || !(next.getHourOfDay() % hourModulus == 0)) {

            next = next.plusHours(1);
        }

        return next.toInstant();
    }

    int hour = Integer.parseInt(hourPart);

    // The schedule is based on days, and therfore the day cannot
    // be a constant. This is is checked in validation as well.
    assert (!isConstant(dayPart));

    DateTime next = currentTime.withMinuteOfHour(minute).withHourOfDay(hour);

    while (next.isBefore(current)) {

        next = next.plusDays(1);
    }

    return next.toInstant();
}

From source file:org.kuali.kpme.core.calendar.entry.dao.CalendarEntryDaoOjbImpl.java

License:Educational Community License

public List<CalendarEntry> getCurrentCalendarEntryNeedsScheduled(int thresholdDays, DateTime asOfDate) {
    DateTime windowStart = asOfDate.minusDays(thresholdDays);
    DateTime windowEnd = asOfDate.plusDays(thresholdDays);

    Criteria root = new Criteria();

    root.addGreaterOrEqualThan("beginPeriodDateTime", windowStart.toDate());
    root.addLessOrEqualThan("beginPeriodDateTime", windowEnd.toDate());

    Query query = QueryFactory.newQuery(CalendarEntry.class, root);
    Collection c = this.getPersistenceBrokerTemplate().getCollectionByQuery(query);

    List<CalendarEntry> pce = new ArrayList<CalendarEntry>(c.size());
    pce.addAll(c);//from   w ww  . ja v  a 2  s .  c  o m

    return pce;
}

From source file:org.kuali.kpme.core.calendar.entry.service.CalendarEntryServiceImpl.java

License:Educational Community License

private DateTime plusSemiMonth(DateTime date) {
    //so assuming the common pairs of this are the 1st & 16th, and then 15th and the last day,
    // and 14th with the last day minus 1
    //so we'll peek at the current date and try to figure out the best guesses for addition.
    if (date.getDayOfMonth() == date.dayOfMonth().getMaximumValue()) {
        //date is on the last day of the month.  Set next date to the 15th
        return date.plusMonths(1).withDayOfMonth(15);
    } else if (date.getDayOfMonth() == 15) {
        //we are on the 15th of the month, so now lets go to the end of the month
        return date.withDayOfMonth(date.dayOfMonth().getMaximumValue());
    } else if (date.getDayOfMonth() == 1) {
        //first of the month, next would be 16
        return date.withDayOfMonth(16);
    } else if (date.getDayOfMonth() == 16) {
        //16th, so add a month and set day to '1'
        return date.plusMonths(1).withDayOfMonth(1);
    } else if (date.getDayOfMonth() == 14) {
        //14th day, set next one to last day minus 1
        return date.withDayOfMonth(date.dayOfMonth().getMaximumValue() - 1);
    } else if (date.getDayOfMonth() == date.dayOfMonth().getMaximumValue() - 1) {
        //date is on the second to last day of the month.  Set next date to the 14th
        return date.plusMonths(1).withDayOfMonth(14);
    } else {//from  w  ww.j  av a  2 s.c o  m
        // so it isn't one of the common dates... i guess we'll just add 15 days...
        return date.plusDays(15);
    }
}

From source file:org.kuali.kpme.core.util.TKUtils.java

License:Educational Community License

/**
 * Constructs a list of Day Spans for the pay calendar entry provided. You
 * must also provide a DateTimeZone so that we can create relative boundaries.
 *
 * @param calendarEntry/*  w w w  .  j a v a 2  s.  c om*/
 * @param timeZone
 * @return
 */
public static List<Interval> getDaySpanForCalendarEntry(CalendarEntry calendarEntry, DateTimeZone timeZone) {
    DateTime beginDateTime = calendarEntry.getBeginPeriodLocalDateTime().toDateTime(timeZone);
    DateTime endDateTime = calendarEntry.getEndPeriodLocalDateTime().toDateTime(timeZone);

    List<Interval> dayIntervals = new ArrayList<Interval>();

    DateTime currDateTime = beginDateTime;
    while (currDateTime.isBefore(endDateTime)) {
        DateTime prevDateTime = currDateTime;
        currDateTime = currDateTime.plusDays(1);
        Interval daySpan = new Interval(prevDateTime, currDateTime);
        dayIntervals.add(daySpan);
    }

    return dayIntervals;
}

From source file:org.kuali.kpme.core.util.TKUtils.java

License:Educational Community License

public static List<Interval> createDaySpan(DateTime beginDateTime, DateTime endDateTime, DateTimeZone zone) {
    beginDateTime = beginDateTime.toDateTime(zone);
    endDateTime = endDateTime.toDateTime(zone);
    List<Interval> dayIntervals = new ArrayList<Interval>();

    DateTime currDateTime = beginDateTime;
    while (currDateTime.isBefore(endDateTime)) {
        DateTime prevDateTime = currDateTime;
        currDateTime = currDateTime.plusDays(1);
        Interval daySpan = new Interval(prevDateTime, currDateTime);
        dayIntervals.add(daySpan);//  ww  w.  j a  v  a 2  s . c o  m
    }

    return dayIntervals;
}

From source file:org.kuali.kpme.core.util.TKUtils.java

License:Educational Community License

public static List<Interval> getFullWeekDaySpanForCalendarEntry(CalendarEntry calendarEntry,
        DateTimeZone timeZone) {/*from   w w w.  j a va 2  s .c  o  m*/
    DateTime beginDateTime = calendarEntry.getBeginPeriodLocalDateTime().toDateTime(timeZone);
    DateTime endDateTime = calendarEntry.getEndPeriodLocalDateTime().toDateTime(timeZone);

    List<Interval> dayIntervals = new ArrayList<Interval>();

    DateTime currDateTime = beginDateTime;
    if (beginDateTime.getDayOfWeek() != 7) {
        currDateTime = beginDateTime.plusDays(0 - beginDateTime.getDayOfWeek());
    }

    int afterEndDate = 6 - endDateTime.getDayOfWeek();
    if (endDateTime.getDayOfWeek() == 7 && endDateTime.getHourOfDay() != 0) {
        afterEndDate = 6;
    }
    if (endDateTime.getHourOfDay() == 0) {
        afterEndDate += 1;
    }
    DateTime aDate = endDateTime.plusDays(afterEndDate);
    while (currDateTime.isBefore(aDate)) {
        DateTime prevDateTime = currDateTime;
        currDateTime = currDateTime.plusDays(1);
        Interval daySpan = new Interval(prevDateTime, currDateTime);
        dayIntervals.add(daySpan);
    }

    return dayIntervals;
}

From source file:org.kuali.kpme.core.util.TKUtils.java

License:Educational Community License

public static int getWorkDays(DateTime startDate, DateTime endDate) {
    int workDays = 0;

    DateTime currentDate = startDate;
    while (!currentDate.isAfter(endDate)) {
        if (!isWeekend(currentDate)) {
            workDays++;/*from  www  .j a va 2s .  co m*/
        }
        currentDate = currentDate.plusDays(1);
    }

    return workDays;
}

From source file:org.kuali.kpme.tklm.common.CalendarValidationUtil.java

License:Educational Community License

public static List<String> validateSpanningWeeks(DateTime startDate, DateTime endDate) {
    List<String> errors = new ArrayList<String>();

    boolean isOnlyWeekendSpan = true;
    while ((startDate.isBefore(endDate) || startDate.isEqual(endDate)) && isOnlyWeekendSpan) {
        if (startDate.getDayOfWeek() != DateTimeConstants.SATURDAY
                && startDate.getDayOfWeek() != DateTimeConstants.SUNDAY) {
            isOnlyWeekendSpan = false;/*from   w ww . j a  v a  2s.  c  o m*/
        }
        startDate = startDate.plusDays(1);
    }
    if (isOnlyWeekendSpan) {
        errors.add("Weekend day is selected, but include weekends checkbox is not checked"); //errorMessages
    }

    return errors;
}

From source file:org.kuali.kpme.tklm.leave.accrual.bucket.KPMEAccrualCategoryBucket.java

License:Educational Community License

private void adjustBalances(CalendarEntry calendarEntry, DateTime rolloverDate, Set<String> assignmentKeys)
        throws KPMEBalanceException {

    //fetch calendar entries in this sequence belonging to the current leave year.
    String dateString = TKUtils.formatDate(LocalDate.now());
    List<CalendarEntry> calendarEntries = HrServiceLocator.getCalendarEntryService()
            .getAllCalendarEntriesForCalendarIdAndYear(calendarEntry.getHrCalendarId(),
                    dateString.substring(6, 10));

    //calendar change into a different leave calendar year
    if (rolloverDate != null) {

        //clear all balances.
        clearLeaveBalances();//  w  w  w  .  jav  a2s.  com

        //reset the asOfDate this bucket will go off of, as well as those of the leave balances
        adjustAsOfDates(calendarEntry, calendarEntries);

        //TODO: if in current calendar year, use current date + planning months for extent of fetch.
        List<LeaveBlock> leaveBlocks = LmServiceLocator.getLeaveBlockService().getLeaveBlocksSinceCarryOver(
                principalCalendar.getPrincipalId(),
                LmServiceLocator.getLeaveBlockService().getLastCarryOverBlocks(
                        principalCalendar.getPrincipalId(), rolloverDate.minusDays(1).toLocalDate()),
                rolloverDate.plusDays(365).toLocalDate(), true);

        //retrieve (if any) last carryover blocks given the new asOfDate
        Map<String, LeaveBlock> carryOverBlocks = LmServiceLocator.getLeaveBlockService()
                .getLastCarryOverBlocks(principalCalendar.getPrincipalId(), asOfDate);

        //method taken from leave summary service - map general leave block fetch by accrual category
        Map<String, List<LeaveBlock>> accrualCategoryMappedLeaveBlocks = mapLeaveBlocksByAccrualCategory(
                leaveBlocks);

        //merge carryOverBlock map with accrualCategoryMappedLeaveBlocks.
        for (Entry<String, LeaveBlock> entry : carryOverBlocks.entrySet()) {
            //TODO: modify CarryOverLeaveBalance to identify and make use of CARRY_OVER type leave block
            if (accrualCategoryMappedLeaveBlocks.containsKey(entry.getKey()))
                accrualCategoryMappedLeaveBlocks.get(entry.getKey()).add(entry.getValue());
            else {
                List<LeaveBlock> carryOverList = new ArrayList<LeaveBlock>();
                carryOverList.add(entry.getValue());
                accrualCategoryMappedLeaveBlocks.put(entry.getKey(), carryOverList);
            }

        }
        //add leave blocks, accrual category by accrual category, to this bucket.
        for (Entry<String, List<LeaveBlock>> entry : accrualCategoryMappedLeaveBlocks.entrySet()) {
            for (LeaveBlock leaveBlock : entry.getValue()) {
                try {
                    addLeaveBlock(leaveBlock);
                } catch (KPMEBalanceException e) {
                    InstantiationException ie = new InstantiationException();
                    ie.setStackTrace(e.getStackTrace());
                    ie.printStackTrace();
                }
            }
        }
    } else {
        //Calendar change within the same leave year.

        List<String> assignmentKeyList = new ArrayList<String>();
        assignmentKeyList.addAll(assignmentKeys);

        List<LeaveBlock> leaveBlocks = new ArrayList<LeaveBlock>();

        //determine which leave blocks are affected by the calendar change, remove them, and re-add them under the new asOfDate
        if (calendarEntry.getEndPeriodFullDateTime()
                .isBefore(viewingCalendarEntry.getEndPeriodFullDateTime().getMillis())) {
            //need to remove leave blocks from otherLeaveCalendarDocument begin date to thisLeaveCalendarDocument end date
            leaveBlocks = LmServiceLocator.getLeaveBlockService().getLeaveBlocks(
                    principalCalendar.getPrincipalId(),
                    LocalDate.fromDateFields(calendarEntry.getBeginPeriodDateTime()),
                    LocalDate.fromDateFields(viewingCalendarEntry.getEndPeriodDateTime()));
            //leaveBlocks = LmServiceLocator.getLeaveBlockService().getLeaveBlocksForLeaveCalendar(principalCalendar.getPrincipalId(), LocalDate.fromDateFields(calendarEntry.getBeginPeriodDateTime()), LocalDate.fromDateFields(viewingCalendarEntry.getEndPeriodDateTime()), assignmentKeyList);
        } else {
            //need to remove leave blocks from thisLeaveCalendarDocument begin date to otherLeaveCalendarDocument end date
            leaveBlocks = LmServiceLocator.getLeaveBlockService().getLeaveBlocks(
                    principalCalendar.getPrincipalId(),
                    LocalDate.fromDateFields(viewingCalendarEntry.getBeginPeriodDateTime()),
                    LocalDate.fromDateFields(calendarEntry.getEndPeriodDateTime()));
            //leaveBlocks = LmServiceLocator.getLeaveBlockService().getLeaveBlocksForLeaveCalendar(principalCalendar.getPrincipalId(), LocalDate.fromDateFields(viewingCalendarEntry.getBeginPeriodDateTime()), LocalDate.fromDateFields(calendarEntry.getEndPeriodDateTime()), assignmentKeyList);
        }
        //remove affected leave blocks
        for (LeaveBlock block : leaveBlocks) {
            removeLeaveBlock(block);
        }

        //update this bucket and its leave balances with new relative date information
        LocalDate newAsOfDate = null;
        DateTime currentLeavePlanStartDate = HrServiceLocator.getLeavePlanService()
                .getFirstDayOfLeavePlan(principalCalendar.getLeavePlan(), LocalDate.now());
        if (calendarEntry.getEndPeriodDate().before(currentLeavePlanStartDate.toDate())) {
            //require balances as of the final day of the leave calendar year.
            DateTime calendarEntryLeavePlanRolloverDate = HrServiceLocator.getLeavePlanService()
                    .getRolloverDayOfLeavePlan(principalCalendar.getLeavePlan(),
                            LocalDate.fromDateFields(calendarEntry.getEndPeriodDate()));
            newAsOfDate = LocalDate.fromDateFields(calendarEntryLeavePlanRolloverDate.toDate()).minusDays(1);
        } else {
            Interval interval = new Interval(calendarEntry.getBeginPeriodDateTime().getTime(),
                    calendarEntry.getEndPeriodDateTime().getTime());
            if (interval.contains(LocalDate.now().toDate().getTime())) {
                newAsOfDate = LocalDate.now();
            } else if (calendarEntry.getBeginPeriodDate().before(LocalDate.now().toDate()))
                newAsOfDate = LocalDate.fromDateFields(calendarEntry.getEndPeriodDate()).minusDays(1);
            else // if it's in the calendar interval above, the equals case is taken care of, begin date must be after today
                newAsOfDate = LocalDate.fromDateFields(calendarEntry.getBeginPeriodDate()).minusDays(1);
        }

        asOfDate = newAsOfDate;

        for (Entry<String, List<LeaveBalance>> leaveBalance : leaveBalances.entrySet()) {
            for (LeaveBalance balance : leaveBalance.getValue()) {
                balance.calendarPeriodBeginDate = LocalDate
                        .fromDateFields(calendarEntry.getBeginPeriodDateTime());
                balance.calendarPeriodEndDate = LocalDate.fromDateFields(calendarEntry.getEndPeriodDateTime());
                balance.asOfDate = newAsOfDate;
            }
        }
        //re-add the affected leave blocks under the new date / calendar information
        for (LeaveBlock block : leaveBlocks) {
            addLeaveBlock(block);
        }
    }
}

From source file:org.kuali.kpme.tklm.leave.accrual.service.AccrualServiceImpl.java

License:Educational Community License

@SuppressWarnings("unchecked")
@Override// ww  w  .  ja  va 2  s  .c  o m
public void runAccrual(String principalId, DateTime startDate, DateTime endDate, boolean recordRanData,
        String runAsPrincipalId) {
    List<LeaveBlock> accrualLeaveBlocks = new ArrayList<LeaveBlock>();
    Map<String, BigDecimal> accumulatedAccrualCatToAccrualAmounts = new HashMap<String, BigDecimal>();
    Map<String, BigDecimal> accumulatedAccrualCatToNegativeAccrualAmounts = new HashMap<String, BigDecimal>();

    if (startDate != null && endDate != null) {
        LOG.info("AccrualServiceImpl.runAccrual() STARTED with Principal: " + principalId + " Start: "
                + startDate.toString() + " End: " + endDate.toString());
    }
    if (startDate.isAfter(endDate)) {
        LOG.error("Start Date " + startDate.toString() + " should not be later than End Date "
                + endDate.toString());
        return;
        //         throw new RuntimeException("Start Date " + startDate.toString() + " should not be later than End Date " + endDate.toString());
    }
    //Inactivate all previous accrual-generated entries for this span of time
    deactivateOldAccruals(principalId, startDate, endDate, runAsPrincipalId);

    //Build a rate range aggregate with appropriate information for this period of time detailing Rate Ranges for job
    //entries for this range of time
    RateRangeAggregate rrAggregate = this.buildRateRangeAggregate(principalId, startDate, endDate);
    PrincipalHRAttributes phra = null;
    PrincipalHRAttributes endPhra = null;
    LeavePlan lp = null;
    List<AccrualCategory> accrCatList = null;

    //Iterate over every day in span 
    DateTime currentDate = startDate;
    while (!currentDate.isAfter(endDate)) {
        RateRange currentRange = rrAggregate.getRateOnDate(currentDate);
        if (currentRange == null) {
            currentDate = currentDate.plusDays(1);
            continue;
        }

        phra = currentRange.getPrincipalHRAttributes();
        if (phra == null || currentDate.toLocalDate().isBefore(phra.getServiceLocalDate())) {
            currentDate = currentDate.plusDays(1);
            continue;
        }

        // use the effectiveDate of this principalHRAttribute to search for inactive entries for this principalId
        // If there's an inactive entry, it means the job is going to end on the effectiveDate of the inactive entry
        // used for minimumPercentage and proration
        endPhra = currentRange.getEndPrincipalHRAttributes();
        if (endPhra != null && currentDate.toLocalDate().isAfter(endPhra.getEffectiveLocalDate())) {
            currentDate = currentDate.plusDays(1);
            continue;
        }

        // if the date range is before the service date of this employee, do not calculate accrual
        if (endDate.toLocalDate().isBefore(phra.getServiceLocalDate())) {
            return;
        }
        lp = currentRange.getLeavePlan();
        accrCatList = currentRange.getAcList();
        // if the employee status is changed, create an empty leave block on the currentDate
        if (currentRange.isStatusChanged()) {
            this.createEmptyLeaveBlockForStatusChange(principalId, accrualLeaveBlocks,
                    currentDate.toLocalDate());
        }
        // if no job found for the employee on the currentDate, do nothing
        if (CollectionUtils.isEmpty(currentRange.getJobs())) {
            currentDate = currentDate.plusDays(1);
            continue;
        }

        BigDecimal ftePercentage = currentRange.getAccrualRatePercentageModifier();
        BigDecimal totalOfStandardHours = currentRange.getStandardHours();
        boolean fullFteGranted = false;
        for (AccrualCategory anAC : accrCatList) {
            fullFteGranted = false;
            if (!currentDate.toLocalDate().isBefore(phra.getEffectiveLocalDate())
                    && !anAC.getAccrualEarnInterval().equals("N")) { // "N" means no accrual
                boolean prorationFlag = this.isProrationFlag(anAC.getProration());
                // get the accrual rule 
                AccrualCategoryRule currentAcRule = this.getRuleForAccrualCategory(currentRange.getAcRuleList(),
                        anAC);

                // check if accrual category rule changed
                if (currentAcRule != null) {
                    DateTime ruleStartDate = getRuleStartDate(currentAcRule.getServiceUnitOfTime(),
                            phra.getServiceLocalDate(), currentAcRule.getStart());
                    DateTime previousIntervalDay = this.getPrevIntervalDate(ruleStartDate,
                            anAC.getAccrualEarnInterval(), phra.getPayCalendar(), rrAggregate.getCalEntryMap());
                    DateTime nextIntervalDay = this.getNextIntervalDate(ruleStartDate,
                            anAC.getAccrualEarnInterval(), phra.getPayCalendar(), rrAggregate.getCalEntryMap());

                    RateRange previousRange = rrAggregate.getRateOnDate(previousIntervalDay);
                    AccrualCategoryRule previousAcRule = null;
                    if (previousRange != null) {
                        previousAcRule = this.getRuleForAccrualCategory(previousRange.getAcRuleList(), anAC);
                    }
                    // rule changed
                    if (previousAcRule != null && !previousAcRule.getLmAccrualCategoryRuleId()
                            .equals(currentAcRule.getLmAccrualCategoryRuleId())) {
                        if (currentDate.toLocalDate().compareTo(previousIntervalDay.toLocalDate()) >= 0
                                && currentDate.toLocalDate().compareTo(nextIntervalDay.toLocalDate()) <= 0) {
                            int workDaysInBetween = TKUtils.getWorkDays(ruleStartDate, nextIntervalDay);
                            boolean minReachedFlag = minimumPercentageReachedForPayPeriod(
                                    anAC.getMinPercentWorked(), anAC.getAccrualEarnInterval(),
                                    workDaysInBetween, nextIntervalDay, phra.getPayCalendar(),
                                    rrAggregate.getCalEntryMap());
                            if (prorationFlag) {
                                if (minReachedFlag) {
                                    // min reached, proration=true, rule changed, then use actual work days of currentRule for calculation
                                    // so nothing special needs to be done here                        
                                } else {
                                    //minimum percentage NOT reached, proration = true, rule changed, then use previousRule for the whole pay period
                                    currentAcRule = previousAcRule;
                                }
                            } else {
                                if (minReachedFlag) {
                                    // min reached, proration = false, rule changed, then accrual the whole fte of the new rule for this pay interval
                                    accumulatedAccrualCatToAccrualAmounts.put(anAC.getLmAccrualCategoryId(),
                                            currentAcRule.getAccrualRate());
                                    fullFteGranted = true;
                                } else {
                                    //min NOT reached, proration = false, rule changed, then accrual the whole fte of the previous rule for this pay interval
                                    accumulatedAccrualCatToAccrualAmounts.put(anAC.getLmAccrualCategoryId(),
                                            previousAcRule.getAccrualRate());
                                    fullFteGranted = true;
                                }
                            }
                        }
                    }
                }

                // check for first pay period of principal attributes considering minimum percentage and proration   
                DateTime firstIntervalDate = this.getNextIntervalDate(
                        phra.getEffectiveLocalDate().toDateTimeAtStartOfDay(), anAC.getAccrualEarnInterval(),
                        phra.getPayCalendar(), rrAggregate.getCalEntryMap());
                if (!currentDate.toLocalDate().isBefore(phra.getEffectiveLocalDate())
                        && !currentDate.toLocalDate().isAfter(firstIntervalDate.toLocalDate())) {
                    int workDaysInBetween = TKUtils.getWorkDays(
                            phra.getEffectiveLocalDate().toDateTimeAtStartOfDay(), firstIntervalDate);
                    boolean minReachedFlag = minimumPercentageReachedForPayPeriod(anAC.getMinPercentWorked(),
                            anAC.getAccrualEarnInterval(), workDaysInBetween, firstIntervalDate,
                            phra.getPayCalendar(), rrAggregate.getCalEntryMap());

                    if (prorationFlag) {
                        if (minReachedFlag) {
                            // minimum reached, proration = true, first pay period, then use actual work days of currentRule for calculation
                            // so nothing special needs to be done here
                        } else {
                            // min NOT reached, proration = true, first pay period, then no accrual for this pay period
                            accumulatedAccrualCatToAccrualAmounts.remove(anAC.getLmAccrualCategoryId());
                            accumulatedAccrualCatToNegativeAccrualAmounts.remove(anAC.getLmAccrualCategoryId());
                            continue;
                        }
                    } else {
                        if (minReachedFlag) {
                            //  minimum reached, proration = false, first pay period, then accrual the whole fte of current AC rule for this pay interval
                            accumulatedAccrualCatToAccrualAmounts.put(anAC.getLmAccrualCategoryId(),
                                    currentAcRule.getAccrualRate());
                            fullFteGranted = true;
                        } else {
                            // min NOT reached, proration = false, first pay period, then no accrual for this pay period
                            accumulatedAccrualCatToAccrualAmounts.remove(anAC.getLmAccrualCategoryId());
                            accumulatedAccrualCatToNegativeAccrualAmounts.remove(anAC.getLmAccrualCategoryId());
                            continue;
                        }
                    }
                }
                // last accrual interval
                if (endPhra != null) { // the employment is going to end on the effectiveDate of enPhra
                    DateTime previousIntervalDate = this.getPrevIntervalDate(
                            endPhra.getEffectiveLocalDate().toDateTimeAtStartOfDay(),
                            anAC.getAccrualEarnInterval(), phra.getPayCalendar(), rrAggregate.getCalEntryMap());
                    // currentDate is between the end date and the last interval date, so we are in the last interval
                    if (!currentDate.toLocalDate().isAfter(endPhra.getEffectiveLocalDate())
                            && currentDate.toLocalDate().isAfter(previousIntervalDate.toLocalDate())) {
                        DateTime lastIntervalDate = this.getNextIntervalDate(
                                endPhra.getEffectiveLocalDate().toDateTimeAtStartOfDay(),
                                anAC.getAccrualEarnInterval(), phra.getPayCalendar(),
                                rrAggregate.getCalEntryMap());
                        int workDaysInBetween = TKUtils.getWorkDays(previousIntervalDate,
                                endPhra.getEffectiveLocalDate().toDateTimeAtStartOfDay());
                        boolean minReachedFlag = minimumPercentageReachedForPayPeriod(
                                anAC.getMinPercentWorked(), anAC.getAccrualEarnInterval(), workDaysInBetween,
                                lastIntervalDate, phra.getPayCalendar(), rrAggregate.getCalEntryMap());
                        if (prorationFlag) {
                            if (minReachedFlag) {
                                // minimum reached, proration = true, first pay period, then use actual work days of currentRule for calculation
                                // so nothing special needs to be done here
                            } else {
                                // min NOT reached, proration = true, first pay period, then no accrual for this pay period
                                accumulatedAccrualCatToAccrualAmounts.remove(anAC.getLmAccrualCategoryId());
                                accumulatedAccrualCatToNegativeAccrualAmounts
                                        .remove(anAC.getLmAccrualCategoryId());
                                continue;
                            }
                        } else {
                            if (minReachedFlag) {
                                //  minimum reached, proration = false, first pay period, then accrual the whole fte of current AC rule for this pay interval
                                accumulatedAccrualCatToAccrualAmounts.put(anAC.getLmAccrualCategoryId(),
                                        currentAcRule.getAccrualRate());
                                fullFteGranted = true;
                            } else {
                                // min NOT reached, proration = false, first pay period, then no accrual for this pay period
                                accumulatedAccrualCatToAccrualAmounts.remove(anAC.getLmAccrualCategoryId());
                                accumulatedAccrualCatToNegativeAccrualAmounts
                                        .remove(anAC.getLmAccrualCategoryId());
                                continue;
                            }
                        }
                    }
                }

                if (currentAcRule == null) {
                    accumulatedAccrualCatToAccrualAmounts.remove(anAC.getLmAccrualCategoryId());
                    accumulatedAccrualCatToNegativeAccrualAmounts.remove(anAC.getLmAccrualCategoryId());
                    continue;
                }

                // only accrual on work days
                if (!TKUtils.isWeekend(currentDate) && !fullFteGranted) {
                    BigDecimal accrualRate = currentAcRule.getAccrualRate();
                    int numberOfWorkDays = this.getWorkDaysInInterval(currentDate,
                            anAC.getAccrualEarnInterval(), phra.getPayCalendar(), rrAggregate.getCalEntryMap());
                    BigDecimal dayRate = numberOfWorkDays > 0
                            ? accrualRate.divide(new BigDecimal(numberOfWorkDays), 6, BigDecimal.ROUND_HALF_UP)
                            : new BigDecimal(0);
                    //Fetch the accural rate based on rate range for today(Rate range is the accumulated list of jobs and accrual rate for today)
                    //Add to total accumulatedAccrualCatToAccrualAmounts
                    //use rule and ftePercentage to calculate the hours                  
                    this.calculateHours(anAC.getLmAccrualCategoryId(), ftePercentage, dayRate,
                            accumulatedAccrualCatToAccrualAmounts);

                    //get not eligible for accrual hours based on leave block on this day
                    BigDecimal noAccrualHours = getNotEligibleForAccrualHours(principalId,
                            currentDate.toLocalDate());

                    if (noAccrualHours != null && noAccrualHours.compareTo(BigDecimal.ZERO) != 0
                            && totalOfStandardHours.compareTo(BigDecimal.ZERO) != 0) {
                        BigDecimal dayHours = totalOfStandardHours.divide(new BigDecimal(5), 6,
                                BigDecimal.ROUND_HALF_UP);
                        BigDecimal noAccrualRate = dayRate.multiply(noAccrualHours.divide(dayHours));
                        this.calculateHours(anAC.getLmAccrualCategoryId(), ftePercentage, noAccrualRate,
                                accumulatedAccrualCatToNegativeAccrualAmounts);
                    }
                }
                //Determine if we are at the accrual earn interval in the span, if so add leave block for accumulated accrual amount to list
                //and reset accumulatedAccrualCatToAccrualAmounts and accumulatedAccrualCatToNegativeAccrualAmounts for this accrual category
                if (this.isDateAnIntervalDate(currentDate.toLocalDate(), anAC.getAccrualEarnInterval(),
                        phra.getPayCalendar(), rrAggregate.getCalEntryMap())) {
                    BigDecimal acHours = accumulatedAccrualCatToAccrualAmounts
                            .get(anAC.getLmAccrualCategoryId());

                    if (acHours != null) {
                        createLeaveBlock(principalId, accrualLeaveBlocks, currentDate.toLocalDate(), acHours,
                                anAC, null, true, currentRange.getLeaveCalendarDocumentId());
                        accumulatedAccrualCatToAccrualAmounts.remove(anAC.getLmAccrualCategoryId()); // reset accumulatedAccrualCatToAccrualAmounts
                        fullFteGranted = false;
                    }

                    BigDecimal adjustmentHours = accumulatedAccrualCatToNegativeAccrualAmounts
                            .get(anAC.getLmAccrualCategoryId());
                    if (adjustmentHours != null && adjustmentHours.compareTo(BigDecimal.ZERO) != 0) {
                        // do not create leave block if the ajustment amount is 0
                        createLeaveBlock(principalId, accrualLeaveBlocks, currentDate.toLocalDate(),
                                adjustmentHours, anAC, null, false, currentRange.getLeaveCalendarDocumentId());
                        accumulatedAccrualCatToNegativeAccrualAmounts.remove(anAC.getLmAccrualCategoryId()); // reset accumulatedAccrualCatToNegativeAccrualAmounts
                    }
                }
            }
        }
        //Determine if today is a system scheduled time off and accrue holiday if so.
        SystemScheduledTimeOff ssto = currentRange.getSysScheTimeOff();
        if (ssto != null) {
            AccrualCategory anAC = HrServiceLocator.getAccrualCategoryService()
                    .getAccrualCategory(ssto.getAccrualCategory(), ssto.getEffectiveLocalDate());
            if (anAC == null) {
                LOG.error("Cannot find Accrual Category for system scheduled time off "
                        + ssto.getLmSystemScheduledTimeOffId());
                return;
                //               throw new RuntimeException("Cannot find Accrual Category for system scheduled time off " + ssto.getLmSystemScheduledTimeOffId());
            }
            BigDecimal hrs = ssto.getAmountofTime().multiply(ftePercentage);
            // system scheduled time off leave block
            createLeaveBlock(principalId, accrualLeaveBlocks, currentDate.toLocalDate(), hrs, anAC,
                    ssto.getLmSystemScheduledTimeOffId(), true, currentRange.getLeaveCalendarDocumentId());
            // usage leave block with negative amount
            createLeaveBlock(principalId, accrualLeaveBlocks, currentDate.toLocalDate(), hrs.negate(), anAC,
                    ssto.getLmSystemScheduledTimeOffId(), true, currentRange.getLeaveCalendarDocumentId());
        }
        // if today is the last day of the employment, create leave blocks if there's any hours available
        if (endPhra != null && currentDate.toLocalDate().equals(endPhra.getEffectiveLocalDate())) {
            // accumulated accrual amount
            if (!accumulatedAccrualCatToAccrualAmounts.isEmpty()) {
                for (Map.Entry<String, BigDecimal> entry : accumulatedAccrualCatToAccrualAmounts.entrySet()) {
                    if (entry.getValue() != null && entry.getValue().compareTo(BigDecimal.ZERO) != 0) {
                        AccrualCategory anAC = HrServiceLocator.getAccrualCategoryService()
                                .getAccrualCategory(entry.getKey());
                        createLeaveBlock(principalId, accrualLeaveBlocks, currentDate.toLocalDate(),
                                entry.getValue(), anAC, null, true, currentRange.getLeaveCalendarDocumentId());
                    }
                }
                accumulatedAccrualCatToAccrualAmounts = new HashMap<String, BigDecimal>(); // reset accumulatedAccrualCatToAccrualAmounts
            }
            // negative/adjustment accrual amount
            if (!accumulatedAccrualCatToNegativeAccrualAmounts.isEmpty()) {
                for (Map.Entry<String, BigDecimal> entry : accumulatedAccrualCatToNegativeAccrualAmounts
                        .entrySet()) {
                    if (entry.getValue() != null && entry.getValue().compareTo(BigDecimal.ZERO) != 0) {
                        AccrualCategory anAC = HrServiceLocator.getAccrualCategoryService()
                                .getAccrualCategory(entry.getKey());
                        createLeaveBlock(principalId, accrualLeaveBlocks, currentDate.toLocalDate(),
                                entry.getValue(), anAC, null, true, currentRange.getLeaveCalendarDocumentId());
                    }
                }
                accumulatedAccrualCatToNegativeAccrualAmounts = new HashMap<String, BigDecimal>(); // reset accumulatedAccrualCatToNegativeAccrualAmounts
            }
            phra = null; // reset principal attribute so new value will be retrieved
            endPhra = null; // reset end principal attribute so new value will be retrieved
        }

        currentDate = currentDate.plusDays(1);
    }

    //Save accrual leave blocks at the very end
    LmServiceLocator.getLeaveBlockService().saveLeaveBlocks(accrualLeaveBlocks);

    // record timestamp of this accrual run in database
    if (recordRanData) {
        LmServiceLocator.getPrincipalAccrualRanService().updatePrincipalAccrualRanInfo(principalId);
    }

}