com.norconex.commons.lang.time.YearMonthDayInterval.java Source code

Java tutorial

Introduction

Here is the source code for com.norconex.commons.lang.time.YearMonthDayInterval.java

Source

/* Copyright 2010-2014 Norconex Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.norconex.commons.lang.time;

import java.io.Serializable;
import java.util.Calendar;
import java.util.Date;

import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.DateUtils;

/**
 * An immutable date interval where both the start and end are inclusive, unless
 * stated otherwise.  Start and end YearMonthDay instances cannot be
 * <code>null</code> and start date must be before or the same date as 
 * the end date.
 * @author Pascal Essiembre
 * @since 1.3.0
 */
public final class YearMonthDayInterval implements Serializable {

    private static final long serialVersionUID = -5607689446876900272L;

    private final YearMonthDay start;
    private final YearMonthDay end;

    public YearMonthDayInterval(YearMonthDay start, YearMonthDay end) {
        if (start == null || end == null) {
            throw new IllegalArgumentException("YearMonthday start and YearMonthday end cannot be null.");
        }
        if (start.isAfter(end)) {
            throw new IllegalArgumentException("YearMonthDay start cannot be after YearMonthDay end.");
        }
        this.start = start;
        this.end = end;
    }

    /**
     * Constructs a YearMonthDayInterval out of a string.  The recommended
     * string format is <code>yyyy-MM-dd - yyyy-MM-dd</code>, but any 
     * characters in between the start and end are accepted as long as there 
     * is a space after the start YearMontDay and before the end YearMonthDay.
     * @param interval the interval to parse
     */
    public YearMonthDayInterval(String interval) {
        String trimmed = StringUtils.trim(interval);
        String startStr = StringUtils.substringBefore(trimmed, " ");
        String endStr = StringUtils.substringAfterLast(trimmed, " ");
        if (StringUtils.isBlank(startStr) || StringUtils.isBlank(endStr)) {
            throw new IllegalArgumentException("String YearMonthDay interval cannot be null or empty.");
        }
        this.start = new YearMonthDay(startStr);
        this.end = new YearMonthDay(endStr);
    }

    public YearMonthDayInterval(Date start, Date end) {
        if (start == null || end == null) {
            throw new IllegalArgumentException("Date start and Date end cannot be null.");
        }
        this.start = new YearMonthDay(start);
        this.end = new YearMonthDay(end);
    }

    public YearMonthDayInterval(Calendar start, Calendar end) {
        if (start == null || end == null) {
            throw new IllegalArgumentException("Calendar start and Calendar end cannot be null.");
        }
        this.start = new YearMonthDay(start);
        this.end = new YearMonthDay(end);
    }

    public YearMonthDay getStart() {
        return start;
    }

    public Date getStartDate() {
        return start.toDate();
    }

    public YearMonthDay getEnd() {
        return end;
    }

    public Date getEndDate() {
        return end.toDate();
    }

    /**
     * Gets the end date as midnight the day after to ensure all dates on the
     * same day as this YearMonthDay are smaller than this returned 
     * exclusive date.  Useful for date range comparisons where typically
     * the end date is exclusive.
     * @return midnight past the end date 
     */
    public Date getEndDateEndOfDay() {
        return end.toEndOfDayDate();
    }

    /**
     * Whether the YearMonthDay falls between this interval 
     * (inclusive endpoints).
     * @param ymd the YearMonthDay
     * @return <code>true</code> if YearMonthDay is included in this interval
     */
    public boolean contains(YearMonthDay ymd) {
        if (start.isAfter(ymd)) {
            return false;
        }
        if (end.isBefore(ymd)) {
            return false;
        }
        return true;
    }

    /**
     * Whether the date falls between this interval 
     * (inclusive endpoints).
     * @param date a date
     * @return <code>true</code> if the date is included in this interval
     */
    public boolean contains(Date date) {
        Date startDate = start.toDate();
        Date endDate = end.toDate();
        if (startDate.after(date)) {
            return false;
        }
        if (endDate.before(date)) {
            return false;
        }
        return true;
    }

    /**
     * Gets the number of years between start and end dates, rounded down.
     * @return number of years
     */
    public int getYears() {
        int years = end.getYear() - start.getYear();
        if (end.getMonth() < start.getMonth()) {
            return years - 1;
        }
        if (end.getMonth() == start.getMonth() && end.getDay() < start.getDay()) {
            return years - 1;
        }
        return years;
    }

    /**
     * Gets the number of months between start and end dates, rounded down.
     * @return number of months
     */
    public int getMonths() {
        int months = 0;
        Calendar cal = start.toCalendar();
        Calendar endCal = end.toCalendar();
        cal.add(Calendar.MONTH, 1);
        while (!cal.after(endCal)) {
            months++;
            cal.add(Calendar.MONTH, 1);
        }
        return months;
    }

    /**
     * Gets the number of days between start and end dates, rounded down.
     * @return number of days
     */
    public int getDays() {
        return (int) ((end.toMillis() - start.toMillis()) / DateUtils.MILLIS_PER_DAY);
    }

    /**
     * Gets the interval as a string of this format:
     *  <code>yyyy-MM-dd - yyyy-MM-dd</code>;
     *  @return interval as string
     */
    @Override
    public String toString() {
        return start + " - " + end;
    }

}