Java tutorial
/** * Copyright (C) 2012-2015 52North Initiative for Geospatial Open Source * Software GmbH * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation. * * If the program is linked with libraries which are licensed under one of * the following licenses, the combination of the program with the linked * library is not considered a "derivative work" of the program: * * - Apache License, version 2.0 * - Apache Software License, version 1.0 * - GNU Lesser General Public License, version 3 * - Mozilla Public License, versions 1.0, 1.1 and 2.0 * - Common Development and Distribution License (CDDL), version 1.0 * * Therefore the distribution of the program linked with libraries licensed * under the aforementioned licenses, is permitted by the copyright holders * if the distribution is compliant with both the GNU General Public * License version 2 and the aforementioned licenses. * * 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 General * Public License for more details. */ package org.n52.iceland.util; import java.util.regex.Pattern; import org.joda.time.DateTime; import org.joda.time.DateTimeZone; import org.joda.time.Period; import org.joda.time.format.DateTimeFormat; import org.joda.time.format.ISODateTimeFormat; import org.joda.time.format.ISOPeriodFormat; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.n52.iceland.exception.ows.concrete.DateTimeException; import org.n52.iceland.exception.ows.concrete.DateTimeFormatException; import org.n52.iceland.exception.ows.concrete.DateTimeParseException; import org.n52.iceland.ogc.gml.time.Time; import org.n52.iceland.ogc.gml.time.Time.TimeFormat; import org.n52.iceland.ogc.gml.time.TimeInstant; import org.n52.iceland.ogc.gml.time.TimePeriod; import org.n52.iceland.ogc.gml.time.TimePosition; import com.google.common.base.Strings; /** * Utility class for Time formatting and parsing. Uses Joda Time. * * @since 4.0.0 * */ public final class DateTimeHelper { private static final Logger LOGGER = LoggerFactory.getLogger(DateTimeHelper.class); /** * Response format for time. */ private static String responseFormat; private static final String YMD_RESPONSE_FORMAT = "yyyy-MM-dd"; private static final String YM_RESPONSE_FORMAT = "yyyy-MM"; private static final String Y_RESPONSE_FORMAT = "yyyy"; private static final int YEAR = 4; private static final int YEAR_MONTH = 7; private static final int YEAR_MONTH_DAY = 10; private static final int YEAR_MONTH_DAY_HOUR = 13; private static final int YEAR_MONTH_DAY_HOUR_MINUTE = 16; private static final int YEAR_MONTH_DAY_HOUR_MINUTE_SECOND = 19; private static final int ONE_VALUE = 1; private static final String Z = "Z"; private static final String UTC_OFFSET = "+00:00"; /** * lease value */ private static int lease; /** * Parses a time String to a Joda Time DateTime object * * @param timeString * Time String * @return DateTime object * @throws DateTimeParseException * If an error occurs. */ public static DateTime parseIsoString2DateTime(final String timeString) throws DateTimeParseException { checkForValidity(timeString); if (Strings.isNullOrEmpty(timeString)) { return null; } try { if (timeString.contains("+") || Pattern.matches("-\\d", timeString) || timeString.contains(Z) || timeString.contains("z")) { return ISODateTimeFormat.dateOptionalTimeParser().withOffsetParsed().parseDateTime(timeString); } else { return ISODateTimeFormat.dateOptionalTimeParser().withZone(DateTimeZone.UTC) .parseDateTime(timeString); } } catch (final RuntimeException uoe) { throw new DateTimeParseException(timeString, uoe); } } /** * Parses the given ISO 8601 String to a {@link Time} including * {@link TimeInstant} and {@link TimePeriod} * * @param timeString * a ISO 8601 formatted time string * @return a Time object * @throws DateTimeParseException * If an error occurs. */ public static Time parseIsoString2DateTime2Time(final String timeString) throws DateTimeParseException { if (timeString.contains(Constants.SLASH_STRING)) { final String[] subTokens = timeString.split(Constants.SLASH_STRING); return new TimePeriod(parseIsoString2DateTime(subTokens[0]), parseIsoString2DateTime(subTokens[1])); } else { return new TimeInstant(parseIsoString2DateTime(timeString)); } } private static void checkForValidity(final String timeString) throws DateTimeParseException { if (!(timeString.length() == YEAR || timeString.length() == YEAR_MONTH || timeString.length() >= YEAR_MONTH_DAY)) { throw new DateTimeParseException(timeString); } } /** * Formats the given Time to ISO 8601 string. * * @param time * an {@link Time} object to be formatted * @return an ISO 8601 conform {@link String}. * @throws IllegalArgumentException * in the case of receiving <tt>null</tt> or not supported * types. * @see #formatDateTime2IsoString(DateTime) */ public static String format(final Time time) { if (time != null) { if (time instanceof TimeInstant) { try { return formatDateTime2String(((TimeInstant) time).getTimePosition()); } catch (DateTimeFormatException e) { throw new IllegalArgumentException(e); } // return formatDateTime2IsoString(((TimeInstant) time).getValue()); } else if (time instanceof TimePeriod) { return String.format("%s/%s", formatDateTime2IsoString(((TimePeriod) time).getStart()), formatDateTime2IsoString(((TimePeriod) time).getEnd())); } } final String exceptionMsg = String.format("Given Time object is not valid: %s", time); LOGGER.debug(exceptionMsg); throw new IllegalArgumentException(exceptionMsg); } /** * Formats a DateTime to a ISO-8601 String * * @param dateTime * Time object * @return ISO-8601 formatted time String */ public static String formatDateTime2IsoString(final DateTime dateTime) { if (dateTime == null) { return getZeroUtcDateTime().toString().replace(Z, UTC_OFFSET); } return dateTime.toString(); } /** * Formats a DateTime to a String using the response format * * @param dateTime * Time object * @return Response formatted time String * * @throws DateTimeFormatException * If an error occurs. */ public static String formatDateTime2ResponseString(final DateTime dateTime) throws DateTimeFormatException { return formatDateTime2FormattedString(dateTime, responseFormat); } public static String formatDateTime2String(final DateTime dateTime, final TimeFormat timeFormat) throws DateTimeFormatException { switch (timeFormat) { case Y: return formatDateTime2YearDateString(dateTime); case YM: return formatDateTime2YearMonthDateString(dateTime); case YMD: return formatDateTime2YearMonthDayDateStringYMD(dateTime); default: return formatDateTime2ResponseString(dateTime); } } public static String formatDateTime2String(final TimePosition timePosition) throws DateTimeFormatException { switch (timePosition.getTimeFormat()) { case Y: return formatDateTime2YearDateString(timePosition.getTime()); case YM: return formatDateTime2YearMonthDateString(timePosition.getTime()); case YMD: return formatDateTime2YearMonthDayDateStringYMD(timePosition.getTime()); default: return formatDateTime2ResponseString(timePosition.getTime()); } } /** * Formats a DateTime to a String using specified format * * @param dateTime * Time object * @param dateFormat * the date time format * * @return Specified formatted time String * * @throws DateTimeFormatException * If an error occurs. */ public static String formatDateTime2FormattedString(final DateTime dateTime, final String dateFormat) throws DateTimeFormatException { try { if (Strings.isNullOrEmpty(dateFormat)) { return formatDateTime2IsoString(dateTime); } else { if (dateTime == null) { return getZeroUtcDateTime().toString(DateTimeFormat.forPattern(dateFormat)); } return dateTime.toString(DateTimeFormat.forPattern(dateFormat)).replace(Z, UTC_OFFSET); } } catch (final IllegalArgumentException iae) { throw new DateTimeFormatException(dateTime, iae); } } /** * formats a DateTime to a string with year-month-day. * * @param dateTime * The DateTime. * @return Returns formatted time String. * * @throws DateTimeFormatException */ public static String formatDateTime2YearMonthDayDateStringYMD(final DateTime dateTime) throws DateTimeFormatException { try { DateTime result = checkAndGetDateTimeWithZoneUtc(dateTime); return result.toString(DateTimeFormat.forPattern(YMD_RESPONSE_FORMAT)); } catch (final IllegalArgumentException iae) { throw new DateTimeFormatException(dateTime, iae); } } /** * formats a DateTime to a string with year-month. * * @param dateTime * The DateTime. * @return Returns formatted time String. * * @throws DateTimeFormatException */ public static String formatDateTime2YearMonthDateString(final DateTime dateTime) throws DateTimeFormatException { try { DateTime result = checkAndGetDateTimeWithZoneUtc(dateTime); return result.toString(DateTimeFormat.forPattern(YM_RESPONSE_FORMAT)); } catch (final IllegalArgumentException iae) { throw new DateTimeFormatException(dateTime, iae); } } /** * formats a DateTime to a string with year. * * @param dateTime * The DateTime. * @return Returns formatted time String. * * @throws DateTimeFormatException */ public static String formatDateTime2YearDateString(final DateTime dateTime) throws DateTimeFormatException { try { DateTime result = checkAndGetDateTimeWithZoneUtc(dateTime); return result.toString(DateTimeFormat.forPattern(Y_RESPONSE_FORMAT)); } catch (final IllegalArgumentException iae) { throw new DateTimeFormatException(dateTime, iae); } } private static DateTime checkAndGetDateTimeWithZoneUtc(final DateTime dateTime) { if (dateTime == null) { return getZeroUtcDateTime(); } else { return new DateTime(dateTime.getMillis(), DateTimeZone.UTC); } } private static DateTime getZeroUtcDateTime() { return new DateTime(0000, 01, 01, 00, 00, 00, 000, DateTimeZone.UTC); } public static int getTimeLengthBeforeTimeZone(String time) { String valueSplit = null; if (time.contains("Z")) { valueSplit = time.substring(0, time.indexOf('Z')); } else if (time.contains(Constants.PLUS_STRING)) { valueSplit = time.substring(0, time.indexOf(Constants.PLUS_CHAR)); } else if (time.contains(Constants.MINUS_STRING) && StringHelper.checkIfCharacterOccursXTimesIgnoreCase(time, Constants.MINUS_CHAR, 3)) { valueSplit = time.substring(0, time.lastIndexOf(Constants.MINUS_CHAR)); } return valueSplit != null ? valueSplit.length() : time.length(); } /** * Set the time object to the end values (seconds, minutes, hours, days,..) * if the time Object has not all values * * @param dateTime * Time object * @param isoTimeLength * Length of the time object * @return Modified time object. */ public static DateTime setDateTime2EndOfMostPreciseUnit4RequestedEndPosition(final DateTime dateTime, final int isoTimeLength) { switch (isoTimeLength) { // year case YEAR: return dateTime.plusYears(ONE_VALUE).minusMillis(ONE_VALUE); // year, month case YEAR_MONTH: return dateTime.plusMonths(ONE_VALUE).minusMillis(ONE_VALUE); // year, month, day case YEAR_MONTH_DAY: return dateTime.plusDays(ONE_VALUE).minusMillis(ONE_VALUE); // year, month, day, hour case YEAR_MONTH_DAY_HOUR: return dateTime.plusHours(ONE_VALUE).minusMillis(ONE_VALUE); // year, month, day, hour, minute case YEAR_MONTH_DAY_HOUR_MINUTE: return dateTime.plusMinutes(ONE_VALUE).minusMillis(ONE_VALUE); // year, month, day, hour, minute, second case YEAR_MONTH_DAY_HOUR_MINUTE_SECOND: return dateTime.plusSeconds(ONE_VALUE).minusMillis(ONE_VALUE); default: return dateTime; } } /** * Parse a duration from a String representation * * @param stringDuration * Duration as String * @return Period object of duration */ public static Period parseDuration(final String stringDuration) { return ISOPeriodFormat.standard().parsePeriod(stringDuration); } /** * Calculates the expire time for a time object * * @param start * Time object * @return Expire time */ public static DateTime calculateExpiresDateTime(final DateTime start) { return start.plusMinutes(lease); } /** * Set the response format * * @param responseFormat * Defined response format */ public static void setResponseFormat(final String responseFormat) { DateTimeHelper.responseFormat = responseFormat; } /** * Set the lease value * * @param lease * Defined lease value */ public static void setLease(final int lease) { DateTimeHelper.lease = lease; } /** * Make a new UTC DateTime from an object * * @param object * @return DateTime, or null if object was null */ public static DateTime makeDateTime(Object object) { return object == null ? null : new DateTime(object, DateTimeZone.UTC); } /** * Find the max of two dates (null safe) * * @param dt1 * @param dt2 * @return Max of two dates */ public static DateTime max(DateTime dt1, DateTime dt2) { if (dt2 == null) { return dt1; } else if (dt1 == null) { return dt2; } else if (dt2.isAfter(dt1)) { return dt2; } return dt1; } /** * Hidden utility constructor. */ private DateTimeHelper() { } }