Package org.libreplan.business.test.workingday

Source Code of org.libreplan.business.test.workingday.IntraDayDateTest

/*
* This file is part of LibrePlan
*
* Copyright (C) 2009-2010 Fundación para o Fomento da Calidade Industrial e
*                         Desenvolvemento Tecnolóxico de Galicia
* Copyright (C) 2010-2012 Igalia, S.L.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/
package org.libreplan.business.test.workingday;

import static org.hamcrest.CoreMatchers.equalTo;
import static org.hamcrest.CoreMatchers.not;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
import static org.libreplan.business.workingday.EffortDuration.hours;
import static org.libreplan.business.workingday.EffortDuration.minutes;
import static org.libreplan.business.workingday.EffortDuration.zero;

import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import org.hamcrest.BaseMatcher;
import org.hamcrest.Description;
import org.hamcrest.Matcher;
import org.joda.time.DateTime;
import org.joda.time.LocalDate;
import org.junit.Test;
import org.libreplan.business.workingday.EffortDuration;
import org.libreplan.business.workingday.EffortDuration.Granularity;
import org.libreplan.business.workingday.IntraDayDate;
import org.libreplan.business.workingday.IntraDayDate.PartialDay;
import org.libreplan.business.workingday.IntraDayDate.UntilEnd;
import org.libreplan.business.workingday.ResourcesPerDay;

/**
* @author Óscar González Fernández
* @author Manuel Rego Casasnovas <rego@igalia.com>
*/
public class IntraDayDateTest {

    private LocalDate today = new LocalDate();
    private LocalDate tomorrow = today.plusDays(1);
    private EffortDuration oneHour = EffortDuration.hours(1);
    private EffortDuration halfHour = EffortDuration.minutes(30);

    @Test(expected = IllegalArgumentException.class)
    public void needsANotNullDuration() {
        IntraDayDate.create(new LocalDate(), null);
    }

    @Test(expected = IllegalArgumentException.class)
    public void needsANotNullDate() {
        IntraDayDate.create(null, EffortDuration.elapsing(1, Granularity.HOURS));
    }

    @Test
    public void equalsAndHashCodeWorkOk() {
        LocalDate today = new LocalDate();
        LocalDate tomorrow = today.plusDays(1);
        EffortDuration oneHour = EffortDuration.hours(1);
        EffortDuration halfHour = EffortDuration.minutes(30);
        assertEquals(IntraDayDate.create(today, halfHour),
                IntraDayDate.create(tomorrow.minusDays(1), halfHour));
        assertEquals(IntraDayDate.create(today, halfHour).hashCode(), IntraDayDate
                .create(tomorrow.minusDays(1), halfHour).hashCode());
        assertThat(IntraDayDate.create(today, halfHour),
                not(equalTo(IntraDayDate.create(today, oneHour))));
    }

    @Test
    public void canKnowIfAreSameDay() {
        assertTrue(IntraDayDate.create(today, halfHour).areSameDay(today));
        assertTrue(IntraDayDate.create(today, oneHour).areSameDay(today));
        assertFalse(IntraDayDate.create(today, halfHour).areSameDay(tomorrow));
        assertFalse(IntraDayDate.create(tomorrow, halfHour).areSameDay(today));
    }

    @Test
    public void canGetDateTimeAtStartOfDay() {
        DateTime dateTime = IntraDayDate.create(today, halfHour)
                .toDateTimeAtStartOfDay();
        assertThat(dateTime, equalTo(today.toDateTimeAtStartOfDay()));
    }

    @Test
    public void implementsComparable() {
        assertTrue(Comparable.class.isAssignableFrom(IntraDayDate.class));
        assertTrue(IntraDayDate.create(today, halfHour).compareTo(
                IntraDayDate.create(today, oneHour)) < 0);
        assertTrue(IntraDayDate.create(today, oneHour).compareTo(
                IntraDayDate.create(tomorrow, halfHour)) < 0);
    }

    @Test
    public void hasMaxAndMinMethods() {
        IntraDayDate a = IntraDayDate.create(today, halfHour);
        IntraDayDate b = IntraDayDate.create(today, oneHour);
        assertThat(IntraDayDate.min(a, b), equalTo(a));
        assertThat(IntraDayDate.max(a, b), equalTo(b));
    }

    @Test
    public void untilTheSameDayReturnsZeroPartialDays() {
        Iterable<PartialDay> days = IntraDayDate.create(today, zero())
                .daysUntil(IntraDayDate.create(today, zero()));
        assertFalse(days.iterator().hasNext());
    }

