1 /* Copyright 2002-2013 CS Systèmes d'Information 2 * Licensed to CS Systèmes d'Information (CS) under one or more 3 * contributor license agreements. See the NOTICE file distributed with 4 * this work for additional information regarding copyright ownership. 5 * CS licenses this file to You under the Apache License, Version 2.0 6 * (the "License"); you may not use this file except in compliance with 7 * the License. You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 */ 17 package org.orekit.time; 18 19 import java.io.Serializable; 20 21 import org.apache.commons.math3.util.FastMath; 22 import org.orekit.utils.Constants; 23 24 /** Holder for date and time components. 25 * <p>This class is a simple holder with no processing methods.</p> 26 * <p>Instance of this class are guaranteed to be immutable.</p> 27 * @see AbsoluteDate 28 * @see DateComponents 29 * @see TimeComponents 30 * @author Luc Maisonobe 31 */ 32 public class DateTimeComponents implements Serializable, Comparable<DateTimeComponents> { 33 34 /** Serializable UID. */ 35 private static final long serialVersionUID = 5061129505488924484L; 36 37 /** Date component. */ 38 private final DateComponents date; 39 40 /** Time component. */ 41 private final TimeComponents time; 42 43 /** Build a new instance from its components. 44 * @param date date component 45 * @param time time component 46 */ 47 public DateTimeComponents(final DateComponents date, final TimeComponents time) { 48 this.date = date; 49 this.time = time; 50 } 51 52 /** Build an instance from raw level components. 53 * @param year year number (may be 0 or negative for BC years) 54 * @param month month number from 1 to 12 55 * @param day day number from 1 to 31 56 * @param hour hour number from 0 to 23 57 * @param minute minute number from 0 to 59 58 * @param second second number from 0.0 to 60.0 (excluded) 59 * @exception IllegalArgumentException if inconsistent arguments 60 * are given (parameters out of range, february 29 for non-leap years, 61 * dates during the gregorian leap in 1582 ...) 62 */ 63 public DateTimeComponents(final int year, final int month, final int day, 64 final int hour, final int minute, final double second) 65 throws IllegalArgumentException { 66 this.date = new DateComponents(year, month, day); 67 this.time = new TimeComponents(hour, minute, second); 68 } 69 70 /** Build an instance from raw level components. 71 * @param year year number (may be 0 or negative for BC years) 72 * @param month month enumerate 73 * @param day day number from 1 to 31 74 * @param hour hour number from 0 to 23 75 * @param minute minute number from 0 to 59 76 * @param second second number from 0.0 to 60.0 (excluded) 77 * @exception IllegalArgumentException if inconsistent arguments 78 * are given (parameters out of range, february 29 for non-leap years, 79 * dates during the gregorian leap in 1582 ...) 80 */ 81 public DateTimeComponents(final int year, final Month month, final int day, 82 final int hour, final int minute, final double second) 83 throws IllegalArgumentException { 84 this.date = new DateComponents(year, month, day); 85 this.time = new TimeComponents(hour, minute, second); 86 } 87 88 /** Build an instance from raw level components. 89 * <p>The hour is set to 00:00:00.000.</p> 90 * @param year year number (may be 0 or negative for BC years) 91 * @param month month number from 1 to 12 92 * @param day day number from 1 to 31 93 * @exception IllegalArgumentException if inconsistent arguments 94 * are given (parameters out of range, february 29 for non-leap years, 95 * dates during the gregorian leap in 1582 ...) 96 */ 97 public DateTimeComponents(final int year, final int month, final int day) 98 throws IllegalArgumentException { 99 this.date = new DateComponents(year, month, day); 100 this.time = TimeComponents.H00; 101 } 102 103 /** Build an instance from raw level components. 104 * <p>The hour is set to 00:00:00.000.</p> 105 * @param year year number (may be 0 or negative for BC years) 106 * @param month month enumerate 107 * @param day day number from 1 to 31 108 * @exception IllegalArgumentException if inconsistent arguments 109 * are given (parameters out of range, february 29 for non-leap years, 110 * dates during the gregorian leap in 1582 ...) 111 */ 112 public DateTimeComponents(final int year, final Month month, final int day) 113 throws IllegalArgumentException { 114 this.date = new DateComponents(year, month, day); 115 this.time = TimeComponents.H00; 116 } 117 118 /** Build an instance from a seconds offset with respect to another one. 119 * @param reference reference date/time 120 * @param offset offset from the reference in seconds 121 * @see #offsetFrom(DateTimeComponents) 122 */ 123 public DateTimeComponents(final DateTimeComponents reference, 124 final double offset) { 125 126 // extract linear data from reference date/time 127 int day = reference.getDate().getJ2000Day(); 128 double seconds = reference.getTime().getSecondsInDay(); 129 130 // apply offset 131 seconds += offset; 132 133 // fix range 134 final int dayShift = (int) FastMath.floor(seconds / Constants.JULIAN_DAY); 135 seconds -= Constants.JULIAN_DAY * dayShift; 136 day += dayShift; 137 138 // set up components 139 this.date = new DateComponents(day); 140 this.time = new TimeComponents(seconds); 141 142 } 143 144 /** Parse a string in ISO-8601 format to build a date/time. 145 * <p>The supported formats are all date formats supported by {@link DateComponents#parseDate(String)} 146 * and all time formats supported by {@link TimeComponents#parseTime(String)} separated 147 * by the standard time separator 'T', or date components only (in which case a 00:00:00 hour is 148 * implied). Typical examples are 2000-01-01T12:00:00Z or 1976W186T210000. 149 * </p> 150 * @param string string to parse 151 * @return a parsed date/time 152 * @exception IllegalArgumentException if string cannot be parsed 153 */ 154 public static DateTimeComponents parseDateTime(final String string) { 155 156 // is there a time ? 157 final int tIndex = string.indexOf('T'); 158 if (tIndex > 0) { 159 return new DateTimeComponents(DateComponents.parseDate(string.substring(0, tIndex)), 160 TimeComponents.parseTime(string.substring(tIndex + 1))); 161 } 162 163 return new DateTimeComponents(DateComponents.parseDate(string), TimeComponents.H00); 164 165 } 166 167 /** Compute the seconds offset between two instances. 168 * @param dateTime dateTime to subtract from the instance 169 * @return offset in seconds between the two instants 170 * (positive if the instance is posterior to the argument) 171 * @see #DateTimeComponents(DateTimeComponents, double) 172 */ 173 public double offsetFrom(final DateTimeComponents dateTime) { 174 final int dateOffset = date.getJ2000Day() - dateTime.date.getJ2000Day(); 175 final double timeOffset = time.getSecondsInDay() - dateTime.time.getSecondsInDay(); 176 return Constants.JULIAN_DAY * dateOffset + timeOffset; 177 } 178 179 /** Get the date component. 180 * @return date component 181 */ 182 public DateComponents getDate() { 183 return date; 184 } 185 186 /** Get the time component. 187 * @return time component 188 */ 189 public TimeComponents getTime() { 190 return time; 191 } 192 193 /** {@inheritDoc} */ 194 public int compareTo(final DateTimeComponents other) { 195 final int dateComparison = date.compareTo(other.date); 196 if (dateComparison < 0) { 197 return -1; 198 } else if (dateComparison > 0) { 199 return 1; 200 } 201 return time.compareTo(other.time); 202 } 203 204 /** {@inheritDoc} */ 205 public boolean equals(final Object other) { 206 try { 207 final DateTimeComponents otherDateTime = (DateTimeComponents) other; 208 return (otherDateTime != null) && 209 date.equals(otherDateTime.date) && time.equals(otherDateTime.time); 210 } catch (ClassCastException cce) { 211 return false; 212 } 213 } 214 215 /** {@inheritDoc} */ 216 public int hashCode() { 217 return (date.hashCode() << 16) ^ time.hashCode(); 218 } 219 220 /** Return a string representation of this pair. 221 * <p>The format used is ISO8601.</p> 222 * @return string representation of this pair 223 */ 224 public String toString() { 225 return date.toString() + 'T' + time.toString(); 226 } 227 228 } 229