Line data Source code
1 : /*
2 : * ALMA - Atacama Large Millimeter Array
3 : * (c) European Southern Observatory, 2002
4 : * (c) Associated Universities Inc., 2002
5 : * Copyright by ESO (in the framework of the ALMA collaboration),
6 : * Copyright by AUI (in the framework of the ALMA collaboration),
7 : * All rights reserved.
8 : *
9 : * This library is free software; you can redistribute it and/or
10 : * modify it under the terms of the GNU Lesser General Public
11 : * License as published by the Free software Foundation; either
12 : * version 2.1 of the License, or (at your option) any later version.
13 : *
14 : * This library is distributed in the hope that it will be useful,
15 : * but WITHOUT ANY WARRANTY, without even the implied warranty of
16 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 : * Lesser General Public License for more details.
18 : *
19 : * You should have received a copy of the GNU Lesser General Public
20 : * License along with this library; if not, write to the Free Software
21 : * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
22 : * MA 02111-1307 USA
23 : *
24 : * File ArrayTime.cpp
25 : */
26 :
27 : #include <cmath>
28 : using std::fmod;
29 :
30 : #include <alma/ASDM/ArrayTime.h>
31 :
32 : #include <alma/ASDM/DoubleWrapper.h>
33 : #include <alma/ASDM/LongWrapper.h>
34 : #include <alma/ASDM/IntegerWrapper.h>
35 : #include <alma/ASDM/InvalidArgumentException.h>
36 : #include <alma/ASDM/NumberFormatException.h>
37 :
38 : using namespace std;
39 :
40 : namespace asdm {
41 :
42 : #define UTCCorrectionLength 32
43 : static const UTCCorrection xUTCCorrectionTable [UTCCorrectionLength] = {
44 : // JD TAI-UTC
45 : UTCCorrection(2438395.5, 3.2401300),
46 : UTCCorrection(2438486.5, 3.3401300),
47 : UTCCorrection(2438639.5, 3.4401300),
48 : UTCCorrection(2438761.5, 3.5401300),
49 : UTCCorrection(2438820.5, 3.6401300),
50 : UTCCorrection(2438942.5, 3.7401300),
51 : UTCCorrection(2439004.5, 3.8401300),
52 : UTCCorrection(2439126.5, 4.3131700),
53 : UTCCorrection(2439887.5, 4.2131700),
54 : UTCCorrection(2441317.5, 10.0),
55 : UTCCorrection(2441499.5, 11.0),
56 : UTCCorrection(2441683.5, 12.0),
57 : UTCCorrection(2442048.5, 13.0),
58 : UTCCorrection(2442413.5, 14.0),
59 : UTCCorrection(2442778.5, 15.0),
60 : UTCCorrection(2443144.5, 16.0),
61 : UTCCorrection(2443509.5, 17.0),
62 : UTCCorrection(2443874.5, 18.0),
63 : UTCCorrection(2444239.5, 19.0),
64 : UTCCorrection(2444786.5, 20.0),
65 : UTCCorrection(2445151.5, 21.0),
66 : UTCCorrection(2445516.5, 22.0),
67 : UTCCorrection(2446247.5, 23.0),
68 : UTCCorrection(2447161.5, 24.0),
69 : UTCCorrection(2447892.5, 25.0),
70 : UTCCorrection(2448257.5, 26.0),
71 : UTCCorrection(2448804.5, 27.0),
72 : UTCCorrection(2449169.5, 28.0),
73 : UTCCorrection(2449534.5, 29.0),
74 : UTCCorrection(2450083.5, 30.0),
75 : UTCCorrection(2450630.5, 31.0),
76 : UTCCorrection(2451179.5, 32.0)
77 : };
78 :
79 : const UTCCorrection *ArrayTime::UTCCorrectionTable = &xUTCCorrectionTable[0];
80 : const UTCCorrection ArrayTime::UTCLast = UTCCorrectionTable [UTCCorrectionLength - 1];
81 :
82 : const double ArrayTime::unitsInADay = 86400000000000.0;
83 : const double ArrayTime::unitsInADayDiv100 = 864000000000.0;
84 : const double ArrayTime::julianDayOfBase = 2400000.5;
85 :
86 : /**
87 : * Return true if the specified year is a leap year.
88 : * @param year the year in the Gregorian calendar.
89 : * @return true if the specified year is a leap year.
90 : */
91 0 : bool ArrayTime::isLeapYear(int year) {
92 0 : if (year % 4 != 0)
93 0 : return false;
94 0 : if (year % 100 == 0 && year % 400 != 0)
95 0 : return false;
96 0 : return true;
97 : }
98 :
99 : /**
100 : * Return the Modified Julian day, given the Julian day.
101 : * @param jd The Julian day
102 : * @return The Modified Julian day
103 : */
104 0 : double ArrayTime::getMJD(double jd) {
105 0 : return jd - 2400000.5;
106 : }
107 :
108 : /**
109 : * Return the Julian day, given the Modified Julian day.
110 : * @param mjd The modified Julian day
111 : * @return the Julian day
112 : */
113 0 : double ArrayTime::getJD(double mjd) {
114 0 : return mjd + 2400000.5;
115 : }
116 :
117 : /**
118 : * Generate a new Time by adding an Interval
119 : * to the specified Time.
120 : * @param time The base Time
121 : * @param interval The interval to be added to the base time.
122 : * @return A new Time formed by adding an Interval
123 : * to the specified Time.
124 : */
125 0 : ArrayTime ArrayTime::add(const ArrayTime &time, const Interval & /* interval */) {
126 0 : ArrayTime t(time);
127 : //t.add(interval);
128 0 : return t;
129 : }
130 :
131 : /**
132 : * Generate a new Time by subtracting an Interval
133 : * from the specified Time.
134 : * @param time The base Time
135 : * @param interval The interval to be subtracted from the base time.
136 : * @return A new Time formed by subtracting an Interval
137 : * from the specified Time.
138 : */
139 0 : ArrayTime ArrayTime::sub(const ArrayTime &time, const Interval & /* interval */) {
140 0 : ArrayTime t(time);
141 : //t.sub(interval);
142 0 : return t;
143 : }
144 :
145 0 : ArrayTime ArrayTime::getArrayTime(StringTokenizer &t) {
146 0 : int64_t value = Long::parseLong(t.nextToken());
147 0 : return ArrayTime (value);
148 : }
149 :
150 : /**
151 : * Create a default Time, initialized to a value of zero.
152 : *
153 : */
154 0 : ArrayTime::ArrayTime() : Interval(0LL) {
155 0 : }
156 :
157 : /**
158 : * Create a Time from a string, which can be in one of three
159 : * formats:
160 : * <ul>
161 : * <li>A FITS formatted string,
162 : * <li>A modified Julian day, or,
163 : * <li>An integer representing the number of
164 : * nanoseconds since 15 October 1582 00:00:00 UTC.
165 : * </ul>
166 : * <p>
167 : * If the format is a FITS formatted string, its format must be
168 : * of the following form:
169 : * "YYYY-MM-DDThh:mm:ss.ssss"
170 : * Leading zeros are required if months, days, hours, minutes, or seconds
171 : * are single digits. The value for months ranges from "01" to "12".
172 : * The "T" separting the data and time values is optional (which is a
173 : * relaxation of the strict FITS standard). If the "T" is
174 : * not present, then a space MUST be present.
175 : * <p>
176 : * If the format is a modified Julian day, then the string value
177 : * must be in the form of a double which MUST include a decimal point.
178 : * <p>
179 : * If the format is an interger, then it MUST represent the number of
180 : * nanoseconds since 17 November 1858 00:00:00 UTC, the beginning of the
181 : * modified Julian Day.
182 : *
183 : * @param s The string containing the initial value.
184 : */
185 0 : ArrayTime::ArrayTime (const string &s) {
186 0 : int64_t u = 0L;
187 0 : if (s.find(':') != string::npos)
188 0 : u = FITSString(s);
189 : else {
190 0 : if (s.find('.') != string::npos) {
191 0 : u = mjdToUnit(Double::parseDouble(s));
192 : } else {
193 0 : u = Long::parseLong(s);
194 : }
195 : }
196 0 : *this = u;
197 0 : }
198 :
199 : /**
200 : * Create a Time that is initialized to a specified Time.
201 : * @param t
202 : */
203 0 : ArrayTime::ArrayTime(const ArrayTime &t) : Interval(t.get()) {
204 0 : }
205 :
206 : #ifndef WITHOUT_ACS
207 : /**
208 : * Create a Time from an IDL time object.
209 : * @param t The IDL time object.
210 : */
211 : ArrayTime::ArrayTime (const asdmIDLTypes::IDLArrayTime &t) {
212 : *this = t.value;
213 : }
214 : #endif
215 :
216 : /**
217 : * Create a Time by specifying the year, month, and day plus the fraction of a day.
218 : * @param year The yeay
219 : * @param month The month
220 : * @param day the day (and time)
221 : */
222 0 : ArrayTime::ArrayTime(int year, int month, double day) :
223 0 : Interval(init(year,month,day)) {
224 0 : }
225 :
226 : /**
227 : * Create a Time by specifying the calendar date and the time.
228 : * @param year
229 : * @param month
230 : * @param day
231 : * @param hour
232 : * @param minute
233 : * @param second
234 : */
235 0 : ArrayTime::ArrayTime(int year, int month, int day, int hour, int minute, double second) : Interval(0L) {
236 0 : if (hour < 0 || hour > 23 || minute < 0 || minute > 59 || second < 0.0 || second >= 60.0) {
237 0 : throw InvalidArgumentException("Invalid time");
238 : }
239 0 : *this = init(year,month,(double)(day + (((((second / 60.0) + minute) / 60.0) + hour) / 24.0)));
240 0 : }
241 :
242 : /**
243 : * Create a Time by specifying the modified Julian day.
244 : * @param modifiedJulianDay the modified Julian day, including fractions thereof.
245 : */
246 0 : ArrayTime::ArrayTime(double modifiedJulianDay) :
247 0 : Interval(mjdToUnit(modifiedJulianDay)) {
248 0 : }
249 :
250 : /**
251 : * Create a Time by specifying the modified Julian day plus an additional factor
252 : * that designates the number of seconds and fractions in a day.
253 : * @param modifiedJulianDay the Modified Julian day expressed as an interger
254 : * @param secondsInADay The number of seconds (with fractions) in this day.
255 : */
256 0 : ArrayTime::ArrayTime(int modifiedJulianDay, double secondsInADay) :
257 0 : Interval(modifiedJulianDay * 8640000000000LL + (long)(secondsInADay * 100000000.0)) {
258 0 : }
259 :
260 : /**
261 : * Create a Time by specifying the number of
262 : * nanoseconds since 17 November 1858 00:00:00 UTC, the beginning of the
263 : * modified Julian Day.
264 : * @param tensOfNanoseconds The number of
265 : * nanoseconds since 17 November 1858 00:00:00 UTC, the beginning of the
266 : * modified Julian Day.
267 : */
268 0 : ArrayTime::ArrayTime(int64_t nanoseconds) : Interval (nanoseconds) {
269 0 : }
270 :
271 : /**
272 : * Return the Julian day.
273 : * @return The Julian day as a double.
274 : */
275 0 : double ArrayTime::getJD() const {
276 0 : return unitToJD(get());
277 : }
278 :
279 : /**
280 : * Return the Modified Julian day.
281 : * @return The Modified Julian day as a double.
282 : */
283 0 : double ArrayTime::getMJD() const {
284 0 : return unitToMJD(get());
285 : }
286 :
287 : #ifndef WITHOUT_ACS
288 : /**
289 : * Return an IDL Time object.
290 : * @return An IDL Time object.
291 : */
292 : asdmIDLTypes::IDLArrayTime ArrayTime::toIDLArrayTime() const {
293 : asdmIDLTypes::IDLArrayTime x;
294 : x.value = get();
295 : return x;
296 : }
297 : #endif
298 :
299 : /**
300 : * Return this Time as a FITS formatted string, which is of the
301 : * form "YYYY-MM-DDThh:mm:ss.ssss".
302 : * @return This Time as a FITS formatted string.
303 : */
304 0 : string ArrayTime::toFITS() const {
305 0 : int *unit = getDateTime();
306 0 : int yy = unit[0];
307 0 : int mm = unit[1];
308 0 : int dd = unit[2];
309 0 : int hh = unit[3];
310 0 : int min = unit[4];
311 0 : int sec = unit[5];
312 0 : string s = Integer::toString(yy); s += '-';
313 0 : if (mm < 10) s += '0';
314 0 : s += Integer::toString(mm); s += '-';
315 0 : if (dd < 10) s += '0';
316 0 : s += Integer::toString(dd); s += 'T';
317 0 : if (hh < 10) s += '0';
318 0 : s += Integer::toString(hh); s += ':';
319 0 : if (min < 10) s += '0';
320 0 : s += Integer::toString(min); s += ':';
321 0 : if (sec < 10) s += '0';
322 0 : s += Integer::toString(sec);
323 : // apply fractions of a second
324 0 : string frac = Integer::toString(unit[6]);
325 0 : s += '.';
326 : // The statement below is sensitive to the number of significant
327 : // digits in a fraction. If units are nanoseconds,
328 : // then we need we will have 9 significant digits in a fraction
329 : // string.
330 0 : string tmp = "0000000000000000";
331 0 : s += tmp.substr(0,numberSigDigitsInASecond - frac.length());
332 0 : s += frac;
333 0 : delete[] unit;
334 0 : return s;
335 0 : }
336 :
337 0 : void ArrayTime::toBin(EndianOSStream& eoss) {
338 0 : eoss.writeLongLong( get());
339 0 : }
340 :
341 0 : void ArrayTime::toBin(const vector<ArrayTime>& arrayTime, EndianOSStream& eoss) {
342 0 : eoss.writeInt((int) arrayTime.size());
343 0 : for (unsigned int i = 0; i < arrayTime.size(); i++)
344 0 : eoss.writeLongLong(arrayTime.at(i).get());
345 0 : }
346 :
347 0 : void ArrayTime::toBin(const vector<vector<ArrayTime> >& arrayTime, EndianOSStream& eoss) {
348 0 : eoss.writeInt((int) arrayTime.size());
349 0 : eoss.writeInt((int) arrayTime.at(0).size());
350 0 : for (unsigned int i = 0; i < arrayTime.size(); i++)
351 0 : for (unsigned int j = 0; j < arrayTime.at(0).size(); j++)
352 0 : eoss.writeLongLong(arrayTime.at(i).at(j).get());
353 0 : }
354 :
355 0 : void ArrayTime::toBin(const vector< vector<vector<ArrayTime> > >& arrayTime, EndianOSStream& eoss) {
356 0 : eoss.writeInt((int) arrayTime.size());
357 0 : eoss.writeInt((int) arrayTime.at(0).size());
358 0 : eoss.writeInt((int) arrayTime.at(0).at(0).size());
359 0 : for (unsigned int i = 0; i < arrayTime.size(); i++)
360 0 : for (unsigned int j = 0; j < arrayTime.at(0).size(); j++)
361 0 : for (unsigned int k = 0; k < arrayTime.at(0).at(0).size(); j++)
362 0 : eoss.writeLongLong(arrayTime.at(i).at(j).at(k).get());
363 0 : }
364 :
365 0 : ArrayTime ArrayTime::fromBin(EndianIStream & eis) {
366 0 : return ArrayTime(eis.readLongLong());
367 : }
368 :
369 0 : vector<ArrayTime> ArrayTime::from1DBin(EndianIStream & eis) {
370 0 : int dim1 = eis.readInt();
371 0 : vector<ArrayTime> result;
372 0 : for (int i = 0; i < dim1; i++)
373 0 : result.push_back(ArrayTime(eis.readLongLong()));
374 0 : return result;
375 0 : }
376 :
377 0 : vector<vector<ArrayTime > > ArrayTime::from2DBin(EndianIStream & eis) {
378 0 : int dim1 = eis.readInt();
379 0 : int dim2 = eis.readInt();
380 0 : vector< vector<ArrayTime> >result;
381 0 : vector <ArrayTime> aux;
382 0 : for (int i = 0; i < dim1; i++) {
383 0 : aux.clear();
384 0 : for (int j = 0; j < dim2; j++)
385 0 : aux.push_back(ArrayTime(eis.readLongLong()));
386 0 : result.push_back(aux);
387 : }
388 0 : return result;
389 0 : }
390 :
391 0 : vector<vector<vector<ArrayTime > > > ArrayTime::from3DBin(EndianIStream & eis) {
392 0 : int dim1 = eis.readInt();
393 0 : int dim2 = eis.readInt();
394 0 : int dim3 = eis.readInt();
395 0 : vector<vector< vector<ArrayTime> > >result;
396 0 : vector < vector<ArrayTime> >aux1;
397 0 : vector <ArrayTime> aux2;
398 0 : for (int i = 0; i < dim1; i++) {
399 0 : aux1.clear();
400 0 : for (int j = 0; j < dim2; j++) {
401 0 : aux2.clear();
402 0 : for (int k = 0; k < dim3; k++)
403 0 : aux2.push_back(ArrayTime(eis.readLongLong()));
404 0 : aux1.push_back(aux2);
405 : }
406 0 : result.push_back(aux1);
407 : }
408 0 : return result;
409 0 : }
410 :
411 : /**
412 : * Return this time as an array of integers denoting the following:
413 : * <ul>
414 : * <li>year,
415 : * <li>month (varies from 1 to 12),
416 : * <li>day (varies from 1 to 28, 29, 30, or 31),
417 : * <li>hour (varies from 0 to 23),
418 : * <li>minute (varies from 0 to 59),
419 : * <li>second (varies from 0 to 59), and
420 : * <li>the number of nanoseconds that remain in this fraction of a second.
421 : * </ul>
422 : * @return This time as an array of integers denoting year, month, day, hour, minute
423 : * second, and fraction of a second.
424 : */
425 0 : int *ArrayTime::getDateTime() const {
426 0 : int *n = new int [7];
427 0 : int64_t fractionOfADay = get() % unitsInADayL;
428 0 : if (fractionOfADay < 0)
429 0 : fractionOfADay = unitsInADayL - fractionOfADay;
430 0 : int64_t nsec = fractionOfADay / unitsInASecond;
431 0 : n[6] = (int)(fractionOfADay - (nsec * 1000000000LL));
432 0 : int64_t nmin = nsec / 60L;
433 0 : n[5] = (int)(nsec - nmin * 60L);
434 0 : int64_t nhr = nmin / 60L;
435 0 : n[4] = (int)(nmin - nhr * 60L);
436 0 : n[3] = (int)nhr;
437 :
438 0 : double jd = unitToJD(get());
439 :
440 : // For this algorithm see Meeus, chapter 7, p. 63.
441 0 : double x = jd + 0.5; // Make the 12h UT adjustment.
442 0 : int Z = (int)x;
443 0 : double F = x - Z;
444 0 : int A = Z;
445 0 : int alpha = 0;
446 0 : if (Z >= 2299161) {
447 0 : alpha = (int)((Z - 1867216.25) / 36524.25);
448 0 : A = Z + 1 + alpha - (int)(alpha / 4);
449 : }
450 0 : int B = A + 1524;
451 0 : int C = (int)((B - 122.1) / 365.25);
452 0 : int D = (int)(365.25 * C);
453 0 : int E = (int)((B - D) / 30.6001);
454 0 : double day = B - D - (int)(30.6001 * E) + F;
455 0 : int month = (E < 14) ? E - 1 : E - 13;
456 0 : int year = (month > 2) ? C - 4716 : C - 4715;
457 :
458 0 : n[2] = (int)day;
459 0 : n[1] = month;
460 0 : n[0] = year;
461 :
462 0 : return n;
463 : }
464 :
465 : /**
466 : * Return the time of day in hours and fractions thereof.
467 : * @return The time of day in hours.
468 : */
469 0 : double ArrayTime::getTimeOfDay() const {
470 0 : double x = unitToJD(get()) + 0.5;
471 0 : return (x - (int)x) * 24.0;
472 : }
473 :
474 : /**
475 : * Return the day number of the week of this Time.
476 : * The day numbers are 0-Sunday, 1-Monday, 2-Tuesday,
477 : * 3-Wednesday, 4-Thursday, 5-Friday, and 6-Saturday.
478 : * @return The day number of the week of this Time.
479 : */
480 0 : int ArrayTime::getDayOfWeek() const {
481 0 : return ((int)(unitToJD(get()) + 1.5)) % 7;
482 : }
483 :
484 : /**
485 : * Return the day number of the year of this Time.
486 : * @return The day number of the year of this Time.
487 : */
488 0 : int ArrayTime::getDayOfYear() const {
489 0 : int *n = getDateTime();
490 0 : int year = n[0];
491 0 : int month = n[1];
492 0 : int day = n[2];
493 0 : delete n;
494 0 : return ((275 * month) / 9) -
495 0 : ((isLeapYear(year) ? 1 : 2) * ((month + 9) / 12)) +
496 0 : day - 30;
497 : }
498 :
499 : /**
500 : * Return the time of day as a string, in the form
501 : * "hh:mm:ss".
502 : * @return The time of day as a string.
503 : */
504 0 : string ArrayTime::timeOfDayToString() const {
505 0 : int *n = getDateTime();
506 0 : int hh = n[3];
507 0 : int min = n[4];
508 0 : int sec = n[5];
509 0 : string s = "";
510 0 : if (hh < 10) s += '0'; else s += Integer::toString(hh); s += ':';
511 0 : if (min < 10) s += '0'; else s += Integer::toString(min); s += ':';
512 0 : if (sec < 10) s += '0'; else s += Integer::toString(sec);
513 0 : delete n;
514 0 : return s;
515 0 : }
516 :
517 : /**
518 : * Return the local sidereal time for this Time
519 : * in hours and fractions of an hour at the specified longitude.
520 : * @param longitudeInHours The desired longitude in hours.
521 : * @return The local sidereal time in hours.
522 : */
523 0 : double ArrayTime::getLocalSiderealTime(double longitudeInHours) const {
524 0 : return getGreenwichMeanSiderealTime() - longitudeInHours;
525 : }
526 :
527 : /**
528 : * Return the Greenwich mean sidereal time for this Time
529 : * in hours and fractions of an hour.
530 : * @return The Greenwich mean sidereal time in hours.
531 : */
532 0 : double ArrayTime::getGreenwichMeanSiderealTime() const {
533 0 : double jd = unitToJD(get());
534 0 : double t0 = jd - 2451545.0;
535 0 : double t = t0 / 36525.0;
536 0 : double tt = t * t;
537 0 : double x = (280.46061837 +
538 0 : 360.98564736629 * t0 +
539 0 : tt * (0.000387933 - (t / 38710000.0))) / 15.0 ;
540 0 : double y = fmod(x,24.0);
541 0 : if (y < 0)
542 0 : y = 24.0 + y;
543 0 : return y;
544 : }
545 :
546 0 : int64_t ArrayTime::init(int year, int month, double day) {
547 : // For this algorithm see Meeus, chapter 7, p. 61.
548 0 : int iday = (int)day;
549 0 : if (month < 1 || month > 12)
550 0 : throw InvalidArgumentException ("Illegal value of month");
551 0 : if ( (iday < 1 || iday > 31) ||
552 0 : ((month == 4 || month == 6 || month == 9 || month == 11) && iday > 30) ||
553 0 : (month == 2 && (iday > ((isLeapYear(year) ? 29 : 28)))) )
554 0 : throw InvalidArgumentException ("Illegal value of day");
555 0 : if (month <= 2) {
556 0 : --year;
557 0 : month += 12;
558 : }
559 0 : int A = year / 100;
560 0 : int B = 2 - A + (A / 4);
561 0 : double jd = (int)(365.25 * (year + 4716)) + (int)(30.6001 * (month + 1)) + iday + B - 1524.5;
562 0 : int64_t u = jdToUnit(jd);
563 : // Now add the fraction of a day.
564 0 : u += (int64_t)((day - iday) * unitsInADay + 0.5);
565 0 : return u;
566 : }
567 :
568 0 : int64_t ArrayTime::init(int year, int month, int day, int hour, int minute, double second) {
569 0 : if (hour < 0 || hour > 23 || minute < 0 || minute > 59 || second < 0.0 || second >= 60.0) {
570 0 : throw InvalidArgumentException("Invalid time");
571 : }
572 0 : return init(year,month,(double)(day + (((((second / 60.0) + minute) / 60.0) + hour) / 24.0)));
573 : }
574 :
575 : /**
576 : * Return a unit of time, as a long, from a FITS-formatted string that
577 : * specifies the time. The format must be of the form:
578 : * YYYY-MM-DDThh:mm:ss.ssss
579 : * Leading zeros are required if months, days, hours, minutes, or seconds
580 : * are single digits. The value for months ranges from "01" to "12".
581 : * The "T" separting the data and time values is optional. If the "T" is
582 : * not present, then a space MUST be present.
583 : *
584 : * An IllegalArgumentException is thrown is the string is not a valid
585 : * time.
586 : */
587 0 : int64_t ArrayTime::FITSString(string t) const {
588 0 : if (t.length() < 19 || t.at(4) != '-' || t.at(7) != '-' ||
589 0 : (t.at(10) != 'T' && t.at(10) != ' ') ||
590 0 : t.at(13) != ':' || t.at(16) != ':')
591 0 : throw InvalidArgumentException("Invalid time format: " + t);
592 0 : int yyyy = 0;
593 0 : int mm = 0;
594 0 : int dd = 0;
595 0 : int hh = 0;
596 0 : int min = 0;
597 0 : double sec = 0.0;
598 : try {
599 0 : yyyy = Integer::parseInt(t.substr(0,4));
600 0 : mm = Integer::parseInt(t.substr(5,2));
601 0 : dd = Integer::parseInt(t.substr(8,2));
602 0 : hh = Integer::parseInt(t.substr(11,2));
603 0 : min = Integer::parseInt(t.substr(14,2));
604 0 : sec = Double::parseDouble(t.substr(17,(t.length() - 17)));
605 0 : } catch (const NumberFormatException &err) {
606 0 : throw InvalidArgumentException("Invalid time format: " + t);
607 0 : }
608 0 : return init(yyyy,mm,dd,hh,min,sec);
609 : }
610 :
611 : /**
612 : * Convert a unit of time in units since the base time to a Julian day.
613 : * @param unit The unit to be converted.
614 : * @return The Julian day corresponding to the specified unit of time.
615 : */
616 0 : double ArrayTime::unitToJD(int64_t unit) {
617 0 : return (double)(unit) / unitsInADay + julianDayOfBase;
618 : }
619 :
620 : /**
621 : * Convert a unit of time in units since the base time to a Modified Julian day.
622 : * @param unit The unit to be converted.
623 : * @return The Modified Julian day corresponding to the specified unit of time.
624 : */
625 0 : double ArrayTime::unitToMJD(int64_t unit) {
626 0 : return (double)(unit) / unitsInADay;
627 : }
628 :
629 : /**
630 : * Convert a Julian day to a unit of time in tens of nanoseconds
631 : * since 15 October 1582 00:00:00 UTC.
632 : * @param jd The Julian day to be converted.
633 : * @return The unit corresponding to the specified Julian day.
634 : */
635 0 : int64_t ArrayTime::jdToUnit(double jd) {
636 0 : return ((int64_t)(jd * unitsInADayDiv100) - julianDayOfBaseInUnitsInADayDiv100) * 100L;
637 : }
638 :
639 : /**
640 : * Convert a Modified Julian day to units since the base time.
641 : * @param mjd The Modified Julian day to be converted.
642 : * @return The unit corresponding to the specified Modified Julian day.
643 : */
644 0 : int64_t ArrayTime::mjdToUnit(double mjd) {
645 0 : return (int64_t)(mjd * unitsInADay);
646 : }
647 :
648 : /**
649 : * Return the TAI to UTC correction in units of seconds that must be applied
650 : * to a specified Julian Day, in other words return TAI time minus UCT time.
651 : * @param jd The Julian day for the TAI time.
652 : * @return The number of seconds that must be subtracted from the TAI time to get the
653 : * correct UTC time.
654 : */
655 0 : double ArrayTime::utcCorrection(double jd) {
656 0 : if (jd > UTCLast.getJD())
657 0 : return UTCLast.getTAIMinusUTC();
658 0 : int i = UTCCorrectionLength - 1;
659 0 : for (; i >= 0; --i) {
660 0 : if (jd <= UTCCorrectionTable[i].getJD())
661 0 : break;
662 : }
663 0 : return UTCCorrectionTable[i].getTAIMinusUTC();
664 : }
665 : /*
666 : istream & operator >> ( istream &is, ArrayTime& x) {
667 : Interval::operator >> (is, x);
668 : }
669 : */
670 : } // End namespace asdm
|