    @Test
    public void untilTheNextDayReturnsOnePartialDay() {
        IntraDayDate start = IntraDayDate.create(today, zero());
        IntraDayDate end = IntraDayDate.create(tomorrow, zero());
        Iterable<PartialDay> days = start.daysUntil(end);
        assertThat(IntraDayDate.toList(days), delimitedBy(start, end));
    }

    @Test(expected = IllegalArgumentException.class)
    public void untilADayAgo() {
        IntraDayDate start = IntraDayDate.create(today, zero());
        IntraDayDate end = IntraDayDate.create(tomorrow, zero());
        end.daysUntil(start);
    }

    @Test
    public void untilTwoDaysLaterReturnsTwoPartialDays() {
        IntraDayDate start = IntraDayDate.create(today, zero());
        IntraDayDate middle = IntraDayDate.create(today.plusDays(1), zero());
        IntraDayDate end = IntraDayDate.create(today.plusDays(2), zero());
        Iterable<PartialDay> days = start.daysUntil(end);
        assertThat(IntraDayDate.toList(days), delimitedBy(start, middle, end));
    }

    @Test
    public void canNowTheNumberOfDaysBetweenTwoDates() {
        IntraDayDate start = IntraDayDate.create(today, zero());
        IntraDayDate end = IntraDayDate.create(today.plusDays(1), zero());
        assertThat(start.numberOfDaysUntil(end), equalTo(1));
        assertThat(
                start.numberOfDaysUntil(IntraDayDate.create(today, hours(8))),
                equalTo(0));
        assertThat(
                IntraDayDate.create(today, hours(4)).numberOfDaysUntil(
                        IntraDayDate.create(tomorrow, hours(3))), equalTo(0));
        assertThat(
                IntraDayDate.create(today, hours(4)).numberOfDaysUntil(
                        IntraDayDate.create(tomorrow, hours(4))), equalTo(1));
        assertThat(
                IntraDayDate.create(today, hours(4)).numberOfDaysUntil(
                        IntraDayDate.create(tomorrow, hours(5))), equalTo(1));
        assertThat(
                IntraDayDate.create(today, hours(4)).numberOfDaysUntil(
                        IntraDayDate.create(tomorrow.plusDays(1), hours(3))),
                equalTo(1));
    }

    @Test(expected = IllegalArgumentException.class)
    public void theEndMustBeEqualOrBiggerThanTheStart() {
        IntraDayDate start = IntraDayDate.create(today, zero());
        IntraDayDate end = IntraDayDate.create(today.plusDays(1), zero());
        assertThat(end.numberOfDaysUntil(start), equalTo(1));
    }

    public void theEndCanBeTheSameAsTheStart() {
        IntraDayDate start = IntraDayDate.create(today, zero());
        assertThat(start.numberOfDaysUntil(start), equalTo(0));
    }

    @Test
    public void worksWellWithEffortDurationsNotZero() {
        IntraDayDate start = IntraDayDate.create(today, halfHour);
        IntraDayDate end = IntraDayDate.create(today, oneHour);
        IntraDayDate anotherEnd = IntraDayDate.create(tomorrow, halfHour);
        assertThat(IntraDayDate.toList(start.daysUntil(end)), delimitedBy(start, end));
        assertThat(IntraDayDate.toList(start.daysUntil(anotherEnd)),
                delimitedBy(start, IntraDayDate.create(tomorrow, zero()),
                        anotherEnd));
    }

    @Test
    public void canHaveAnExtraCondition() {
        IntraDayDate start = IntraDayDate.create(today, zero());
        IntraDayDate end = IntraDayDate.create(today.plusDays(10), zero());
        final List<PartialDay> generated = new ArrayList<IntraDayDate.PartialDay>();
        Iterable<PartialDay> days = start.daysUntil(new UntilEnd(end) {
            @Override
            protected boolean hasNext(boolean lessThanEnd) {
                return lessThanEnd && generated.size() < 2;
            }
        });
        for (PartialDay each : days) {
            generated.add(each);
        }
        assertThat(generated.size(), equalTo(2));
    }

