ThreeTen / threeten

This project was the home of code used to develop a modern date and time library for JDK8. Development has moved to OpenJDK and a separate backport project, threetenbp.
http://threeten.github.io/
191 stars 37 forks source link

Add Period/Duration from(TemporalAmount) #285

Closed jodastephen closed 11 years ago

jodastephen commented 11 years ago

Add Period/Duration from(TemporalAmount) methods that match those on date and time classes.

jodastephen commented 11 years ago

Code review for Period

    //-----------------------------------------------------------------------
    /**
     * Obtains an instance of {@code Period} from a temporal amount.
     * <p>
     * This obtains a period based on the specified amount.
     * A {@code TemporalAmount} represents an  amount of time, which may be
     * date-based or time-based.
     * This factory attempts to convert the amount to a {@code Period}.
     * <p>
     * The conversion loops around the set of units from the amount and uses
     * the {@link ChronoUnit#YEARS YEARS}, {@link ChronoUnit#MONTHS MONTHS}
     * and {@link ChronoUnit#DAYS DAYS} units to create a period.
     * If any other units are found then an exception is thrown.
     *
     * @param amount  the temporal amount to convert, not null
     * @return the period, not null
     * @throws DateTimeException if unable to convert to a {@code Period}
     * @throws ArithmeticException if the amount of years, months or days exceeds an int
     */
    public static Period from(TemporalAmount amount) {
        Objects.requireNonNull(amount, "amount");
        int years = 0;
        int months = 0;
        int days = 0;
        for (TemporalUnit unit : amount.getUnits()) {
            long unitAmount = amount.get(unit);
            if (unit == ChronoUnit.YEARS) {
                years = Math.toIntExact(unitAmount);
            } else if (unit == ChronoUnit.MONTHS) {
                months = Math.toIntExact(unitAmount);
            } else if (unit == ChronoUnit.DAYS) {
                days = Math.toIntExact(unitAmount);
            } else {
                throw new DateTimeException("Unit must be Years, Months or Days, but was " + unit);
            }
        }
        return create(years, months, days);
    }

tests

    //-----------------------------------------------------------------------
    // from(TemporalAmount)
    //-----------------------------------------------------------------------
    @Test
    public void factory_from_Years() {
        TemporalAmount years23 = new TemporalAmount() {
            @Override
            public long get(TemporalUnit unit) {
                return 23;
            }
            @Override
            public List<TemporalUnit> getUnits() {
                return Collections.<TemporalUnit>singletonList(ChronoUnit.YEARS);
            }
            @Override
            public Temporal addTo(Temporal temporal) {
                throw new UnsupportedOperationException();
            }
            @Override
            public Temporal subtractFrom(Temporal temporal) {
                throw new UnsupportedOperationException();
            }
        };
        assertPeriod(Period.from(years23), 23, 0, 0);
    }

    @Test(expectedExceptions = ArithmeticException.class)
    public void factory_from_Years_tooBig() {
        TemporalAmount yearsBig = new TemporalAmount() {
            @Override
            public long get(TemporalUnit unit) {
                return ((long) (Integer.MAX_VALUE)) + 1;
            }
            @Override
            public List<TemporalUnit> getUnits() {
                return Collections.<TemporalUnit>singletonList(ChronoUnit.YEARS);
            }
            @Override
            public Temporal addTo(Temporal temporal) {
                throw new UnsupportedOperationException();
            }
            @Override
            public Temporal subtractFrom(Temporal temporal) {
                throw new UnsupportedOperationException();
            }
        };
        Period.from(yearsBig);
    }

    @Test(expectedExceptions = DateTimeException.class)
    public void factory_from_TemporalAmount_Duration() {
        Period.from(Duration.ZERO);
    }

    @Test(expectedExceptions = NullPointerException.class)
    public void factory_from_TemporalAmount_null() {
        Period.from(null);
    }
RogerRiggs commented 11 years ago

Look ok.

jodastephen commented 11 years ago

Fixed in Period and Duration by http://hg.openjdk.java.net/threeten/threeten/jdk/rev/651fb9ce9eb3

Reordered methods in http://hg.openjdk.java.net/threeten/threeten/jdk/rev/c46ed88b168e