TimeOfDay lunchEnd = wsType.getMeal().getLunchEnd(); TimeInterval lunchTime = new TimeInterval(wsType.getMeal() .getBeginMealBreak(), lunchEnd, false);  if (lunchTime.contains(firstClockingDate, false)) { workPeriod = workPeriod.minus(new TimeInterval(firstClockingDate, lunchEnd, false).getDurationMillis());
if (lunchDuration.isShorterThan(wsType.getMeal().getMandatoryMealDiscount())) { workPeriod = workPeriod.minus(wsType.getMeal() .getMandatoryMealDiscount().minus(lunchDuration));
    public WorkDaySheet calculateWorkingPeriods(WorkDaySheet workDaySheet, YearMonthDay day,            Timeline timeline, List<Leave> timeLeaves) {        Duration firstWorkPeriod = Duration.ZERO;        Duration lastWorkPeriod = Duration.ZERO;        TimeInterval mealInterval = null;        WorkScheduleType wsType = getWorkScheduleType();        TimePoint firstWorkTimePoint = timeline.getFirstWorkTimePoint();        TimePoint lastWorkTimePoint = timeline.getLastWorkTimePoint();        TimeOfDay firstClockingDate = firstWorkTimePoint.getTime();        TimeOfDay lastClockingDate = lastWorkTimePoint.getTime();        if (wsType.definedMeal()) {            mealInterval = timeline.calculateMealBreakInterval(wsType.getMeal().getMealBreak());            if (mealInterval != null) {                Duration lunchDiscount = wsType.checkMealDurationAccordingToRules(mealInterval,                        justificationInMealBreak(timeLeaves), timeline, firstWorkTimePoint);                if (lunchDiscount != null) {                    firstWorkPeriod = timeline.calculateWorkPeriodDuration(new TimePoint(mealInterval                            .getStartTime(), false, null), null, new TimePoint(getWorkScheduleType()                            .getClockingTime(), AttributeType.NULL), new TimePoint(getWorkScheduleType()                            .getClockingEndTime(), getWorkScheduleType().isClokingTimeNextDay(),                            AttributeType.NULL), wsType.getMaximumContinuousWorkPeriod());                    if (((WorkPeriod) wsType.getNormalWorkPeriod()).isSecondWorkPeriodDefined()) {                        lastWorkPeriod = timeline                                .calculateWorkPeriodDuration(null, new TimePoint(mealInterval                                        .getEndTime(), false, null), new TimePoint(getWorkScheduleType()                                        .getClockingTime(), AttributeType.NULL),                                        new TimePoint(getWorkScheduleType().getClockingEndTime(),                                                getWorkScheduleType().isClokingTimeNextDay(),                                                AttributeType.NULL), wsType                                                .getMaximumContinuousWorkPeriod());                    }                    workDaySheet.setUnjustifiedTime(wsType.calculateFixedPeriodDuration(timeline));                    workDaySheet.setBalanceTime(subtractDurationsWithoutSeconds(                            firstWorkPeriod.plus(lastWorkPeriod).minus(lunchDiscount),                            getWorkScheduleType().getNormalWorkPeriod().getWorkPeriodDuration())                            .toPeriod());                } else {                    workDaySheet.addNote("IRREG");                    workDaySheet.setBalanceTime(Duration.ZERO.minus(                            wsType.getNormalWorkPeriod().getWorkPeriodDuration()).toPeriod());                    if (wsType.getFixedWorkPeriod() != null) {                        workDaySheet.setUnjustifiedTime(wsType.getFixedWorkPeriod()                                .getWorkPeriodDuration());                    }                }            } else { // o funcionario nao foi almocar so fez 1 periodo de trabalho                Duration workPeriod = timeline.calculateWorkPeriodDuration(null, timeline                        .getTimePoints().iterator().next(), new TimePoint(getWorkScheduleType()                        .getClockingTime(), AttributeType.NULL), new TimePoint(getWorkScheduleType()                        .getClockingEndTime(), getWorkScheduleType().isClokingTimeNextDay(),                        AttributeType.NULL), wsType.getMaximumContinuousWorkPeriod());                if (workPeriod.equals(Duration.ZERO)) {                    workDaySheet.setUnjustifiedTime(wsType.calculateFixedPeriodDuration(timeline));                    workDaySheet.setBalanceTime(subtractDurationsWithoutSeconds(workPeriod,                            getWorkScheduleType().getNormalWorkPeriod().getWorkPeriodDuration())                            .toPeriod());                } else if (wsType.getMeal().getMinimumMealBreakInterval().isEqual(Duration.ZERO)) {                    // caso dos horarios de isencao de horario                    if (firstClockingDate != null                            && wsType.getMeal().getMealBreak().contains(firstClockingDate, false)) {                        // funcionario entrou no intervalo de almoco                        // considera-se o periodo desde o inicio do intervalo de almoco + desconto                        // obrigatorio de almoco                        // se funcionario entrar nesse periodo de tempo e'-lhe descontado desde a entrada                        // ate' (inicio do intervalo de almoco + desconto obrigatorio de almoco)                        TimeOfDay lunchEnd = wsType.getMeal().getLunchEnd();                        TimeInterval lunchTime = new TimeInterval(wsType.getMeal().getBeginMealBreak(),                                lunchEnd, false);                        if (lunchTime.contains(firstClockingDate, false)                                && !workPeriod.isEqual(Duration.ZERO)) {                            workPeriod = workPeriod.minus(new TimeInterval(firstClockingDate, lunchEnd,                                    false).getDurationMillis());                        }                    } else if (firstClockingDate != null                            && firstClockingDate.isBefore(wsType.getMeal().getBeginMealBreak())) {                        if (lastClockingDate != null                                && (timeline.getLastWorkTimePoint().isNextDay()                                        || lastClockingDate                                                .isAfter(wsType.getMeal().getBeginMealBreak()) || lastClockingDate                                        .isEqual(wsType.getMeal().getBeginMealBreak()))) {                            if (wsType.getMeal().getEndOfMealBreakMinusDiscountInterval().contains(                                    lastClockingDate, timeline.getLastWorkTimePoint().isNextDay())) {                                // descontar periodo de tempo desde fim da refeicao menos periodo                                // obrigatorio de refeicao ate' 'a ultima marcacao do funcionario                                workPeriod = workPeriod.minus((new TimeInterval(wsType.getMeal()                                        .getEndOfMealBreakMinusMealDiscount(), lastClockingDate, false))                                        .getDurationMillis());                            } else if (timeline.getLastWorkTimePoint().isNextDay()                                    || lastClockingDate.isAfter(wsType.getMeal().getEndMealBreak())) {                                workPeriod = workPeriod.minus(wsType.getMeal()                                        .getMandatoryMealDiscount());                            }                        }                    }                    workDaySheet.setBalanceTime(subtractDurationsWithoutSeconds(workPeriod,                            getWorkScheduleType().getNormalWorkPeriod().getWorkPeriodDuration())                            .toPeriod());                } else { // caso dos horarios em q o minimo de intervalo de almoco e' tipicamente de                    // 15minutos                    if (firstClockingDate != null) {                        if (wsType.getMeal().getMealBreak().contains(firstClockingDate, false)) {                            // funcionario entrou no intervalo de almoco                            // considera-se o periodo desde o inicio do intervalo de almoco + desconto                            // obrigatorio de almoco                            // se funcionario entrar nesse periodo de tempo e'-lhe descontado desde a                            // entrada                            // ate' (inicio do intervalo de almoco + desconto obrigatorio de almoco)                            TimeOfDay lunchEnd = wsType.getMeal().getLunchEnd();                            TimeInterval lunchTime = new TimeInterval(wsType.getMeal()                                    .getBeginMealBreak(), lunchEnd, false);                            if (lunchTime.contains(firstClockingDate, false)) {                                workPeriod = workPeriod.minus(new TimeInterval(firstClockingDate,                                        lunchEnd, false).getDurationMillis());                            }                            // calcular o periodo fixo                            workDaySheet.setUnjustifiedTime(wsType                                    .calculateFixedPeriodDuration(timeline));                            workDaySheet.setBalanceTime(subtractDurationsWithoutSeconds(workPeriod,                                    getWorkScheduleType().getNormalWorkPeriod().getWorkPeriodDuration())                                    .toPeriod());                            // primeiro clocking e' antes do periodo de almoco;                            // ver se o ultimo clocking e' depois do periodo de almoco                        } else if (lastClockingDate != null                                && (!wsType.getMeal().getMealBreak().contains(lastClockingDate, false))) {                            if (justificationInMealBreak(timeLeaves)) {                                workPeriod = workPeriod.minus(wsType.getMeal()                                        .getMandatoryMealDiscount());                                workDaySheet.setBalanceTime(subtractDurationsWithoutSeconds(                                        workPeriod,                                        getWorkScheduleType().getNormalWorkPeriod()                                                .getWorkPeriodDuration()).toPeriod());                                workDaySheet.setUnjustifiedTime(wsType                                        .calculateFixedPeriodDuration(timeline));                            } else {                                if (firstClockingDate.isBefore(wsType.getMeal().getBeginMealBreak())                                        && new TimePoint(wsType.getMeal().getEndMealBreak(),                                                (Attributes) null).isBefore(lastWorkTimePoint)) {                                    workDaySheet.addNote("IRREG");                                    workDaySheet.setBalanceTime(Duration.ZERO.minus(                                            wsType.getNormalWorkPeriod().getWorkPeriodDuration())                                            .toPeriod());                                    if (wsType.getFixedWorkPeriod() != null) {                                        workDaySheet.setUnjustifiedTime(wsType.getFixedWorkPeriod()                                                .getWorkPeriodDuration());                                    }                                } else {                                    workDaySheet.setBalanceTime(subtractDurationsWithoutSeconds(                                            workPeriod,                                            getWorkScheduleType().getNormalWorkPeriod()                                                    .getWorkPeriodDuration()).toPeriod());                                    if (wsType.getFixedWorkPeriod() != null) {                                        workDaySheet.setUnjustifiedTime(wsType                                                .calculateFixedPeriodDuration(timeline));                                    }                                }                            }                        } else {                            // ver se e' dentro do final do intervalo de almoco menos o desconto                            // obrigatorio                            if (wsType.getMeal().getEndOfMealBreakMinusDiscountInterval().contains(                                    lastClockingDate, false)) {                                // descontar periodo de tempo desde fim da refeicao menos periodo                                // obrigatorio de refeicao ate' 'a ultima marcacao do funcionario                                workPeriod = workPeriod.minus((new TimeInterval(wsType.getMeal()                                        .getEndOfMealBreakMinusMealDiscount(), lastClockingDate, false))                                        .getDurationMillis());                            }                            workDaySheet.setBalanceTime(subtractDurationsWithoutSeconds(workPeriod,                                    getWorkScheduleType().getNormalWorkPeriod().getWorkPeriodDuration())                                    .toPeriod());                            workDaySheet.setUnjustifiedTime(wsType                                    .calculateFixedPeriodDuration(timeline));                        }                    }                }            }        } else { // meal nao esta definida - so ha 1 periodo de trabalho            Duration worked = timeline.calculateWorkPeriodDuration(null, timeline.getTimePoints()                    .iterator().next(), new TimePoint(getWorkScheduleType().getClockingTime(),                    AttributeType.NULL), new TimePoint(getWorkScheduleType().getClockingEndTime(),                    getWorkScheduleType().isClokingTimeNextDay(), AttributeType.NULL), wsType                    .getMaximumContinuousWorkPeriod());            workDaySheet.setBalanceTime(subtractDurationsWithoutSeconds(worked,                    getWorkScheduleType().getNormalWorkPeriod().getWorkPeriodDuration()).toPeriod());            workDaySheet.setUnjustifiedTime(wsType.calculateFixedPeriodDuration(timeline));        }        return workDaySheet;    }