    @Test
    public void aPartialDayCanLimitAWorkingDayDuration() {
        PartialDay day = new PartialDay(IntraDayDate.create(today,
                halfHour), IntraDayDate.create(today, oneHour));
        assertThat(day.limitWorkingDay(hours(10)), equalTo(minutes(30)));
        assertThat(day.limitWorkingDay(minutes(40)), equalTo(minutes(10)));
        PartialDay completeDay = new PartialDay(IntraDayDate.startOfDay(today),
                IntraDayDate.startOfDay(tomorrow));
        assertThat(completeDay.limitWorkingDay(hours(10)), equalTo(hours(10)));
        PartialDay startsInTheMiddle = new PartialDay(IntraDayDate.create(
                today, EffortDuration.hours(3)),
                IntraDayDate.startOfDay(tomorrow));
        assertThat(startsInTheMiddle.limitWorkingDay(hours(10)),
                equalTo(hours(7)));
        assertThat(startsInTheMiddle.limitWorkingDay(hours(3)), equalTo(zero()));
        assertThat(startsInTheMiddle.limitWorkingDay(hours(2)), equalTo(zero()));
        PartialDay startAndEndInSameDay = new PartialDay(IntraDayDate.create(
                today, EffortDuration.hours(3)), IntraDayDate.create(today,
                EffortDuration.hours(6)));
        assertThat(startAndEndInSameDay.limitWorkingDay(hours(4)),
                equalTo(hours(1)));
        assertThat(startAndEndInSameDay.limitWorkingDay(hours(5)),
                equalTo(hours(2)));
        assertThat(startAndEndInSameDay.limitWorkingDay(hours(6)),
                equalTo(hours(3)));
        assertThat(startAndEndInSameDay.limitWorkingDay(hours(10)),
                equalTo(hours(3)));
    }

    private Matcher<Iterable<PartialDay>> delimitedBy(
            final IntraDayDate... dates) {
        return new BaseMatcher<Iterable<PartialDay>>() {

            @Override
            public boolean matches(Object param) {
                List<IntraDayDate> list = toPoints(param);
                return list.equals(Arrays.asList(dates));
            }

            @SuppressWarnings("unchecked")
            private List<IntraDayDate> toPoints(Object param) {
                return toPoints((Iterable<PartialDay>) param);
            }

            private List<IntraDayDate> toPoints(Iterable<PartialDay> param) {
                List<IntraDayDate> result = new ArrayList<IntraDayDate>();
                PartialDay last = null;
                for (PartialDay each : param) {
                    result.add(each.getStart());
                    last = each;
                }
                if (last != null) {
                    result.add(last.getEnd());
                }
                return result;
            }

            @Override
            public void describeTo(Description description) {
                description.appendText(Arrays.asList(group(dates))
                        .toString());
            }

            private Object group(IntraDayDate[] dates) {
                List<Object> result = new ArrayList<Object>();
                for (int i = 0; i < dates.length - 1; i++) {
                    result.add(Arrays.asList(dates[i], dates[i + 1]));
                }
                return result;
            }
        };
    }

    @Test
    public void roundsUpGoesToTheNextLocalDateOrKeepsTheSame() {
        assertThat(IntraDayDate.create(today, halfHour).roundUp(),
                equalTo(today.plusDays(1)));

        assertThat(IntraDayDate.startOfDay(today).roundUp(), equalTo(today));
    }

    @Test
    public void roundDownGoesToPreviousLocalDateOrKeepsTheSame() {
        assertThat(IntraDayDate.create(today, halfHour).roundDown(),
                equalTo(today));

        assertThat(IntraDayDate.startOfDay(today).roundDown(), equalTo(today));
    }

    @Test
    public void canIncreaseAnIntraDayDayBySomeEffort() {
        LocalDate today = new LocalDate();
        IntraDayDate intraDate = IntraDayDate.create(today, hours(2));
        EffortDuration[] efforts = { hours(4), hours(8), hours(12), hours(0),
                hours(16) };
        for (EffortDuration effort : efforts) {
            IntraDayDate newDay = intraDate.increaseBy(
                    ResourcesPerDay.amount(1), effort);

            assertThat(newDay.getDate(), equalTo(today));
            assertThat(newDay.getEffortDuration(), equalTo(hours(2)
                    .plus(effort)));
        }
    }

    @Test
    public void theAmountOfTheIncreaseDependsOnTheAmountOfResourcesPerDay() {
        LocalDate today = new LocalDate();
        IntraDayDate intraDate = IntraDayDate.startOfDay(today);

        EffortDuration effort = hours(6);

        ResourcesPerDay half = ResourcesPerDay.amount(new BigDecimal(BigInteger
                .valueOf(5), 1));
        ResourcesPerDay oneQuarter = ResourcesPerDay.amount(new BigDecimal(
                BigInteger.valueOf(25), 2));
        ResourcesPerDay[] resourcesPerDays = { ResourcesPerDay.amount(2),
                ResourcesPerDay.amount(3), half, oneQuarter,
                ResourcesPerDay.amount(4) };

        EffortDuration[] ends = { hours(3), hours(2), hours(12), hours(24),
                hours(1).and(30, Granularity.MINUTES) };

        for (int i = 0; i < resourcesPerDays.length; i++) {
            ResourcesPerDay r = resourcesPerDays[i];
            EffortDuration end = ends[i];
            IntraDayDate newDay = intraDate.increaseBy(r, effort);

            assertThat(newDay.getDate(), equalTo(today));
            assertThat(newDay.getEffortDuration(), equalTo(end));
        }
    }

