/* * 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.reference; import java.util.Collection; import java.util.GregorianCalendar; import org.geotools.metadata.iso.citation.Citations; import org.geotools.referencing.NamedIdentifier; import org.geotools.util.Utilities; import org.geotools.temporal.object.DefaultCalendarDate; import org.geotools.temporal.object.DefaultDateAndTime; import org.geotools.temporal.object.DefaultJulianDate; import org.geotools.util.SimpleInternationalString; import org.opengis.temporal.Calendar; import org.opengis.temporal.CalendarDate; import org.opengis.temporal.CalendarEra; import org.opengis.temporal.Clock; import org.opengis.temporal.ClockTime; import org.opengis.temporal.JulianDate; import org.opengis.metadata.extent.Extent; import org.opengis.referencing.ReferenceIdentifier; import org.opengis.temporal.DateAndTime; import org.opengis.temporal.TemporalCoordinateSystem; /** * * @author Mehdi Sidhoum (Geomatys) * * * @source $URL$ */ public class DefaultCalendar extends DefaultTemporalReferenceSystem implements Calendar { /** * Collection of CalendarEra which uses this Calendar as a reference. */ private Collection<CalendarEra> basis; /** * */ private Clock timeBasis; /** * Creates a new instance of DefaultCalendar * @param name * @param domainOfValidity */ public DefaultCalendar(ReferenceIdentifier name, Extent domainOfValidity) { super(name, domainOfValidity); } /** * Convert a TemporalPosition representing by a CalendarDate and a ClockTime to a Julian date. * @param calDate * @param time * @return */ public JulianDate dateTrans(CalendarDate calDate, ClockTime time) { JulianDate response; if (calDate != null && time != null) { DateAndTime dateAndTime = new DefaultDateAndTime(this, calDate.getIndeterminatePosition(), calDate.getCalendarEraName(), calDate.getCalendarDate(), time.getClockTime()); return dateTrans(dateAndTime); } GregorianCalendar gc = new GregorianCalendar(-4713, 1, 1); gc.set(GregorianCalendar.ERA, GregorianCalendar.BC); final int julianGre = 15 + 31 * (10 + 12 * 1582); Number coordinateValue = 0; TemporalCoordinateSystem refSystem = new DefaultTemporalCoordinateSystem(new NamedIdentifier(Citations.CRS, new SimpleInternationalString("Julian calendar")), null, gc.getTime(), new SimpleInternationalString("day")); 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]; } int julianYear = year; if (year < 0) { julianYear++; } int julianMonth = month; if (month > 2) { julianMonth++; } else { julianYear--; julianMonth += 13; } double julian = (java.lang.Math.floor(365.25 * julianYear) + java.lang.Math.floor(30.6001 * julianMonth) + day + 1720995.0); if (day + 31 * (month + 12 * year) >= julianGre) { // change over to Gregorian calendar int ja = (int) (0.01 * julianYear); julian += 2 - ja + (0.25 * ja); } coordinateValue = java.lang.Math.floor(julian); response = new DefaultJulianDate(refSystem, null, coordinateValue); return response; } } else if (time != null) { Number[] clk = time.getClockTime(); Number hour = 0; Number minute = 0; Number second = 0; if (clk.length > 3) { throw new IllegalArgumentException("The ClockTime Number array is malformed ! see ISO 8601 format."); } else { hour = clk[0]; if (clk.length > 0) { minute = clk[1]; } if (clk.length > 1) { second = clk[2]; } double julian = ((hour.doubleValue() - 12) / 24) + (minute.doubleValue() / 1440) + (second.doubleValue() / 86400); coordinateValue = julian; response = new DefaultJulianDate(refSystem, null, coordinateValue); return response; } } else { throw new IllegalArgumentException("the both CalendarDate and ClockTime cannot be null !"); } } /** * This method is called by the Overrided method dateTrans() which take 2 arguments CalendarDate and ClockTime. * @param dateAndTime * @return */ public JulianDate dateTrans(DateAndTime dateAndTime) { JulianDate response; GregorianCalendar gc = new GregorianCalendar(-4713, 1, 1); gc.set(GregorianCalendar.ERA, GregorianCalendar.BC); final int julianGre = 15 + 31 * (10 + 12 * 1582); TemporalCoordinateSystem refSystem = new DefaultTemporalCoordinateSystem(new NamedIdentifier(Citations.CRS, new SimpleInternationalString("Julian calendar")), null, gc.getTime(), new SimpleInternationalString("day")); Number coordinateValue = 0; int year = 0, month = 0, day = 0; Number hour = 0, minute = 0, second = 0; if (dateAndTime == null) { throw new IllegalArgumentException("The DateAndTime cannot be null ! "); } if (dateAndTime.getCalendarDate() != null) { int[] cal = dateAndTime.getCalendarDate(); 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]; } int julianYear = year; if (year < 0) { julianYear++; } int julianMonth = month; if (month > 2) { julianMonth++; } else { julianYear--; julianMonth += 13; } double julian = (java.lang.Math.floor(365.25 * julianYear) + java.lang.Math.floor(30.6001 * julianMonth) + day + 1720995.0); if (day + 31 * (month + 12 * year) >= julianGre) { int ja = (int) (0.01 * julianYear); julian += 2 - ja + (0.25 * ja); } coordinateValue = java.lang.Math.floor(julian); } } if (dateAndTime.getClockTime() != null) { Number[] clk = dateAndTime.getClockTime(); if (clk.length > 3) { throw new IllegalArgumentException("The ClockTime Number array is malformed ! see ISO 8601 format."); } else { hour = clk[0]; if (clk.length > 0) { minute = clk[1]; } if (clk.length > 1) { second = clk[2]; } double julian = ((hour.doubleValue() - 12) / 24) + (minute.doubleValue() / 1440) + (second.doubleValue() / 86400); coordinateValue = coordinateValue.doubleValue() + julian; } } response = new DefaultJulianDate(refSystem, null, coordinateValue); return response; } /** * Convert a JulianDate to CalendarDate * @param jdt * @return */ public CalendarDate julTrans(JulianDate jdt) { if (jdt == null) return null; CalendarDate 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--; } int[] calendarDate = {year, month, day}; response = new DefaultCalendarDate(this, null, null, calendarDate); return response; } public Collection<CalendarEra> getBasis() { return basis; } public Clock getClock() { return timeBasis; } public void setBasis(Collection<CalendarEra> basis) { this.basis = basis; } public void setClock(Clock clock) { this.timeBasis = clock; } @Override public boolean equals(final Object object) { if (object == this) { return true; } if (object instanceof DefaultCalendar && super.equals(object)) { final DefaultCalendar that = (DefaultCalendar) object; return Utilities.equals(this.basis, that.basis) && Utilities.equals(this.timeBasis, that.timeBasis); } return false; } @Override public int hashCode() { int hash = super.hashCode(); hash = 37 * hash + (this.timeBasis != null ? this.timeBasis.hashCode() : 0); hash = 37 * hash + (this.basis != null ? this.basis.hashCode() : 0); return hash; } @Override public String toString() { StringBuilder s = new StringBuilder("Calendar:").append('\n'); if (timeBasis != null) { s.append("clock:").append(timeBasis).append('\n'); } if (basis != null) { s.append("basis:").append(basis).append('\n'); } return super.toString().concat("\n").concat(s.toString()); } }