/* * Geotoolkit - An Open Source Java GIS Toolkit * http://www.geotoolkit.org * * (C) 2008, Open Source Geospatial Foundation (OSGeo) * (C) 2009, Geomatys * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License. * * This library 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 * Lesser General Public License for more details. */ package org.geotoolkit.temporal.object; import java.util.Objects; import org.apache.sis.util.iso.SimpleInternationalString; import org.opengis.temporal.PeriodDuration; import org.opengis.util.InternationalString; import static org.geotoolkit.temporal.object.TemporalConstants.*; /** * Uses the format specified by ISO 8601 for exchanging information * about the duration of a period. * * @author Mehdi Sidhoum (Geomatys) * @module * @since 4.0 * @version 4.0 */ public class DefaultPeriodDuration extends DefaultDuration implements PeriodDuration { /** * {@literal P} is a mandatory element which designates that the following characters represent the duration of a period. */ private static final InternationalString DESIGNATOR = new SimpleInternationalString("P"); private InternationalString years; private InternationalString months; private InternationalString weeks; private InternationalString days; /** * {@literal T} shall be included whenever the sequence includes values for units of less than a day. */ private static final InternationalString TIME_INDICATOR = new SimpleInternationalString("T"); private InternationalString hours; private InternationalString minutes; private InternationalString seconds; /** * Creates a new instances of PeriodDuration. * * @param years * @param months * @param weeks * @param days * @param hours * @param minutes * @param seconds */ public DefaultPeriodDuration(final InternationalString years, final InternationalString months, final InternationalString weeks, final InternationalString days, final InternationalString hours, final InternationalString minutes, final InternationalString seconds) { this.years = years; this.months = months; this.weeks = weeks; this.days = days; this.hours = hours; this.minutes = minutes; this.seconds = seconds; } /** * Creates a new instance of PeriodDuration from a long value passed in parameter. * if the long contains milliseconds, this will be ignored because there is no * MilliSeconds specified in the string format PnYnMnDTnHnMnS, see ISO 8601. * * @param durationInMilliSeconds */ public DefaultPeriodDuration(long durationInMilliSeconds) { InternationalString _years = null; InternationalString _months = null; InternationalString _week = null; InternationalString _days = null; InternationalString _hours = null; InternationalString _minutes = null; InternationalString _seconds = null; long temp = durationInMilliSeconds / YEAR_MS; if (temp >= 1) { _years = new SimpleInternationalString(String.valueOf(temp)); durationInMilliSeconds -= temp * YEAR_MS; } this.years = _years; temp = durationInMilliSeconds / MONTH_MS; if (temp >= 1) { _months = new SimpleInternationalString(String.valueOf(temp)); durationInMilliSeconds -= temp * MONTH_MS; } this.months = _months; temp = durationInMilliSeconds / WEEK_MS; if (temp >= 1) { _week = new SimpleInternationalString(String.valueOf(temp)); durationInMilliSeconds -= temp * WEEK_MS; } this.weeks = _week; //we look if the gap is more than one day (86400000 ms) temp = durationInMilliSeconds / DAY_MS; if (temp >= 1) { _days = new SimpleInternationalString(String.valueOf(temp)); durationInMilliSeconds -= temp * DAY_MS; } this.days = _days; temp = durationInMilliSeconds / HOUR_MS; if (temp >= 1) { _hours = new SimpleInternationalString(String.valueOf(temp)); durationInMilliSeconds -= temp * HOUR_MS; } this.hours = _hours; temp = durationInMilliSeconds / MINUTE_MS; if (temp >= 1) { _minutes = new SimpleInternationalString(String.valueOf(temp)); durationInMilliSeconds -= temp * MINUTE_MS; } this.minutes = _minutes; temp = durationInMilliSeconds / SECOND_MS; if (temp >= 1) { _seconds = new SimpleInternationalString(String.valueOf(temp)); durationInMilliSeconds -= temp * SECOND_MS; } this.seconds = _seconds; /*if (durationInMilliSeconds != 0) { throw new IllegalArgumentException("PeriodDuration can't be found at the Millisecond precision in the pattern PnYnMnDTnHnMnS specified by ISO 8601."); }*/ } /** * Returns {@literal P} which is a mandatory element which designates that the following * characters represent the duration of a period. * * @return {@literal P} is a mandatory element which designates that the * following characters represent the duration of a period. */ @Override public InternationalString getDesignator() { return DESIGNATOR; } /** * Returns a positive integer, followed by the character "Y", * which indicated the number of years in the period. * * @return a positive integer, followed by the character "Y", * which indicated the number of years in the period. */ @Override public InternationalString getYears() { return years; } /** * Returns a positive integer, followed by the character "M", * which indicated the number of months in the period. * * @return a positive integer, followed by the character "M", * which indicated the number of months in the period. */ @Override public InternationalString getMonths() { return months; } /** * Returns a positive integer, followed by the character "D", * which indicated the number of days in the period. * * @return a positive integer, followed by the character "D", * which indicated the number of days in the period. */ @Override public InternationalString getDays() { return days; } /** * Returns {@code T} which shall be included whenever the sequence includes values for * units less than a day. * * @return {@code T} which shall be included whenever the sequence includes values for * units less than a day. */ @Override public InternationalString getTimeIndicator() { return TIME_INDICATOR; } /** * Returns A positive integer, followed by the character "H", * which indicated the number of hours in the period. * * @return A positive integer, followed by the character "H", * which indicated the number of hours in the period. */ @Override public InternationalString getHours() { return hours; } /** * Returns a positive integer, followed by the character "M", * which indicated the number of minutes in the period. * * @return A positive integer, followed by the character "M", * which indicated the number of minutes in the period. */ @Override public InternationalString getMinutes() { return minutes; } /** * Returns a positive integer, followed by the character "S", * which indicated the number of seconds in the period. * * @return a positive integer, followed by the character "S", * which indicated the number of seconds in the period. */ @Override public InternationalString getSeconds() { return seconds; } /** * Returns a positive integer, followed by the character "W", * which indicated the number of week(s) in the period. * * @return a positive integer, followed by the character "W", * which indicated the number of week(s) in the period. */ public InternationalString getWeek() { return weeks; } void setYears(final InternationalString years) { this.years = years; } void setMonths(final InternationalString months) { this.months = months; } void setDays(final InternationalString days) { this.days = days; } void setHours(final InternationalString hours) { this.hours = hours; } void setMinutes(final InternationalString minutes) { this.minutes = minutes; } void setSeconds(final InternationalString seconds) { this.seconds = seconds; } void setWeek(final InternationalString week) { this.weeks = week; } /** * {@inheritDoc } */ @Override public long getTimeInMillis() { String periodDescription = this.toString(); long response = 0; //removing the 'P' character periodDescription = periodDescription.substring(1); //if the period contains years (31536000000 ms) the response will be incremented if (periodDescription.indexOf('Y') != -1) { int nbYear = Integer.parseInt(periodDescription.substring(0, periodDescription.indexOf('Y'))); response += nbYear * YEAR_MS; periodDescription = periodDescription.substring(periodDescription.indexOf('Y') + 1); } //if the period contains months (2628000000 ms) if ((periodDescription.indexOf('M') != -1 && (periodDescription.indexOf('T') == -1)) || ((periodDescription.indexOf('T') != -1) && (periodDescription.indexOf('M') < periodDescription.indexOf('T')) && ((periodDescription.indexOf('M') != -1)))) { int nbMonth = Integer.parseInt(periodDescription.substring(0, periodDescription.indexOf('M'))); response += nbMonth * MONTH_MS; periodDescription = periodDescription.substring(periodDescription.indexOf('M') + 1); } //if the period contains weeks (604800000 ms) if (periodDescription.indexOf('W') != -1) { int nbWeek = Integer.parseInt(periodDescription.substring(0, periodDescription.indexOf('W'))); response += nbWeek * WEEK_MS; periodDescription = periodDescription.substring(periodDescription.indexOf('W') + 1); } //if the period contains days (86400000 ms) if (periodDescription.indexOf('D') != -1) { int nbDay = Integer.parseInt(periodDescription.substring(0, periodDescription.indexOf('D'))); response += nbDay * DAY_MS; periodDescription = periodDescription.substring(periodDescription.indexOf('D') + 1); } // removing 'T' character if exists if (periodDescription.indexOf('T') != -1) { periodDescription = periodDescription.substring(1); } //if the period contains hours (3600000 ms) if (periodDescription.indexOf('H') != -1) { int nbHour = Integer.parseInt(periodDescription.substring(0, periodDescription.indexOf('H'))); response += nbHour * HOUR_MS; periodDescription = periodDescription.substring(periodDescription.indexOf('H') + 1); } //if the period contains minutes (60000 ms) if (periodDescription.indexOf('M') != -1) { int nbMin = Integer.parseInt(periodDescription.substring(0, periodDescription.indexOf('M'))); response += nbMin * MINUTE_MS; periodDescription = periodDescription.substring(periodDescription.indexOf('M') + 1); } //if the period contains seconds (1000 ms) if (periodDescription.indexOf('S') != -1) { int nbSec = Integer.parseInt(periodDescription.substring(0, periodDescription.indexOf('S'))); response += nbSec * SECOND_MS; periodDescription = periodDescription.substring(periodDescription.indexOf('S') + 1); } if (periodDescription.length() != 0) { throw new IllegalArgumentException("The period duration string is malformed"); } return response; } /** * {@inheritDoc} */ @Override public boolean equals(final Object object) { if (object == this) { return true; } if (object instanceof DefaultPeriodDuration) { final DefaultPeriodDuration that = (DefaultPeriodDuration) object; return Objects.equals(this.days, that.days) && Objects.equals(this.hours, that.hours) && Objects.equals(this.minutes, that.minutes) && Objects.equals(this.months, that.months) && Objects.equals(this.seconds, that.seconds) && Objects.equals(this.years, that.years); } return false; } /** * {@inheritDoc } */ @Override public int hashCode() { int hash = 5; hash = 37 * hash + (this.days != null ? this.days.hashCode() : 0); hash = 37 * hash + (this.hours != null ? this.hours.hashCode() : 0); hash = 37 * hash + (this.minutes != null ? this.minutes.hashCode() : 0); hash = 37 * hash + (this.months != null ? this.months.hashCode() : 0); hash = 37 * hash + (this.seconds != null ? this.seconds.hashCode() : 0); hash = 37 * hash + (this.years != null ? this.years.hashCode() : 0); return hash; } /** * Returns a duration value String in format 8601. the pattern is PnYnMnDTnHnMnS. * * @return a duration value String in format 8601. the pattern is PnYnMnDTnHnMnS. */ @Override public String toString() { StringBuilder s = new StringBuilder(); s.append(DESIGNATOR); if (years != null) { s.append(years).append('Y'); } if (months != null) { s.append(months).append('M'); } if (weeks != null) { s.append(weeks).append('W'); } if (days != null) { s.append(days).append('D'); } // if (hours != null || minutes != null || seconds != null) { s.append(TIME_INDICATOR); // } if (hours != null) { s.append(hours).append('H'); } if (minutes != null) { s.append(minutes).append('M'); } if (seconds != null) { s.append(seconds).append('S'); } else { s.append("0S"); } return s.toString(); } }