    @Test
    public void canDecreaseAnIntraDayBySomeEffort() {
        LocalDate today = new LocalDate();
        IntraDayDate intraDate = IntraDayDate.create(today, hours(10));
        EffortDuration[] efforts = { hours(4), hours(8), hours(5), hours(10),
                hours(1) };
        for (EffortDuration effort : efforts) {
            IntraDayDate newDay = intraDate.decreaseBy(
                    ResourcesPerDay.amount(1), effort);

            assertThat(newDay.getDate(), equalTo(today));
            assertThat(newDay.getEffortDuration(),
                    equalTo(hours(10).minus(effort)));
        }
    }

    @Test
    public void theDateAlwaysKeepsBeingTheSameWhenDecreasing() {
        LocalDate today = new LocalDate();
        IntraDayDate intraDate = IntraDayDate.create(today, hours(10));
        assertThat(intraDate.decreaseBy(ResourcesPerDay.amount(1), hours(12))
                .getDate(), equalTo(today));
    }

    @Test
    public void calculateEffortBetweenTwoDates() {
        IntraDayDate start = IntraDayDate.create(today, zero());
        IntraDayDate end = IntraDayDate.create(today.plusDays(3), hours(0));

        assertThat(start.effortUntil(end), equalTo(hours(8 * 3)));

        end = IntraDayDate.create(today.plusDays(3), hours(8));
        assertThat(start.effortUntil(end), equalTo(hours(8 * 4)));

        start = IntraDayDate.create(today, hours(8));
        end = IntraDayDate.create(today.plusDays(3), hours(0));
        assertThat(start.effortUntil(end), equalTo(hours(8 * 2)));

        start = IntraDayDate.create(today, hours(3));
        assertThat(start.effortUntil(end), equalTo(hours(8 * 2 + 5)));

        end = IntraDayDate.create(today.plusDays(3), hours(6));
        assertThat(start.effortUntil(end), equalTo(hours(8 * 2 + 5 + 6)));

        end = IntraDayDate.create(today.plusDays(3), minutes(30));
        assertThat(start.effortUntil(end),
                equalTo(hours(8 * 2 + 5).plus(minutes(30))));

        start = IntraDayDate.create(today, hours(5).plus(minutes(40)));
        assertThat(start.effortUntil(end),
                equalTo(hours(8 * 2 + 2).plus(minutes(50))));
    }

    @Test
    public void calculateAddEffort() {
        IntraDayDate start = IntraDayDate.create(today, zero());

        assertThat(start.addEffort(hours(24)),
                equalTo(IntraDayDate.create(today.plusDays(3), hours(0))));

        assertThat(start.addEffort(hours(20)),
                equalTo(IntraDayDate.create(today.plusDays(2), hours(4))));

        assertThat(
                start.addEffort(hours(20).plus(minutes(20))),
                equalTo(IntraDayDate.create(today.plusDays(2),
                        hours(4).plus(minutes(20)))));

        start = IntraDayDate.create(today, hours(3));
        assertThat(start.addEffort(hours(24)),
                equalTo(IntraDayDate.create(today.plusDays(3), hours(3))));

        assertThat(start.addEffort(hours(20)),
                equalTo(IntraDayDate.create(today.plusDays(2), hours(7))));

        assertThat(start.addEffort(hours(20).plus(minutes(20))),
                equalTo(IntraDayDate.create(today.plusDays(2),
                        hours(7).plus(minutes(20)))));

        start = IntraDayDate.create(today, hours(3).plus(minutes(40)));
        assertThat(
                start.addEffort(hours(24)),
                equalTo(IntraDayDate.create(today.plusDays(3),
                        hours(3).plus(minutes(40)))));

        assertThat(
                start.addEffort(hours(20)),
                equalTo(IntraDayDate.create(today.plusDays(2),
                        hours(7).plus(minutes(40)))));

        assertThat(start.addEffort(hours(20).plus(minutes(20))),
                equalTo(IntraDayDate.create(today.plusDays(3), hours(0))));

        assertThat(
                start.addEffort(hours(20).plus(minutes(10))),
                equalTo(IntraDayDate.create(today.plusDays(2),
                        hours(7).plus(minutes(50)))));
    }

}
TOP

Related Classes of org.libreplan.business.test.workingday.IntraDayDateTest

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.