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