/* * GeoTools - The Open Source Java GIS Toolkit * http://geotools.org * * (C) 2008, Open Source Geospatial Foundation (OSGeo) * * 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.geotools.temporal.object; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Calendar; import java.util.Date; import java.util.TimeZone; import java.util.logging.Logger; import javax.measure.unit.NonSI; import javax.measure.unit.SI; import javax.measure.unit.Unit; import org.geotools.temporal.reference.DefaultTemporalCoordinateSystem; import org.opengis.temporal.CalendarDate; import org.opengis.temporal.DateAndTime; import org.opengis.temporal.Duration; import org.opengis.temporal.JulianDate; import org.opengis.temporal.OrdinalPosition; import org.opengis.temporal.TemporalCoordinate; import org.opengis.temporal.TemporalCoordinateSystem; /** * This is a tool class to convert DateTime from ISO8601 to Date object. * * @author Mehdi Sidhoum (Geomatys) * * * @source $URL$ */ public class Utils { Logger logger = Logger.getLogger("org.geotools.temporal"); /** * The number of millisecond in one year. */ private final static long yearMS = 31536000000L; /** * The number of millisecond in one month. */ private final static long monthMS = 2628000000L; /** * The number of millisecond in one week. */ private final static long weekMS = 604800000L; /** * The number of millisecond in one day. */ private final static long dayMS = 86400000L; /** * The number of millisecond in one hour. */ private final static long hourMS = 3600000L; /** * The number of millisecond in one minute. */ private final static long minMS = 60000; /** * The number of millisecond in one second. */ private final static long secondMS = 1000; /** * Returns a Date object from an ISO-8601 representation string. (String defined with pattern yyyy-MM-dd'T'HH:mm:ss.SSSZ or yyyy-MM-dd). * @param dateString * @return */ public static Date getDateFromString(String dateString) throws ParseException { final String DATE_FORMAT = "yyyy-MM-dd'T'HH:mm:ssZ"; final String DATE_FORMAT2 = "yyyy-MM-dd"; final String DATE_FORMAT3 = "yyyy-MM-dd'T'HH:mm:ss.SSSZ"; final SimpleDateFormat sdf = new java.text.SimpleDateFormat(DATE_FORMAT); final SimpleDateFormat sdf2 = new java.text.SimpleDateFormat(DATE_FORMAT2); final SimpleDateFormat sdf3 = new java.text.SimpleDateFormat(DATE_FORMAT3); if (dateString.contains("T")) { String timezoneStr; int index = dateString.lastIndexOf("+"); if (index == -1) { index = dateString.lastIndexOf("-"); } if (index > dateString.indexOf("T")) { timezoneStr = dateString.substring(index + 1); if (timezoneStr.contains(":")) { //e.g : 1985-04-12T10:15:30+04:00 timezoneStr = timezoneStr.replace(":", ""); dateString = dateString.substring(0, index + 1).concat(timezoneStr); } else if (timezoneStr.length() == 2) { //e.g : 1985-04-12T10:15:30-04 dateString = dateString.concat("00"); } } else if (dateString.endsWith("Z")) { //e.g : 1985-04-12T10:15:30Z dateString = dateString.substring(0, dateString.length() - 1).concat("+0000"); }else { //e.g : 1985-04-12T10:15:30 dateString = dateString + "+0000"; } final String timezone = getTimeZone(dateString); sdf.setTimeZone(TimeZone.getTimeZone(timezone)); if (dateString.contains(".")) { return sdf3.parse(dateString); } return sdf.parse(dateString); } if (dateString.contains("-")) { return sdf2.parse(dateString); } return null; } public static String getTimeZone(final String dateString) { if (dateString.endsWith("Z")) { return "GMT+" + 0; } int index = dateString.lastIndexOf("+"); if (index == -1) { index = dateString.lastIndexOf("-"); } if (index > dateString.indexOf("T")) { return "GMT" + dateString.substring(index); } return TimeZone.getDefault().getID(); } /** * Return a Date (long time) from a String description * * @param periodDuration * @return */ public static long getTimeInMillis(String periodDuration) { long time = 0; //we remove the 'P' periodDuration = periodDuration.substring(1); //we look if the period contains years (31536000000 ms) if (periodDuration.indexOf('Y') != -1) { int nbYear = Integer.parseInt(periodDuration.substring(0, periodDuration.indexOf('Y'))); time += nbYear * yearMS; periodDuration = periodDuration.substring(periodDuration.indexOf('Y') + 1); } //we look if the period contains months (2628000000 ms) if (periodDuration.indexOf('M') != -1 && (periodDuration.indexOf("T") == -1 || periodDuration.indexOf("T") > periodDuration.indexOf('M'))) { int nbMonth = Integer.parseInt(periodDuration.substring(0, periodDuration.indexOf('M'))); time += nbMonth * monthMS; periodDuration = periodDuration.substring(periodDuration.indexOf('M') + 1); } //we look if the period contains weeks (604800000 ms) if (periodDuration.indexOf('W') != -1) { int nbWeek = Integer.parseInt(periodDuration.substring(0, periodDuration.indexOf('W'))); time += nbWeek * weekMS; periodDuration = periodDuration.substring(periodDuration.indexOf('W') + 1); } //we look if the period contains days (86400000 ms) if (periodDuration.indexOf('D') != -1) { int nbDay = Integer.parseInt(periodDuration.substring(0, periodDuration.indexOf('D'))); time += nbDay * dayMS; periodDuration = periodDuration.substring(periodDuration.indexOf('D') + 1); } //if the periodDuration is not over we pass to the hours by removing 'T' if (periodDuration.indexOf('T') != -1) { periodDuration = periodDuration.substring(1); } //we look if the period contains hours (3600000 ms) if (periodDuration.indexOf('H') != -1) { int nbHour = Integer.parseInt(periodDuration.substring(0, periodDuration.indexOf('H'))); time += nbHour * hourMS; periodDuration = periodDuration.substring(periodDuration.indexOf('H') + 1); } //we look if the period contains minutes (60000 ms) if (periodDuration.indexOf('M') != -1) { int nbMin = Integer.parseInt(periodDuration.substring(0, periodDuration.indexOf('M'))); time += nbMin * minMS; periodDuration = periodDuration.substring(periodDuration.indexOf('M') + 1); } //we look if the period contains seconds (1000 ms) if (periodDuration.indexOf('S') != -1) { int nbSec = Integer.parseInt(periodDuration.substring(0, periodDuration.indexOf('S'))); time += nbSec * secondMS; periodDuration = periodDuration.substring(periodDuration.indexOf('S') + 1); } if (periodDuration.length() != 0) { throw new IllegalArgumentException("The period descritpion is malformed"); } return time; } /** * Convert a JulianDate to Date */ public static Date JulianToDate(final JulianDate jdt) { if (jdt == null) { return null; } Date response = null; int JGREG = 15 + 31 * (10 + 12 * 1582); int jalpha, ja, jb, jc, jd, je, year, month, day; ja = (int) jdt.getCoordinateValue().intValue(); if (ja >= JGREG) { jalpha = (int) (((ja - 1867216) - 0.25) / 36524.25); ja = ja + 1 + jalpha - jalpha / 4; } jb = ja + 1524; jc = (int) (6680.0 + ((jb - 2439870) - 122.1) / 365.25); jd = 365 * jc + jc / 4; je = (int) ((jb - jd) / 30.6001); day = jb - jd - (int) (30.6001 * je); month = je - 1; if (month > 12) { month = month - 12; } year = jc - 4715; if (month > 2) { year--; } if (year <= 0) { year--; } Calendar cal = Calendar.getInstance(); cal.set(year, month, day); response = cal.getTime(); return response; } /** * Convert a CalendarDate object to java.util.Date. * @param calDate * @return */ public static Date calendarDateToDate(final CalendarDate calDate) { if (calDate == null) { return null; } final Calendar calendar = Calendar.getInstance(); final DefaultCalendarDate caldate = (DefaultCalendarDate) calDate; if (caldate != null) { int[] cal = calDate.getCalendarDate(); int year = 0; int month = 0; int day = 0; if (cal.length > 3) { throw new IllegalArgumentException("The CalendarDate integer array is malformed ! see ISO 8601 format."); } else { year = cal[0]; if (cal.length > 0) { month = cal[1]; } if (cal.length > 1) { day = cal[2]; } calendar.set(year, month, day); return calendar.getTime(); } } return null; } /** * Convert a DateAndTime object to Date. * @param dateAndTime * @return */ public static Date dateAndTimeToDate(final DateAndTime dateAndTime) { if (dateAndTime == null) { return null; } final Calendar calendar = Calendar.getInstance(); final DefaultDateAndTime dateTime = (DefaultDateAndTime) dateAndTime; if (dateTime != null) { int[] cal = dateTime.getCalendarDate(); int year = 0; int month = 0; int day = 0; if (cal.length > 3) { throw new IllegalArgumentException("The CalendarDate integer array is malformed ! see ISO 8601 format."); } else { year = cal[0]; if (cal.length > 0) { month = cal[1]; } if (cal.length > 1) { day = cal[2]; } } Number[] clock = dateTime.getClockTime(); Number hour = 0; Number minute = 0; Number second = 0; if (clock.length > 3) { throw new IllegalArgumentException("The ClockTime Number array is malformed ! see ISO 8601 format."); } else { hour = clock[0]; if (clock.length > 0) { minute = clock[1]; } if (clock.length > 1) { second = clock[2]; } } calendar.set(year, month, day, hour.intValue(), minute.intValue(), second.intValue()); return calendar.getTime(); } return null; } /** * Convert a TemporalCoordinate object to Date. * @param temporalCoord */ public static Date temporalCoordToDate(final TemporalCoordinate temporalCoord) { if (temporalCoord == null) { return null; } final Calendar calendar = Calendar.getInstance(); final DefaultTemporalCoordinate timeCoord = (DefaultTemporalCoordinate) temporalCoord; Number value = timeCoord.getCoordinateValue(); if (timeCoord.getFrame() instanceof TemporalCoordinateSystem) { DefaultTemporalCoordinateSystem coordSystem = (DefaultTemporalCoordinateSystem) timeCoord.getFrame(); Date origin = coordSystem.getOrigin(); String interval = coordSystem.getInterval().toString(); Long timeInMS = 0L; if (interval.equals("year")) { timeInMS = value.longValue() * yearMS; } else if (interval.equals("month")) { timeInMS = value.longValue() * monthMS; } else if (interval.equals("week")) { timeInMS = value.longValue() * weekMS; } else if (interval.equals("day")) { timeInMS = value.longValue() * dayMS; } else if (interval.equals("hour")) { timeInMS = value.longValue() * hourMS; } else if (interval.equals("minute")) { timeInMS = value.longValue() * minMS; } else if (interval.equals("second")) { timeInMS = value.longValue() * secondMS; } else { throw new IllegalArgumentException(" The interval of TemporalCoordinateSystem for this TemporalCoordinate object is unknown ! "); } timeInMS = timeInMS + origin.getTime(); calendar.setTimeInMillis(timeInMS); return calendar.getTime(); } else { throw new IllegalArgumentException("The frame of this TemporalCoordinate object must be an instance of TemporalCoordinateSystem"); } } public static Date ordinalToDate(final OrdinalPosition ordinalPosition) { if (ordinalPosition == null) { return null; } final Calendar calendar = Calendar.getInstance(); if (ordinalPosition.getOrdinalPosition() != null) { Date beginEra = ordinalPosition.getOrdinalPosition().getBeginning(); Date endEra = ordinalPosition.getOrdinalPosition().getEnd(); Long middle = ((endEra.getTime() - beginEra.getTime()) / 2) + beginEra.getTime(); calendar.setTimeInMillis(middle); return calendar.getTime(); } else { return null; } } /** * This method returns the nearest Unit of a Duration. */ public static Unit getUnitFromDuration(Duration duration) { if (duration == null) { return null; } DefaultDuration duration_ = (DefaultDuration) duration; long mills = duration_.getTimeInMillis(); long temp = mills / yearMS; if (temp >= 1) { return NonSI.YEAR; } temp = mills / monthMS; if (temp >= 1) { return NonSI.MONTH; } temp = mills / weekMS; if (temp >= 1) { return NonSI.WEEK; } temp = mills / dayMS; if (temp >= 1) { return NonSI.DAY; } temp = mills / hourMS; if (temp >= 1) { return NonSI.HOUR; } temp = mills / minMS; if (temp >= 1) { return NonSI.MINUTE; } temp = mills / secondMS; if (temp >= 1) { return SI.SECOND; } return null; } }