Changeset 4051
- Timestamp:
- May 31, 2005, 11:48:13 AM (21 years ago)
- Location:
- trunk/psLib/src
- Files:
-
- 7 edited
-
astro/psTime.c (modified) (65 diffs)
-
astro/psTime.h (modified) (15 diffs)
-
astronomy/psAstrometry.c (modified) (2 diffs)
-
astronomy/psTime.c (modified) (65 diffs)
-
astronomy/psTime.h (modified) (15 diffs)
-
dataManip/psConstants.h (modified) (2 diffs)
-
math/psConstants.h (modified) (2 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/psLib/src/astro/psTime.c
r4029 r4051 10 10 * @author Ross Harman, MHPCC 11 11 * 12 * @version $Revision: 1.6 1$ $Name: not supported by cvs2svn $13 * @date $Date: 2005-05- 25 20:26:55$12 * @version $Revision: 1.62 $ $Name: not supported by cvs2svn $ 13 * @date $Date: 2005-05-31 21:47:46 $ 14 14 * 15 15 * Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii … … 24 24 #include "psTime.h" 25 25 #include "psError.h" 26 #include "psLogMsg.h" 26 27 #include "psMemory.h" 27 28 #include "psAbort.h" … … 69 70 static psMetadata *timeMetadata = NULL; 70 71 72 // Offset to convert terrestrial time(TT) to international atomic time(TAI) 73 #define TAI_TT_OFFSET_SECONDS 32 74 #define TAI_TT_OFFSET_NANOSECONDS 184000000 75 76 // Offset from converting to MJD 77 #define MJD_EPOCH_OFFSET 40587.0 78 79 // Offset for converting to JD 80 #define JD_EPOCH_OFFSET 2440587.5 81 82 // Offset of year 0000 from epoch 83 #define YEAR_0000_SEC -62125920000.0 84 85 // Offset of year 9999 from epoch 86 #define YEAR_9999_SEC 253202544000.0 87 71 88 /** Static function prototypes */ 72 89 static char *cleanString(char *inString, int sLen); 73 90 static char* getToken(char **inString, char *delimiter, psParseErrorType *status); 74 psF64 searchTables(psF64 index, psU64 column, psLookupStatusType *status, char *metadataTableNames[], psU32 nTables); 75 91 static psF64 searchTables(psF64 index, psU64 column, char *metadataTableNames[], 92 psU32 nTables, psLookupStatusType* status); 93 static psTime* convertTimeTAIUTC(psTime* time); 94 static psTime* convertTimeUTCTAI(psTime* time); 95 static psTime* convertTimeTAITT(psTime* time); 96 static psTime* convertTimeTTTAI(psTime* time); 97 static psTime* convertTimeUTCUT1(psTime* time); 76 98 77 99 /** Removes leading and trailing whitespace and # characters from a string. The cleaned string is a new null … … 83 105 char *cleaned = NULL; 84 106 85 86 107 ptrB = inString; 87 108 88 / * Skip over leading # or whitespace */109 // Skip over leading # or whitespace 89 110 while (isspace(*ptrB) || *ptrB=='#') { 90 111 ptrB++; 91 112 } 92 113 93 / * Skip over trailing whitespace, null terminators, and # characters */94 ptrE = inString + sLen ;114 // Skip over trailing whitespace, null terminators, and # characters 115 ptrE = inString + sLen - 1; 95 116 while(isspace(*ptrE) || *ptrE=='\0' || *ptrE=='#') { 96 117 ptrE--; … … 113 134 int sLen = 0; 114 135 115 116 136 // Skip over leading whitespace 117 137 while(isspace(**inString)) { … … 121 141 // Length of token, not including delimiter 122 142 sLen = strcspn(*inString, delimiter); 143 123 144 if(sLen) { 124 145 … … 127 148 128 149 // Move to end of token 129 (*inString) += sLen; 150 (*inString) += (sLen+1); 151 130 152 } else if(**inString!='\0' && sLen==0) { 131 153 *status = PS_PARSE_ERROR_GENERAL; … … 148 170 149 171 150 /** Searches time tables in priority order and performs interpolation if input index value is within a table. 151 * If the index value is out of range, the status is set accordingly. */ 152 psF64 searchTables(psF64 index, psU64 column, psLookupStatusType *status, char *metadataTableNames[], psU32 nTables) 153 { 154 psU32 i = 0; 155 char *tableName = NULL; 156 psF64 result = 0.0; 157 psLookupTable *table = NULL; 158 psMetadataItem *tableMetadataItem = NULL; 159 160 172 // Searches time tables in priority order and performs interpolation if input index value is within a table. 173 // If the index value is out of range, the status is set accordingly. 174 static psF64 searchTables(psF64 index, psU64 column, char *metadataTableNames[], 175 psU32 nTables, psLookupStatusType* status) 176 { 177 char* tableName = NULL; 178 psF64 result = NAN; 179 psLookupTable* table = NULL; 180 psMetadataItem* tableMetadataItem = NULL; 161 181 162 182 // Check time metadata. Function call reports errors. 163 183 if(timeMetadata == NULL) { 164 184 if(!p_psTimeInit(p_psGetConfigFileName())) 165 return 0.0; 166 } 167 168 // Search each table in priority order: ser7, eopc,finals 169 for(i=0; i<nTables; i++) { 170 171 // Get table from metadata 185 *status = PS_LOOKUP_ERROR; 186 return NAN; 187 } 188 189 // Search each table in priority order: daily, eopc,finals 190 for(psS32 i = 0; i < nTables; i++) { 191 192 // Get table name from list of tables to search 172 193 tableName = metadataTableNames[i]; 194 195 // Lookup table name in time metadata 173 196 tableMetadataItem = psMetadataLookup(timeMetadata, tableName); 197 198 // Check if table not a metadata item 174 199 if(tableMetadataItem == NULL) { 175 200 psError(PS_ERR_BAD_PARAMETER_VALUE, true, PS_ERRORTEXT_psTime_LOOKUP_METADATA_FAILED, 176 201 tableName); 177 return 0.0; 178 } 202 *status = PS_LOOKUP_ERROR; 203 return NAN; 204 } 205 206 // Get table from metadata 179 207 table = (psLookupTable*)tableMetadataItem->data.V; 180 PS_ASSERT_PTR_NON_NULL(table,0.0); 181 182 // Attempt to interpolate table 183 *status = PS_LOOKUP_SUCCESS; 184 result = psLookupTableInterpolate(table, index, 2, status); 185 if(*status == PS_LOOKUP_SUCCESS) { 186 return result; 187 } else if(*status == PS_LOOKUP_ERROR) { 188 psError(PS_ERR_BAD_PARAMETER_VALUE, true, PS_ERRORTEXT_psTime_INTERPOLATION_FAILED_NAME, 189 tableName); 190 return 0.0; 208 209 // Check that table is not NULL 210 PS_ASSERT_PTR_NON_NULL(table,NAN); 211 212 // Check if index within to/from range 213 if(index >= table->validFrom ) { 214 if(index <= table->validTo) { 215 // Attempt to interpolate table 216 result = psLookupTableInterpolate(table, index, column); 217 *status = PS_LOOKUP_SUCCESS; 218 if(!isnan(result)) { 219 break; 220 } 221 } else { 222 *status = PS_LOOKUP_PAST_BOTTOM; 223 } 224 } else { 225 *status = PS_LOOKUP_PAST_TOP; 191 226 } 192 227 } … … 197 232 bool p_psTimeInit(const char *fileName) 198 233 { 234 psS32 numLines = 0; 199 235 bool foundTable = false; 200 236 char *tableDir = NULL; 201 237 char *tableNames = NULL; 238 char *tableFormats = NULL; 202 239 char *namesPtr = NULL; 240 char *formatPtr = NULL; 203 241 char *metadataNamesPtr = NULL; 204 242 char *tableName = NULL; 243 char *tableFormat = NULL; 205 244 char *fullTableName = NULL; 206 245 psS32 i = 0; … … 210 249 psVector *tablesFrom = NULL; 211 250 psVector *tablesTo = NULL; 251 psVector *tablesIndex = NULL; 212 252 psMetadataItem *metadataItem = NULL; 213 253 psLookupTable *table = NULL; 214 254 psParseErrorType status = PS_PARSE_SUCCESS; 215 char metadataTableNames[4][MAX_STRING_LENGTH] = {" ser7", "eopc", "finals", "tai"};255 char metadataTableNames[4][MAX_STRING_LENGTH] = {"daily", "eopc", "finals", "tai"}; 216 256 217 257 // Read time config file … … 251 291 psError(PS_ERR_BAD_PARAMETER_VALUE, true, PS_ERRORTEXT_psTime_LOOKUP_METADATA_FAILED, 252 292 "psLib.time.tables.to"); 293 psFree(tablesFrom); 253 294 return false; 254 295 } … … 258 299 psFree(tablesFrom); 259 300 psFree(tablesTo); 301 return false; 302 } 303 304 // Get index columns for the tables 305 metadataItem = psMetadataLookup(timeMetadata, "psLib.time.tables.index"); 306 if(metadataItem == NULL) { 307 psError(PS_ERR_BAD_PARAMETER_VALUE,true,PS_ERRORTEXT_psTime_LOOKUP_METADATA_FAILED, 308 "psLib.time.tables.index"); 309 psFree(tablesFrom); 310 psFree(tablesTo); 311 return false; 312 } 313 tablesIndex = psVectorCopy(tablesIndex, metadataItem->data.V, PS_TYPE_S32); 314 if(tablesIndex->n != numTables) { 315 psError(PS_ERR_BAD_PARAMETER_VALUE,true,PS_ERRORTEXT_psTime_BAD_VECTOR,tablesIndex->n,numTables); 316 psFree(tablesFrom); 317 psFree(tablesTo); 318 psFree(tablesIndex); 260 319 return false; 261 320 } … … 268 327 psFree(tablesFrom); 269 328 psFree(tablesTo); 329 psFree(tablesIndex); 270 330 return false; 271 331 } … … 280 340 psFree(tablesFrom); 281 341 psFree(tablesTo); 342 psFree(tablesIndex); 282 343 psFree(tableDir); 283 344 return false; 284 345 } 285 346 tableNames = psStringCopy(metadataItem->data.V); 347 348 // Get table format strings 349 metadataItem = psMetadataLookup(timeMetadata, "psLib.time.tables.format"); 350 if(metadataItem == NULL) { 351 psError(PS_ERR_BAD_PARAMETER_VALUE,true, PS_ERRORTEXT_psTime_LOOKUP_METADATA_FAILED, 352 "psLib.time.tables.format"); 353 psFree(tablesFrom); 354 psFree(tablesTo); 355 psFree(tablesIndex); 356 psFree(tableDir); 357 psFree(tableNames); 358 return false; 359 } 360 tableFormats = psStringCopy(metadataItem->data.V); 361 formatPtr = tableFormats; 286 362 287 363 // Read time tables … … 289 365 while((tableName=getToken(&namesPtr, " ", &status)) != NULL) { 290 366 291 // Form path with table name, adding one to length for last '/' that may not occur in string in cong file 367 // Form path with table name, adding one to length for last '/' that may not occur 368 // in string in cong file 292 369 fullTableName = (char*)psAlloc(strlen(tableDir)+strlen(tableName)+1+1); 293 370 … … 298 375 strcat(fullTableName, tableName); 299 376 377 // Get table format 378 tableFormat = getToken(&formatPtr,",",&status); 379 if(tableFormat == NULL) { 380 psError(PS_ERR_BAD_PARAMETER_VALUE,true,PS_ERRORTEXT_psTime_LOOKUP_METADATA_FAILED, 381 "psLib.time.tables.format"); 382 } 383 300 384 // Create and read table 301 385 if(i < numTables) { 302 table = psLookupTableAlloc(fullTableName, tablesFrom->data.F64[i], tablesTo->data.F64[i]);303 table= psLookupTableRead(table);386 table = psLookupTableAlloc(fullTableName, (const char*)tableFormat, tablesIndex->data.S32[i]); 387 numLines = psLookupTableRead(table); 304 388 } else { 305 389 psError(PS_ERR_BAD_PARAMETER_VALUE, true, PS_ERRORTEXT_psTime_BAD_TABLE_COUNT, i+1, numTables); … … 321 405 psFree(fullTableName); 322 406 psFree(tableName); 407 psFree(tableFormat); 323 408 psFree(table); 324 409 i++; … … 333 418 psFree(tablesFrom); 334 419 psFree(tablesTo); 420 psFree(tablesIndex); 421 psFree(tableFormats); 335 422 336 423 return true; … … 351 438 psTime *outTime = NULL; 352 439 353 354 440 // Error checks 355 if(type!=PS_TIME_TAI && type!=PS_TIME_UTC) { 441 if(type!=PS_TIME_TAI && type!=PS_TIME_UTC && type!=PS_TIME_UT1 && 442 type!=PS_TIME_TT) { 356 443 psError(PS_ERR_BAD_PARAMETER_VALUE, true, 357 444 PS_ERRORTEXT_psTime_TYPE_UNKNOWN, … … 360 447 } 361 448 449 // Allocate memory for structure 362 450 outTime = (psTime*)psAlloc(sizeof(psTime)); 363 451 452 // Initialize members 364 453 outTime->sec = 0; 365 454 outTime->nsec = 0; … … 375 464 psTime *time = NULL; 376 465 377 378 466 // Allocate psTime struct 379 467 time = psTimeAlloc(type); 380 468 469 // Verify time structure allocated 470 if(time == NULL) { 471 return NULL; 472 } 473 474 // Get the system time 381 475 if (gettimeofday(&now, (struct timezone *)0) == -1) { 382 476 psError(PS_ERR_OS_CALL_FAILED, true, … … 391 485 // Add most leapseconds to UTC time to get TAI time if necessary 392 486 if(type == PS_TIME_TAI) { 393 time->sec += p sTimeGetTAIDelta(time);487 time->sec += p_psTimeGetTAIDelta(time); 394 488 } 395 489 … … 397 491 } 398 492 493 static psTime* convertTimeTAIUTC(psTime* time) 494 { 495 psF64 deltaTAI = 0.0; 496 psS64 deltaSec = 0; 497 psU32 deltaNsec = 0; 498 psF64 deltaUTC = 0.0; 499 500 // Determine delta to convert between UTC and TAI 501 deltaTAI = p_psTimeGetTAIDelta(time); 502 deltaSec = (psS64)(deltaTAI); 503 deltaNsec = (psU32)((deltaTAI - (psF64)deltaSec) * 1e9); 504 505 // Determine seconds 506 time->sec -= deltaSec; 507 508 // Check for underflow in nsec 509 if(deltaNsec > time->nsec) { 510 // Borrow second 511 time->nsec += 1e9; 512 time->sec--; 513 } 514 515 // Determine nsec 516 time->nsec -= deltaNsec; 517 518 // Check for overflow in nsec 519 if(time->nsec >= 1e9) { 520 time->nsec -= 1e9; 521 time->sec++; 522 } 523 524 // Set new type 525 time->type = PS_TIME_UTC; 526 527 // Check if leapsecond present in delta 528 deltaUTC = p_psTimeGetTAIDelta(time); 529 if(fabs(deltaTAI-deltaUTC) >= 1.0) { 530 time->sec++; 531 } 532 533 return time; 534 } 535 536 static psTime* convertTimeUTCTAI(psTime* time) 537 { 538 psF64 delta = 0.0; 539 psS64 deltaSec = 0; 540 psU32 deltaNsec = 0; 541 542 // Determine delta to convert between UTC and TAI 543 delta = p_psTimeGetTAIDelta(time); 544 545 deltaSec = (psS64)(delta); 546 deltaNsec = (psU32)((delta - (psF64)deltaSec) * 1e9); 547 548 // Determine seconds 549 time->sec += deltaSec; 550 551 // Determine nsec 552 time->nsec += deltaNsec; 553 554 // Check for overflow in nsec 555 if(time->nsec >= 1e9) { 556 time->nsec -= 1e9; 557 time->sec++; 558 } 559 560 // Set new type 561 time->type = PS_TIME_TAI; 562 563 return time; 564 } 565 566 static psTime* convertTimeTAITT(psTime* time) 567 { 568 // Add TT offset 569 time->sec += TAI_TT_OFFSET_SECONDS; 570 time->nsec += TAI_TT_OFFSET_NANOSECONDS; 571 572 // Check for overflow in nsec 573 if(time->nsec >= 1e9) { 574 time->nsec -= 1e9; 575 time->sec++; 576 } 577 578 // Set new type 579 time->type = PS_TIME_TT; 580 581 return time; 582 } 583 584 static psTime* convertTimeTTTAI(psTime* time) 585 { 586 // Subtract TT offset 587 time->sec -= TAI_TT_OFFSET_SECONDS; 588 589 // Check for nsec underflow 590 if(TAI_TT_OFFSET_NANOSECONDS > time->nsec) { 591 // Borrow second 592 time->sec--; 593 time->nsec += 1e9; 594 } 595 time->nsec -= TAI_TT_OFFSET_NANOSECONDS; 596 597 // Check for overflow in nsec 598 if(time->nsec >= 1e9) { 599 time->nsec -= 1e9; 600 time->sec++; 601 } 602 603 // Set new type 604 time->type = PS_TIME_TAI; 605 606 return time; 607 } 608 609 static psTime* convertTimeUTCUT1(psTime* time) 610 { 611 psS64 ut1utc = 0; 612 613 // Get UT1-UTC value 614 ut1utc = (psS64)(psTimeGetUT1Delta(time,PS_IERS_A) * 1e9); 615 616 // Since UTC is within 0.9 sec of UT1 then nsec member is the member affected 617 if((ut1utc < 0) && (abs(ut1utc) > time->nsec)) { 618 // Borrow from sec 619 time->sec--; 620 if(time->leapsecond) { 621 time->leapsecond = false; 622 } else { 623 time->leapsecond = psTimeIsLeapSecond(time); 624 } 625 // Add to nsec 626 time->nsec += 1e9; 627 } 628 time->nsec += ut1utc; 629 630 // Check for overflow in nsec 631 if(time->nsec >= 1e9) { 632 time->nsec -= 1e9; 633 time->sec++; 634 if(time->leapsecond) { 635 time->leapsecond = false; 636 time->sec--; 637 } else { 638 time->leapsecond = psTimeIsLeapSecond(time); 639 } 640 } 641 642 // Set new type 643 time->type = PS_TIME_UT1; 644 645 return time; 646 } 647 399 648 psTime* psTimeConvert(psTime *time, psTimeType type) 400 649 { 401 double delta = 0.0;402 403 404 650 // Error checks 405 651 PS_ASSERT_PTR_NON_NULL(time,NULL); 406 PS_ASSERT_INT_WITHIN_RANGE(time->nsec,0,1e9-1,NULL); 407 408 if (time->type == type) { // time already right type. That was easy! 652 PS_ASSERT_INT_WITHIN_RANGE(time->nsec,0,(psU32)((1e9)-1),time); 653 654 // If the input type is UT1 then return time and generate error message 655 if(time->type == PS_TIME_UT1) { 656 psError(PS_ERR_BAD_PARAMETER_VALUE,true,"Cannot convert from UT1 time type"); 409 657 return time; 410 658 } 411 659 412 delta = psTimeGetTAIDelta(time); 413 414 if (type == PS_TIME_UTC) { 415 time->sec = time->sec - delta; // User wants UTC time. Subtract leapseconds. 416 } else if(type == PS_TIME_TAI) { 417 time->sec = time->sec + delta; // User wants TAI time. Add leapseconds. 660 // If the time to convert to is the same as psTime the return time 661 if (time->type == type) { 662 return time; 663 } 664 665 // Convert from TAI to UTC, TT, UT1 666 if(time->type == PS_TIME_TAI) { 667 // Convert from TAI to UTC 668 if(type == PS_TIME_UTC) { 669 time = convertTimeTAIUTC(time); 670 // Convert from TAI to TT 671 } else if(type == PS_TIME_TT) { 672 time = convertTimeTAITT(time); 673 // Convert from TAI to UT1 674 } else if(type == PS_TIME_UT1) { 675 // Convert to UTC first 676 time = convertTimeTAIUTC(time); 677 // Convert UTC to UT1 678 time = convertTimeUTCUT1(time); 679 // Convert from TAI to unknown time type 680 } else { 681 psError(PS_ERR_BAD_PARAMETER_VALUE, true, PS_ERRORTEXT_psTime_TYPE_UNKNOWN, type); 682 } 683 // Convert from TT to TAI, UTC, UT1 684 } else if(time->type == PS_TIME_TT) { 685 // Convert from TT to UTC 686 if(type == PS_TIME_UTC) { 687 // Convert to TAI time first 688 time = convertTimeTTTAI(time); 689 // Convert from TAI to UTC 690 time = convertTimeTAIUTC(time); 691 // Convert from TT to TAI 692 } else if(type == PS_TIME_TAI) { 693 time = convertTimeTTTAI(time); 694 // Convert from TT to UT1 695 } else if(type == PS_TIME_UT1) { 696 // Convert to UTC first 697 // Convert to TAI time first 698 time = convertTimeTTTAI(time); 699 // Convert from TAI to UTC 700 time = convertTimeTAIUTC(time); 701 // Convert from UTC to UT1 702 time = convertTimeUTCUT1(time); 703 // Convert from TT to unknown time type 704 } else { 705 psError(PS_ERR_BAD_PARAMETER_VALUE, true, PS_ERRORTEXT_psTime_TYPE_UNKNOWN, type); 706 } 707 // Convert from UTC to TAI, TT, UT1 708 } else if(time->type == PS_TIME_UTC) { 709 // Convert UTC to TAI 710 if(type == PS_TIME_TAI) { 711 time = convertTimeUTCTAI(time); 712 // Convert UTC to TT 713 } else if(type == PS_TIME_TT) { 714 // Convert to TAI time first 715 time = convertTimeUTCTAI(time); 716 // Convert TAI to TT 717 time = convertTimeTAITT(time); 718 // Convert UTC to UT1 719 } else if(type == PS_TIME_UT1) { 720 time = convertTimeUTCUT1(time); 721 // Convert UTC to unknown time type 722 } else { 723 psError(PS_ERR_BAD_PARAMETER_VALUE, true, PS_ERRORTEXT_psTime_TYPE_UNKNOWN, type); 724 } 725 // Convert unknown time type 418 726 } else { 419 psError(PS_ERR_BAD_PARAMETER_VALUE, true, PS_ERRORTEXT_psTime_TYPE_UNKNOWN, t ype);727 psError(PS_ERR_BAD_PARAMETER_VALUE, true, PS_ERRORTEXT_psTime_TYPE_UNKNOWN, time->type); 420 728 } 421 729 … … 423 731 } 424 732 425 double psTimeToLMST(psTime *time, doublelongitude)733 psF64 psTimeToLMST(psTime *time, psF64 longitude) 426 734 { 427 735 psF64 jdTdtDays = 0.0; … … 433 741 psF64 t = 0.0; 434 742 psF64 tu = 0.0; 435 psF64 ut1UtcDbl = 0.0;436 743 psF64 const1 = 24110.5493771; 437 744 psF64 const2 = 8639877.3173760; … … 440 747 psF64 const5 = -0.0000062; 441 748 psF64 const6 = 0.0000013; 442 psTime *ut1UtcDelta = NULL;443 749 psTime *tdtTime = NULL; 444 psTime *taiTime = NULL;445 psTime *utcTime = NULL;446 750 psTime *ut1Time = NULL; 447 448 751 449 752 // Error checks 450 753 PS_ASSERT_PTR_NON_NULL(time,NAN); 451 PS_ASSERT_INT_WITHIN_RANGE(time->nsec,0, 1e9-1,NAN);452 453 // Calculate TAI or UTC time based on type of time user passes454 if(time->type == PS_TIME_ TAI) {455 taiTime = psMemIncrRefCounter(time);456 utcTime = psTimeAlloc(PS_TIME_UTC);457 utcTime->sec = taiTime->sec - psTimeGetTAIDelta(time);458 utcTime->nsec = taiTime->nsec; 459 } else if(time->type == PS_TIME_UTC) {460 utcTime = psMemIncrRefCounter(time);461 taiTime = psTimeAlloc(PS_TIME_TAI);462 taiTime->sec = utcTime->sec + psTimeGetTAIDelta(time);463 taiTime->nsec = utcTime->nsec;464 }465 466 // Convert Universal Time (UTC) toUT1467 ut1 UtcDbl = psTimeGetUT1Delta(taiTime);468 ut cTime->type = PS_TIME_TAI; // Don't allow addition of leapseconds to ut1Time469 ut1Time = psTimeMath(utcTime, ut1UtcDbl);470 ut cTime->type = PS_TIME_UTC;471 754 PS_ASSERT_INT_WITHIN_RANGE(time->nsec,0,(psU32)((1e9)-1),NAN); 755 756 // Verify input time is not in UT1 seconds 757 if(time->type == PS_TIME_UT1) { 758 psError(PS_ERR_BAD_PARAMETER_VALUE,true,PS_ERRORTEXT_psTime_TYPE_INCORRECT,time->type); 759 return NAN; 760 } 761 762 // Determine time reference to TT 763 tdtTime = psTimeAlloc(time->type); 764 tdtTime->sec = time->sec; 765 tdtTime->nsec = time->nsec; 766 tdtTime->leapsecond = time->leapsecond; 767 tdtTime = psTimeConvert(tdtTime,PS_TIME_TT); 768 769 // Determine time reference to UT1 770 ut1Time = psTimeAlloc(time->type); 771 ut1Time->sec = time->sec; 772 ut1Time->nsec = time->nsec; 773 ut1Time->leapsecond = time->leapsecond; 774 ut1Time = psTimeConvert(ut1Time,PS_TIME_UT1); 472 775 473 776 // Calculate UT1 as Julian Centuries since J2000.0 … … 476 779 t = (jdUt1Days - 2451545.0)/36525.0; 477 780 478 // Calculate Terrestial Dynamical Time (TDT)479 tdtTime = psTimeMath(taiTime, 32.184);480 481 781 // Calculate TDT as Julian centuries since J2000.0 482 782 jdTdtDays = psTimeToJD(tdtTime); … … 486 786 fracDays = fmod(mjdUt1Days, 1.0); 487 787 488 // Calculate Greenwich Mean Sidereal Time (GMST) in radians. Equation set up to minimize multiplications. 489 gmstRad = fracDays*TWOPI+(const1+const2*tu+t*(const3+t*(const4+t*(const5+const6*t))))*S2R; 788 // Calculate Greenwich Mean Sidereal Time (GMST) in radians. 789 // Equation set up to minimize multiplications. 790 gmstRad = fracDays*TWOPI 791 + (const1+const2*tu+t*(const3+t*(const4+t*(const5+const6*t))))*S2R; 490 792 491 793 // Place GMST between 0 and 2*pi … … 496 798 497 799 // Free temporary structs 498 psFree(ut1UtcDelta);499 800 psFree(ut1Time); 500 801 psFree(tdtTime); 501 psFree(utcTime);502 psFree(taiTime);503 802 504 803 return lmstRad; 505 804 } 506 805 507 double psTimeGetUT1Delta(const psTime *time)508 { 509 psU32 nTables = 3;510 psF64 mjd= 0.0;511 psF64 result= 0.0;512 ps F64 dut2ut1 = 0.0;513 psF64 t= 0.0;514 ps Vector *dut = NULL;515 ps MetadataItem *tableMetadataItem= NULL;516 ps LookupStatusType status = PS_LOOKUP_SUCCESS;517 char *metadataTableNames[3] = {"ser7Table", "eopcTable", "finalsTable"};518 806 psF64 psTimeGetUT1Delta(const psTime *time, psTimeBulletin bulletin) 807 { 808 psU32 nTables = 2; 809 psF64 mjd = 0.0; 810 psF64 result = 0.0; 811 psU64 tableColumn = 0; 812 psF64 dut2ut1 = 0.0; 813 psF64 t = 0.0; 814 psVector* dut = NULL; 815 psMetadataItem* tableMetadataItem = NULL; 816 psLookupStatusType status = PS_LOOKUP_SUCCESS; 817 char* metadataTableNames[2] = {"dailyTable", "finalsTable"}; 519 818 520 819 // Error checks 521 820 PS_ASSERT_PTR_NON_NULL(time,NAN); 522 PS_ASSERT_INT_WITHIN_RANGE(time->nsec,0,1e9-1,NAN); 523 524 if(time->type != PS_TIME_TAI) { 525 psError(PS_ERR_BAD_PARAMETER_VALUE, true, PS_ERRORTEXT_psTime_TYPE_INCORRECT, time->type); 526 return 0.0; 821 PS_ASSERT_INT_WITHIN_RANGE(time->nsec,0,(psU32)((1e9)-1),NAN); 822 823 // Check for invalid bulletin specified 824 if((bulletin != PS_IERS_A) && (bulletin != PS_IERS_B)) { 825 psError(PS_ERR_BAD_PARAMETER_VALUE,true,"Invalid bulletin specified %d",bulletin); 826 return NAN; 827 } 828 829 // Set lookup table column based on Bullentin 830 if(bulletin == PS_IERS_A) { 831 tableColumn = 3; 832 } else { 833 tableColumn = 6; 527 834 } 528 835 529 836 // Attempt to find value through table lookup and interpolation 530 837 mjd = psTimeToMJD(time); 531 result = searchTables(mjd, 0, &status, metadataTableNames, nTables);838 result = searchTables(mjd,tableColumn,metadataTableNames,nTables,&status); 532 839 533 840 // Value could not be found through table lookup and interpolation … … 535 842 536 843 // Date too early for tables. Get default time delta value from metadata, and issue warning. 537 psError(PS_ERR_BAD_PARAMETER_VALUE, true, PS_ERRORTEXT_psTime_TIME_PREDATES_TABLES, mjd, "UT1-UTC"); 538 844 psLogMsg(__func__,PS_LOG_WARN,PS_ERRORTEXT_psTime_TIME_PREDATES_TABLES,mjd,"UT1-UTC"); 845 846 // Lookup value from time metadata loaded from psTime.config 539 847 tableMetadataItem = psMetadataLookup(timeMetadata, "psLib.time.before.dut"); 540 848 if(tableMetadataItem == NULL) { 541 psError(PS_ERR_BAD_PARAMETER_VALUE, true, PS_ERRORTEXT_psTime_LOOKUP_METADATA_FAILED, "psLib.time.before.dut"); 542 return 0.0; 849 psError(PS_ERR_BAD_PARAMETER_VALUE, true, PS_ERRORTEXT_psTime_LOOKUP_METADATA_FAILED, 850 "psLib.time.before.dut"); 851 return NAN; 543 852 } 544 853 result = tableMetadataItem->data.F64; … … 552 861 t = 2000.0 + (MJD - 51544.03)/365.2422 553 862 */ 554 psError(PS_ERR_BAD_PARAMETER_VALUE, true, PS_ERRORTEXT_psTime_TIME_POSTDATES_TABLES, mjd, "UT1-UTC"); 555 863 // Generate warning of postdate information 864 psLogMsg(__func__,PS_LOG_WARN,PS_ERRORTEXT_psTime_TIME_POSTDATES_TABLES, mjd, "UT1-UTC"); 865 866 // Lookup values to calculate prediction 556 867 tableMetadataItem = psMetadataLookup(timeMetadata, "psLib.time.predict.dut"); 557 868 if(tableMetadataItem == NULL) { 558 psError(PS_ERR_BAD_PARAMETER_VALUE, true, PS_ERRORTEXT_psTime_LOOKUP_METADATA_FAILED, "psLib.time.predict.dut"); 559 return 0.0; 869 psError(PS_ERR_BAD_PARAMETER_VALUE, true, PS_ERRORTEXT_psTime_LOOKUP_METADATA_FAILED, 870 "psLib.time.predict.dut"); 871 return NAN; 560 872 } 561 873 dut = (psVector*)tableMetadataItem->data.V; 562 PS_ASSERT_PTR_NON_NULL(dut,0.0); 563 874 PS_ASSERT_PTR_NON_NULL(dut,NAN); 875 876 // Calculate predication of future UT1-UTC 564 877 t = 2000.0 + (mjd - 51544.03)/365.2422; 565 878 dut2ut1 = 0.022*sin(TWOPI*t) - 0.012*cos(TWOPI*t) - 0.006*sin(4.0*M_PI*t) + 0.007*cos(4.0*M_PI*t); … … 568 881 } else if(status != PS_LOOKUP_SUCCESS) { 569 882 psError(PS_ERR_BAD_PARAMETER_VALUE, true, PS_ERRORTEXT_psTime_INTERPOLATION_FAILED); 570 return 0.0;883 return NAN; 571 884 } 572 885 … … 574 887 } 575 888 576 struct psSphere* p sTimeGetPoleCoords(const psTime* time)889 struct psSphere* p_psTimeGetPoleCoords(const psTime* time) 577 890 { 578 891 psU32 nTables = 3; … … 587 900 psLookupStatusType yStatus = PS_LOOKUP_SUCCESS; 588 901 psMetadataItem *tableMetadataItem = NULL; 589 char *metadataTableNames[3] = {" ser7Table", "eopcTable", "finalsTable"};902 char *metadataTableNames[3] = {"dailyTable", "eopcTable", "finalsTable"}; 590 903 psVector *xp = NULL; 591 904 psVector *yp = NULL; … … 593 906 // Error checks 594 907 PS_ASSERT_PTR_NON_NULL(time,NULL); 595 PS_ASSERT_INT_WITHIN_RANGE(time->nsec,0, 1e9-1,NULL);908 PS_ASSERT_INT_WITHIN_RANGE(time->nsec,0,(psU32)((1e9)-1),NULL); 596 909 597 910 if(time->type != PS_TIME_TAI) … … 603 916 // Attempt to find value through table lookup and interpolation 604 917 mjd = psTimeToMJD(time); 605 x = searchTables(mjd, 0, &xStatus, metadataTableNames, nTables); 606 y = searchTables(mjd, 0, &yStatus, metadataTableNames, nTables); 918 // x = searchTables(mjd, 0, &xStatus, metadataTableNames, nTables); 919 x = searchTables(mjd, 0, metadataTableNames, nTables,&xStatus); 920 // y = searchTables(mjd, 0, &yStatus, metadataTableNames, nTables); 921 y = searchTables(mjd, 0, metadataTableNames, nTables,&yStatus); 607 922 608 923 // Value could not be found through table lookup and interpolation … … 641 956 psError(PS_ERR_BAD_PARAMETER_VALUE, true, PS_ERRORTEXT_psTime_TIME_POSTDATES_TABLES, mjd, "polar motion"); 642 957 643 644 958 // Get predicted MJD 645 959 tableMetadataItem = psMetadataLookup(timeMetadata, "psLib.time.predict.mjd"); … … 692 1006 } 693 1007 694 // Create output sphere and convert arcsec to radians (i.e. x/60/60* M_PI/180)1008 // Create output sphere and convert arcsec to radians (i.e. x/60/60*PS_PI/180) 695 1009 output = psAlloc(sizeof(psSphere)); 696 1010 output->r = x * M_PI / 648000.0; … … 700 1014 } 701 1015 702 double psTimeGetTAIDelta(const psTime *time) 703 { 704 psU64 i = 0; 1016 psF64 p_psTimeGetTAIDelta(const psTime *time) 1017 { 705 1018 psF64 jd = 0.0; 706 1019 psF64 mjd = 0.0; … … 711 1024 psLookupTable* table = NULL; 712 1025 psMetadataItem *tableMetadataItem = NULL; 713 psVector *stats = NULL;714 1026 psVector *results = NULL; 715 1027 716 1028 // Error checks 717 1029 PS_ASSERT_PTR_NON_NULL(time,NAN); 718 PS_ASSERT_INT_WITHIN_RANGE(time->nsec,0, 1e9-1,NAN);1030 PS_ASSERT_INT_WITHIN_RANGE(time->nsec,0,(psU32)((1e9)-1),NAN); 719 1031 720 1032 // Check time metadata … … 739 1051 mjd = psTimeToMJD(time); 740 1052 741 stats = psVectorAlloc(table->numCols, PS_TYPE_U32); 742 results = psLookupTableInterpolateAll(table, jd, stats); 1053 // Set ceiling of the julian date to the last entry in the lookup table 1054 if(table->validTo < jd) { 1055 jd = table->validTo; 1056 } 1057 1058 // Interpolation of look up table 1059 results = psLookupTableInterpolateAll(table, jd); 743 1060 744 1061 // Check for successful interpolation 745 for(i=0; i<stats->n; i++) { 746 if(stats->data.U32[i] == PS_LOOKUP_ERROR) { 747 psError(PS_ERR_BAD_PARAMETER_VALUE, true, PS_ERRORTEXT_psTime_INTERPOLATION_FAILED); 748 } 749 } 750 751 const1 = results->data.F64[0]; 752 const2 = results->data.F64[1]; 753 const3 = results->data.F64[2]; 754 out = const1 + (mjd - const2) * const3; 755 756 psFree(stats); 1062 if(results == NULL) { 1063 psError(PS_ERR_BAD_PARAMETER_VALUE, true, PS_ERRORTEXT_psTime_INTERPOLATION_FAILED); 1064 } 1065 1066 // Set constants from table 1067 const1 = results->data.F64[1]; 1068 const2 = results->data.F64[2]; 1069 const3 = results->data.F64[3]; 1070 1071 // If const3 not equal to zero solve for difference else floor of const1 1072 if(fabs(const3-0.0) > FLT_EPSILON) { 1073 out = const1 + (mjd - const2) * const3; 1074 } else { 1075 out = floor(const1); 1076 } 1077 757 1078 psFree(results); 758 1079 … … 760 1081 } 761 1082 762 763 1083 psS64 psTimeLeapSecondDelta(const psTime *time1, const psTime *time2) 764 1084 { 765 1085 psS64 diff = 0; 766 767 1086 768 1087 // Error checks 769 1088 PS_ASSERT_PTR_NON_NULL(time1,0); 770 1089 PS_ASSERT_PTR_NON_NULL(time2,0); 771 PS_ASSERT_INT_WITHIN_RANGE(time1->nsec,0, 1e9-1,0);772 PS_ASSERT_INT_WITHIN_RANGE(time2->nsec,0, 1e9-1,0);773 diff = abs((psS64)p sTimeGetTAIDelta((psTime*)time1)-(psS64)psTimeGetTAIDelta((psTime*)time2));1090 PS_ASSERT_INT_WITHIN_RANGE(time1->nsec,0,(psU32)((1e9)-1),0); 1091 PS_ASSERT_INT_WITHIN_RANGE(time2->nsec,0,(psU32)((1e9)-1),0); 1092 diff = abs((psS64)p_psTimeGetTAIDelta((psTime*)time1)-(psS64)p_psTimeGetTAIDelta((psTime*)time2)); 774 1093 775 1094 return diff; 776 1095 } 777 1096 778 double psTimeToJD(const psTime *time) 779 { 780 double jd = 0.0; 1097 psBool psTimeIsLeapSecond(const psTime* utc) 1098 { 1099 psTime* prevUtc = NULL; 1100 psBool returnValue = false; 1101 1102 // Check for valid time 1103 PS_ASSERT_PTR_NON_NULL(utc,false); 1104 1105 // Verify time is UTC type 1106 if(utc->type != PS_TIME_UTC) { 1107 psError(PS_ERR_BAD_PARAMETER_VALUE,true,PS_ERRORTEXT_psTime_TYPE_INCORRECT,utc->type); 1108 return false; 1109 } 1110 1111 // Allocate time to hold utc - 1 second 1112 prevUtc = psTimeAlloc(PS_TIME_UTC); 1113 prevUtc->sec = utc->sec - 1; 1114 1115 // Check the absolute difference between the two times for leapsecond 1116 if(psTimeLeapSecondDelta(utc,prevUtc) >= 1.0) { 1117 returnValue = true; 1118 } else { 1119 returnValue = false; 1120 } 1121 1122 // Free prevUtc 1123 psFree(prevUtc); 1124 1125 return returnValue; 1126 } 1127 1128 psF64 psTimeToJD(const psTime *time) 1129 { 1130 psF64 jd = NAN; 781 1131 782 1132 // Error checks 783 1133 PS_ASSERT_PTR_NON_NULL(time,NAN); 784 PS_ASSERT_INT_WITHIN_RANGE(time->nsec,0, 1e9-1,NAN);1134 PS_ASSERT_INT_WITHIN_RANGE(time->nsec,0,(psU32)((1e9)-1),NAN); 785 1135 786 1136 // Julian date conversion 787 1137 if(time->sec < 0) { 788 jd = time->sec / SEC_PER_DAY - time->nsec / NSEC_PER_DAY + 2440587.5; // psTime earlier than epoch 1138 // psTime earlier than epoch 1139 jd = time->sec / SEC_PER_DAY - time->nsec / NSEC_PER_DAY + JD_EPOCH_OFFSET; 789 1140 } else { 790 jd = time->sec / SEC_PER_DAY + time->nsec / NSEC_PER_DAY + 2440587.5; // psTime greater than epoch 1141 // psTime greater than epoch 1142 jd = time->sec / SEC_PER_DAY + time->nsec / NSEC_PER_DAY + JD_EPOCH_OFFSET; 791 1143 } 792 1144 … … 794 1146 } 795 1147 796 double psTimeToMJD(const psTime *time) 797 { 798 double mjd = 0.0; 799 1148 psF64 psTimeToMJD(const psTime *time) 1149 { 1150 psF64 mjd = NAN; 800 1151 801 1152 // Error checks 802 1153 PS_ASSERT_PTR_NON_NULL(time,NAN); 803 PS_ASSERT_INT_WITHIN_RANGE(time->nsec,0, 1e9-1,NAN);1154 PS_ASSERT_INT_WITHIN_RANGE(time->nsec,0,(psU32)((1e9)-1),NAN); 804 1155 805 1156 // Modified Julian date conversion 806 1157 if(time->sec < 0) { 807 mjd = time->sec / SEC_PER_DAY - time->nsec / NSEC_PER_DAY + 40587.0; // psTime earlier than epoch 1158 // psTime earlier than epoch 1159 mjd = time->sec / SEC_PER_DAY - time->nsec / NSEC_PER_DAY + MJD_EPOCH_OFFSET; 808 1160 } else { 809 mjd = time->sec / SEC_PER_DAY + time->nsec / NSEC_PER_DAY + 40587.0; // psTime greater than epoch 1161 // psTime greater than epoch 1162 mjd = time->sec / SEC_PER_DAY + time->nsec / NSEC_PER_DAY + MJD_EPOCH_OFFSET; 810 1163 } 811 1164 … … 815 1168 char* psTimeToISO(const psTime *time) 816 1169 { 817 psS32 ms = 0;1170 psS32 ds = 0; 818 1171 char *timeString = NULL; 819 1172 char *tempString = NULL; … … 821 1174 time_t sec; 822 1175 823 824 1176 // Error checks 825 1177 PS_ASSERT_PTR_NON_NULL(time,NULL); 826 PS_ASSERT_INT_WITHIN_RANGE(time->nsec,0,1e9-1,NULL); 827 1178 PS_ASSERT_INT_WITHIN_RANGE(time->nsec,0,(psU32)((1e9)-1),NULL); 1179 1180 // Check valid year range 1181 PS_ASSERT_LONG_WITHIN_RANGE(time->sec,YEAR_0000_SEC,YEAR_9999_SEC,NULL) 1182 1183 // Allocate temp strings 828 1184 tempString = psAlloc(MAX_TIME_STRING_LENGTH); 829 1185 timeString = psAlloc(MAX_TIME_STRING_LENGTH); 830 1186 831 ms = time->nsec / 1000000; 1187 // Convert nanoseconds to decaseconds 1188 ds = time->nsec / 100000000; 832 1189 sec = time->sec; 1190 1191 // If leapsecond use previous day 1192 if(time->leapsecond) { 1193 sec--; 1194 } 833 1195 834 1196 // tmTime variable is statically allocated, no need to free … … 840 1202 } 841 1203 842 if (snprintf(timeString, MAX_TIME_STRING_LENGTH, "%s.%3.3dZ", tempString, ms) < 0) { 1204 // Check if time is UTC and leapsecond 1205 if(((time->type==PS_TIME_UTC)||(time->type==PS_TIME_UT1)) && (time->leapsecond)) { 1206 // Modify second to be 60 1207 tempString[17] = '6'; 1208 tempString[18] = '0'; 1209 } 1210 1211 // Create string with milliseconds 1212 if (snprintf(timeString, MAX_TIME_STRING_LENGTH, "%s,%1dZ", tempString, ds) < 0) { 843 1213 psError(PS_ERR_OS_CALL_FAILED, true, PS_ERRORTEXT_psTime_APPEND_MSEC_FAILED); 844 1214 } … … 848 1218 } 849 1219 850 struct timeval psTimeToTimeval(const psTime *time) 851 { 852 struct timeval timevalTime; 853 854 timevalTime.tv_sec = 0; 855 timevalTime.tv_usec = 0; 1220 struct timeval* psTimeToTimeval(const psTime *time) 1221 { 1222 struct timeval *timevalTime = NULL; 856 1223 857 1224 // Error checks 858 PS_ASSERT_PTR_NON_NULL(time,timevalTime); 859 PS_ASSERT_INT_WITHIN_RANGE(time->nsec,0,1e9-1,timevalTime); 860 861 timevalTime.tv_sec = time->sec; 862 timevalTime.tv_usec = time->nsec / 1000; 1225 PS_ASSERT_PTR_NON_NULL(time,NULL); 1226 PS_ASSERT_INT_WITHIN_RANGE(time->sec,0,INT32_MAX,NULL); 1227 PS_ASSERT_INT_WITHIN_RANGE(time->nsec,0,(psU32)((1e9)-1),NULL); 1228 1229 // Allocate structure timeval 1230 timevalTime = (struct timeval*)psAlloc(sizeof(struct timeval)); 1231 1232 // Set structure members 1233 timevalTime->tv_sec = time->sec; 1234 timevalTime->tv_usec = time->nsec / 1000; 863 1235 864 1236 return timevalTime; 865 1237 } 866 1238 867 struct tm* psTimeToTM(const psTime *time) 1239 /* 1240 struct tm* p_psTimeToTM(const psTime *time) 868 1241 { 869 1242 psS64 cent = 0; … … 876 1249 psS64 temp = 0; 877 1250 struct tm* tmTime = NULL; 878 879 1251 1252 880 1253 // Error checks 881 1254 PS_ASSERT_PTR_NON_NULL(time,NULL); 882 PS_ASSERT_INT_WITHIN_RANGE(time->nsec,0, 1e9-1,NULL);883 1255 PS_ASSERT_INT_WITHIN_RANGE(time->nsec,0,(psU32)((1e9)-1),NULL); 1256 884 1257 seconds = time->sec%60; 885 1258 minute = time->sec/60%60; 886 1259 hour = time->sec/3600%24; 887 1260 day = (time->sec+62135596800)/86400; 888 1261 889 1262 // Add 306 days to make relative to Mar 1, 0; also adjust day to be within a range (1..2**28-1) where our 890 1263 // calculations will work with 32bit ints … … 898 1271 day -= temp * 146097; 899 1272 } 900 1273 901 1274 cent = (day*4-1)/146097; // Calc number of centuries day is after 29 Feb of yr 0 902 1275 day -= cent*146097/4; // 4 centuries = 146097 days … … 906 1279 day -= (month*367-1094)/12; // February of following year) 907 1280 year += cent*100+temp*400; // Get the real year, which is off by 908 1281 909 1282 // One if month is January or February 910 1283 if(month > 12) … … 913 1286 month -= 12; 914 1287 } 915 1288 916 1289 // Allocate output 917 1290 tmTime = (struct tm*)psAlloc(sizeof(struct tm)); 918 1291 919 1292 tmTime->tm_year = year - 1900; 920 1293 tmTime->tm_mon = month - 1; … … 924 1297 tmTime->tm_sec = seconds; 925 1298 tmTime->tm_isdst = -1; 926 1299 927 1300 return tmTime; 928 1301 } 929 930 psTime* psTimeFromJD(double time) 931 { 932 double days = 0.0; 933 double seconds = 0.0; 1302 */ 1303 1304 psTime* psTimeFromJD(psF64 time) 1305 { 1306 psF64 days = 0.0; 1307 psF64 seconds = 0.0; 934 1308 psTime *outTime = NULL; 935 936 1309 937 1310 // Allocate psTime struct … … 949 1322 950 1323 // Error check 951 PS_ASSERT_INT_WITHIN_RANGE(outTime->nsec,0, 1e9-1,outTime);1324 PS_ASSERT_INT_WITHIN_RANGE(outTime->nsec,0,(psU32)((1e9)-1),outTime); 952 1325 953 1326 return outTime; 954 1327 } 955 1328 956 psTime* psTimeFromMJD( doubletime)957 { 958 doubledays = 0.0;959 doubleseconds = 0.0;1329 psTime* psTimeFromMJD(psF64 time) 1330 { 1331 psF64 days = 0.0; 1332 psF64 seconds = 0.0; 960 1333 psTime *outTime = NULL; 961 962 1334 963 1335 // Allocate psTime struct … … 967 1339 days = time - 40587.0; 968 1340 seconds = days * SEC_PER_DAY; 1341 969 1342 if(seconds < 0.0) { 970 1343 outTime->nsec = (seconds - (psS64)seconds) * -1000000000.0; // psTime earlier than epoch … … 975 1348 976 1349 // Error check 977 PS_ASSERT_INT_WITHIN_RANGE(outTime->nsec,0, 1e9-1,outTime);1350 PS_ASSERT_INT_WITHIN_RANGE(outTime->nsec,0,(psU32)((1e9)-1),NULL); 978 1351 979 1352 return outTime; … … 986 1359 psTime *outTime = NULL; 987 1360 1361 // Check for NULL string 1362 PS_ASSERT_PTR_NON_NULL(time,NULL); 1363 988 1364 // Convert YYYY-MM-DDThh:mm:ss.sss in string form to tm time 989 if (sscanf(time, "%d-%d-%dT%d:%d:%d .%d", &tmTime.tm_year, &tmTime.tm_mon, &tmTime.tm_mday,1365 if (sscanf(time, "%d-%d-%dT%d:%d:%d,%d", &tmTime.tm_year, &tmTime.tm_mon, &tmTime.tm_mday, 990 1366 &tmTime.tm_hour, &tmTime.tm_min, &tmTime.tm_sec,&millisecond) < 7) { 991 1367 psError(PS_ERR_BAD_PARAMETER_VALUE, true, PS_ERRORTEXT_psTime_ISOTIME_MALFORMED, time); … … 1006 1382 1007 1383 // Convert tm time to psTime 1008 outTime = p sTimeFromTM(&tmTime);1384 outTime = p_psTimeFromTM(&tmTime); 1009 1385 outTime->nsec = millisecond * 1000000; 1386 1387 return outTime; 1388 } 1389 1390 psTime* psTimeFromTT(psS64 sec, psU32 nsec) 1391 { 1392 psTime* outTime = NULL; 1393 1394 // Verify nsec within range 1395 PS_ASSERT_INT_WITHIN_RANGE(nsec,0,(psU32)((1e9)-1),NULL); 1396 1397 // Allocate psTime data 1398 outTime = psTimeAlloc(PS_TIME_TT); 1399 1400 // Set data members 1401 outTime->sec = sec; 1402 outTime->nsec = nsec; 1403 1404 // Return data structure 1405 return outTime; 1406 } 1407 1408 psTime* psTimeFromUTC(psS64 sec, psU32 nsec, psBool leapsecond) 1409 { 1410 psTime* outTime = NULL; 1411 1412 // Verify nsec within range 1413 PS_ASSERT_INT_WITHIN_RANGE(nsec,0,(psU32)((1e9)-1),NULL); 1414 1415 // Allocate psTime data 1416 outTime = psTimeAlloc(PS_TIME_UTC); 1417 1418 // Set data members 1419 outTime->sec = sec; 1420 outTime->nsec = nsec; 1421 1422 // Set leapsecond flag if necessary 1423 outTime->leapsecond = psTimeIsLeapSecond(outTime); 1010 1424 1011 1425 return outTime; … … 1028 1442 1029 1443 // Error check 1030 PS_ASSERT_INT_WITHIN_RANGE(outTime->nsec,0, 1e9-1,outTime);1444 PS_ASSERT_INT_WITHIN_RANGE(outTime->nsec,0,(psU32)((1e9)-1),outTime); 1031 1445 1032 1446 return outTime; 1033 1447 } 1034 1448 1035 psTime* p sTimeFromTM(const struct tm* time)1449 psTime* p_psTimeFromTM(const struct tm* time) 1036 1450 { 1037 1451 psS64 year; … … 1044 1458 psTime *outTime = NULL; 1045 1459 1046 1047 1460 // Error check 1048 1461 PS_ASSERT_PTR_NON_NULL(time,NULL); … … 1062 1475 if( month <= 2 ) 1063 1476 { 1064 year -= (temp = (14 - month) / 12); 1477 temp = (14 - month) / 12; 1478 // year -= (temp = (14 - month) / 12); 1479 year -= temp; 1065 1480 month += 12 * temp; 1066 1481 } else if(month > 14) 1067 1482 { 1068 year += (temp = (month - 3) / 12); 1483 temp = (month - 3) / 12; 1484 // year += (temp = (month - 3) / 12); 1485 year += temp; 1069 1486 month -= 12 * temp; 1070 1487 } … … 1081 1498 // days to adjust from Mar 1, year 0-relative to Jan 1, year 1-relative. Add hours, minutes, and seconds. 1082 1499 day += (month * 367 - 1094) / 12 + year % 100 * 1461 / 4 + (year/100 * 36524 + year/400) - 306; 1083 outTime->sec = (((day - 1) * SEC_PER_DAY) - 62135596800) + hour*SEC_PER_HOUR + minute*SEC_PER_MINUTE + seconds; 1500 outTime->sec = (((day - 1) * SEC_PER_DAY) - 62135596800) + hour*SEC_PER_HOUR 1501 + minute*SEC_PER_MINUTE + seconds; 1084 1502 1085 1503 // C's TM does not define a microsecond field. Microseconds must be manipulated by calling function. … … 1087 1505 1088 1506 // Error check 1089 PS_ASSERT_INT_WITHIN_RANGE(outTime->nsec,0, 1e9-1,outTime);1507 PS_ASSERT_INT_WITHIN_RANGE(outTime->nsec,0,(psU32)((1e9)-1),outTime); 1090 1508 1091 1509 return outTime; … … 1098 1516 psTime *tempTime = NULL; 1099 1517 1100 1101 1518 // Error checks 1102 1519 PS_ASSERT_PTR_NON_NULL(time,NULL); 1103 PS_ASSERT_INT_WITHIN_RANGE(time->nsec,0, 1e9-1,NULL);1520 PS_ASSERT_INT_WITHIN_RANGE(time->nsec,0,(psU32)((1e9)-1),NULL); 1104 1521 1105 1522 // Convert time to TAI if necessary, but without changing input arguments … … 1109 1526 tempTime->nsec = time->nsec; 1110 1527 tempTime = psTimeConvert(tempTime, PS_TIME_TAI); 1528 outTime = psTimeAlloc(PS_TIME_TAI); 1111 1529 } else { 1112 1530 tempTime = psMemIncrRefCounter((psTime*)time); 1531 outTime = psTimeAlloc(time->type); 1113 1532 } 1114 1533 1115 1534 // Create output time 1116 outTime = psTimeAlloc(PS_TIME_TAI);1117 1535 sec = delta + (psF64)tempTime->sec + (psF64)tempTime->nsec/1e9; 1118 outTime->sec = sec; 1119 outTime->nsec = (sec - outTime->sec)*1e9; 1536 PS_ASSERT_LONG_WITHIN_RANGE((psS64)sec,0,PS_MAX_S64,outTime); 1537 outTime->sec = (psS64)sec; 1538 outTime->nsec = (psU32)((sec - (psF64)outTime->sec)*1e9); 1120 1539 1121 1540 // Error check 1122 PS_ASSERT_INT_WITHIN_RANGE(outTime->nsec,0, 1e9-1,outTime);1541 PS_ASSERT_INT_WITHIN_RANGE(outTime->nsec,0,(psU32)((1e9)-1),outTime); 1123 1542 1124 1543 // Convert result to same time type as input … … 1140 1559 psTime *tempTime2 = NULL; 1141 1560 1142 1143 1561 // Error checks 1144 1562 PS_ASSERT_PTR_NON_NULL(time1,0.0); 1145 PS_ASSERT_INT_WITHIN_RANGE(time1->nsec,0, 1e9-1,0.0);1563 PS_ASSERT_INT_WITHIN_RANGE(time1->nsec,0,(psU32)((1e9)-1),0.0); 1146 1564 PS_ASSERT_PTR_NON_NULL(time2,0.0); 1147 PS_ASSERT_INT_WITHIN_RANGE(time2->nsec,0,1e9-1,0.0); 1565 PS_ASSERT_INT_WITHIN_RANGE(time2->nsec,0,(psU32)((1e9)-1),0.0); 1566 1567 // Verify both times of the same type 1568 if(time1->type != time2->type) { 1569 psError(PS_ERR_BAD_PARAMETER_VALUE,true,PS_ERRORTEXT_psTime_TYPE_INCORRECT,time1->type); 1570 return out; 1571 } 1148 1572 1149 1573 // Convert time to TAI if necessary, but without changing input arguments -
trunk/psLib/src/astro/psTime.h
r3713 r4051 1 1 /** @file psTime.h 2 2 * 3 * @brief Definitions for time, time utilities, and conversion functions for use with psLib astronomy 4 * functions. 5 * 6 * A collection of functions are required by psLib to manipulate time data. These functions primarily consist 7 * of conversions between specific time formats. They use the UNIX timeval time system as the 8 * base upon which International Atomic Time (TAI) and Universal Time Coordinated (UTC) are calculated. 3 * @brief Definitions for time, time utilities, and conversion functions for use 4 * with psLib astronomy functions. 5 * 6 * A collection of functions are required by psLib to manipulate time data. These 7 * functions primarily consist of conversions between specific time formats. They 8 * use the UNIX timeval time system as the base upon which International Atomic 9 * Time (TAI) and Universal Time Coordinated (UTC) are calculated. 9 10 * 10 11 * @author Ross Harman, MHPCC 11 12 * 12 * @version $Revision: 1.2 8$ $Name: not supported by cvs2svn $13 * @date $Date: 2005-0 4-19 02:44:12$13 * @version $Revision: 1.29 $ $Name: not supported by cvs2svn $ 14 * @date $Date: 2005-05-31 21:47:46 $ 14 15 * 15 16 * Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii 16 17 */ 17 18 18 19 19 #ifndef PSTIME_H … … 88 88 /** Allocate time struct. 89 89 * 90 * Allocates an empty time struct. User must specify the psTimeType (PS_TIME_TAI or PS_TIME_UTC) in the argument. 91 * The seconds and microseconds members of the struct are set to zero. 90 * Allocates an empty time struct. User must specify the psTimeType 91 * (PS_TIME_TAI or PS_TIME_UTC) in the argument. The seconds and microseconds members 92 * of the struct are set to zero. 92 93 * 93 94 * @return psTime*: Struct with empty time. … … 99 100 /** Get current time. 100 101 * 101 * Gets current time from the system clock. User must specify the psTimeType (PS_TIME_TAI or PS_TIME_UTC) in102 * the argument.102 * Gets current time from the system clock. User must specify the psTimeType 103 * (PS_TIME_TAI or PS_TIME_UTC) in the argument. 103 104 * 104 105 * @return psTime*: Struct with current time. … … 121 122 /** Convert psTime to Local Mean Sidereal Time (LMST). 122 123 * 123 * Converts psTime at the given longitude to LMST time. If the input time is not in UTC format, then it is124 * converted.125 * 126 * @return double: LST Time.127 */ 128 doublepsTimeToLMST(124 * Converts psTime at the given longitude to LMST time. If the input time is not 125 * in UTC format, then it is converted. 126 * 127 * @return psF64: LST Time. 128 */ 129 psF64 psTimeToLMST( 129 130 psTime *time, ///< psTime to be converted. 130 doublelongitude ///< Longitude.131 psF64 longitude ///< Longitude. 131 132 ); 132 133 … … 135 136 * This function is necessary to for various SLALIB functions. 136 137 * 137 * @return double: Time difference. 138 */ 139 double psTimeGetUT1Delta( 138 * @return psF64: Time difference. 139 */ 140 psF64 psTimeGetUT1Delta( 141 const psTime *time, ///< psTime to be looked up. 142 psTimeBulletin bulletin ///< IERS bulletin to use 143 ); 144 145 /** Determine TAI - UTC from table lookup. 146 * 147 * This function is necessary to for various psTime functions. 148 * 149 * @return psF64: Time difference. 150 */ 151 psF64 p_psTimeGetTAIDelta( 140 152 const psTime *time ///< psTime to be looked up. 141 153 ); 142 154 143 /** Determine TAI - UTC from table lookup.144 *145 * This function is necessary to for various psTime functions.146 *147 * @return double: Time difference.148 */149 double psTimeGetTAIDelta(150 const psTime *time ///< psTime to be looked up.151 );152 153 155 /** Determine polar coordinates at a given time. 154 156 * … … 157 159 * @return psSphere*: Spherical coordinates of Earth's polar axias. 158 160 */ 159 struct psSphere* p sTimeGetPoleCoords(160 const psTime *time ///< psTime determine polar orientation.161 struct psSphere* p_psTimeGetPoleCoords( 162 const psTime *time ///< psTime determine polar orientation. 161 163 ); 162 164 … … 172 174 ); 173 175 176 /** Determine if UTC time is a leapsecond. 177 * 178 * Determines if the specified UTC time is a valid leapsecond. 179 * 180 * @return psBool: valid leap second 181 */ 182 psBool psTimeIsLeapSecond( 183 const psTime* utc ///< UTC to verify if leap second 184 ); 185 174 186 /** Convert psTime to Julian date time. 175 187 * 176 * Converts psTime to Julian date (JD) time. This function does not add or subtract leapseconds. 177 * 178 * @return double: Julian Date (JD) time. 179 */ 180 double psTimeToJD( 188 * Converts psTime to Julian date (JD) time. This function does not add or 189 * subtract leapseconds. 190 * 191 * @return psF64: Julian Date (JD) time. 192 */ 193 psF64 psTimeToJD( 181 194 const psTime* time ///< Input time to be converted. 182 195 ); 183 196 /** Convert psTime to modified Julian date time. 184 197 * 185 * Converts psTime to modified Julian date (MJD) time. This function does not add or subtract leapseconds. 186 * 187 * @return double: Modified Julian Days (MJD) time. 188 */ 189 double psTimeToMJD( 198 * Converts psTime to modified Julian date (MJD) time. This function does not 199 * add or subtract leapseconds. 200 * 201 * @return psF64: Modified Julian Days (MJD) time. 202 */ 203 psF64 psTimeToMJD( 190 204 const psTime* time ///< Input time to be converted. 191 205 ); … … 193 207 /** Convert psTime to ISO8601 formatted string. 194 208 * 195 * Converts psTime to a null terminated string in the form of YYYY-MM-DDThh:mm:ss.sss. This function does not196 * add or subtract leapseconds.209 * Converts psTime to a null terminated string in the form of YYYY-MM-DDThh:mm:ss.sss. 210 * This function does not add or subtract leapseconds. 197 211 * 198 212 * @return char*: Pointer null terminated array of chars in ISO time. … … 206 220 * Converts psTime to timeval time. This function does not add or subtract leapseconds. 207 221 * 208 * @return timeval : timeval struct time.209 */ 210 struct timeval psTimeToTimeval(211 const psTime* time ///< Input time to be converted.222 * @return timeval*: timeval struct time. 223 */ 224 struct timeval* psTimeToTimeval( 225 const psTime* time ///< Input time to be converted. 212 226 ); 213 227 214 /** Convert psTime to tm time. 215 * 216 * Converts psTime to tm time. This function is based on a Perl algorithm availble in the Pan-STARRS Image 217 * processing Algorithm Design Description (ADD). This function does not add or subtract leapseconds. 228 /* 229 * Convert psTime to tm time. 230 * 231 * Converts psTime to tm time. This function is based on a Perl algorithm availble 232 * in the Pan-STARRS Image processing Algorithm Design Description (ADD). This function 233 * does not add or subtract leapseconds. 218 234 * 219 235 * @return tm: tm struct time. 220 * /221 struct tm* p sTimeToTM(222 const psTime *time ///< Input time to be converted.236 * 237 struct tm* p_psTimeToTM( 238 const psTime *time ///< Input time to be converted. 223 239 ); 224 240 */ 225 241 /** Convert JD to psTime. 226 242 * … … 230 246 */ 231 247 psTime* psTimeFromJD( 232 double time///< Input time to be converted.248 psF64 time ///< Input time to be converted. 233 249 ); 234 250 … … 240 256 */ 241 257 psTime* psTimeFromMJD( 242 double time///< Input time to be converted.258 psF64 time ///< Input time to be converted. 243 259 ); 244 260 … … 250 266 */ 251 267 psTime* psTimeFromISO( 252 const char* time ///< Input time to be converted.268 const char* time ///< Input time to be converted. 253 269 ); 254 270 … … 260 276 */ 261 277 psTime* psTimeFromTimeval( 262 const struct timeval *time ///< Input time to be converted. 278 const struct timeval *time ///< Input time to be converted. 279 ); 280 281 /** Convert Terrestrial Time to psTime 282 * 283 * Converts Terrestial Time to psTime. This function assumes resultant time is of type TT. 284 * 285 * @return psTime*: time (TT) 286 */ 287 psTime* psTimeFromTT( 288 psS64 sec, ///< Input terrestrial time in seconds 289 psU32 nsec ///< Input terrestrial time fraction of seconds (nanoseconds) 290 ); 291 292 /** Convert UTC time to psTime 293 * 294 * Converts UTC time to psTime. It will verify if time specified is a leapsecond. 295 * 296 * @return psTime*: time (UTC) 297 */ 298 psTime* psTimeFromUTC( 299 psS64 sec, ///< Input time in seconds 300 psU32 nsec, ///< Input time fraction of seconds (nanoseconds) 301 psBool leapsecond ///< Input time is a leapsecond 263 302 ); 264 303 265 304 /** Convert tm time to psTime. 266 305 * 267 * Converts tm time to psTime. This function is based on a Perl algorithm availble in the Pan-STARRS Image 268 * processing Algorithm Design Description (ADD). This function does not add or subtract leapseconds. 306 * Converts tm time to psTime. This function is based on a Perl algorithm availble 307 * in the Pan-STARRS Image processing Algorithm Design Description (ADD). This function 308 * does not add or subtract leapseconds. 269 309 * 270 310 * @return psTime*: time. 271 311 */ 272 psTime* p sTimeFromTM(273 const struct tm *time ///< Input time to be converted.312 psTime* p_psTimeFromTM( 313 const struct tm *time ///< Input time to be converted. 274 314 ); 275 315 … … 281 321 */ 282 322 psTime* psTimeMath( 283 const psTime *time, ///< Time.284 psF64 delta ///< Time delta.323 const psTime *time, ///< Time. 324 psF64 delta ///< Time delta. 285 325 ); 286 326 … … 292 332 */ 293 333 psF64 psTimeDelta( 294 const psTime *time1, ///< First time.295 const psTime *time2 ///< Second time.334 const psTime *time1, ///< First time. 335 const psTime *time2 ///< Second time. 296 336 ); 297 337 -
trunk/psLib/src/astronomy/psAstrometry.c
r4029 r4051 8 8 * @author GLG, MHPCC 9 9 * 10 * @version $Revision: 1.6 6$ $Name: not supported by cvs2svn $11 * @date $Date: 2005-05- 25 20:26:55$10 * @version $Revision: 1.67 $ $Name: not supported by cvs2svn $ 11 * @date $Date: 2005-05-31 21:47:46 $ 12 12 * 13 13 * Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii … … 409 409 410 410 double date = psTimeToMJD(exp->time); 411 double dut = psTimeGetUT1Delta(exp->time );411 double dut = psTimeGetUT1Delta(exp->time,PS_IERS_A); 412 412 double elongm = exp->observatory->longitude; 413 413 double phim = exp->observatory->latitude; 414 414 double hm = exp->observatory->height; 415 415 416 psSphere* polarMotion = p sTimeGetPoleCoords(exp->time);416 psSphere* polarMotion = p_psTimeGetPoleCoords(exp->time); 417 417 double xp = polarMotion->r; 418 418 double yp = polarMotion->d; -
trunk/psLib/src/astronomy/psTime.c
r4029 r4051 10 10 * @author Ross Harman, MHPCC 11 11 * 12 * @version $Revision: 1.6 1$ $Name: not supported by cvs2svn $13 * @date $Date: 2005-05- 25 20:26:55$12 * @version $Revision: 1.62 $ $Name: not supported by cvs2svn $ 13 * @date $Date: 2005-05-31 21:47:46 $ 14 14 * 15 15 * Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii … … 24 24 #include "psTime.h" 25 25 #include "psError.h" 26 #include "psLogMsg.h" 26 27 #include "psMemory.h" 27 28 #include "psAbort.h" … … 69 70 static psMetadata *timeMetadata = NULL; 70 71 72 // Offset to convert terrestrial time(TT) to international atomic time(TAI) 73 #define TAI_TT_OFFSET_SECONDS 32 74 #define TAI_TT_OFFSET_NANOSECONDS 184000000 75 76 // Offset from converting to MJD 77 #define MJD_EPOCH_OFFSET 40587.0 78 79 // Offset for converting to JD 80 #define JD_EPOCH_OFFSET 2440587.5 81 82 // Offset of year 0000 from epoch 83 #define YEAR_0000_SEC -62125920000.0 84 85 // Offset of year 9999 from epoch 86 #define YEAR_9999_SEC 253202544000.0 87 71 88 /** Static function prototypes */ 72 89 static char *cleanString(char *inString, int sLen); 73 90 static char* getToken(char **inString, char *delimiter, psParseErrorType *status); 74 psF64 searchTables(psF64 index, psU64 column, psLookupStatusType *status, char *metadataTableNames[], psU32 nTables); 75 91 static psF64 searchTables(psF64 index, psU64 column, char *metadataTableNames[], 92 psU32 nTables, psLookupStatusType* status); 93 static psTime* convertTimeTAIUTC(psTime* time); 94 static psTime* convertTimeUTCTAI(psTime* time); 95 static psTime* convertTimeTAITT(psTime* time); 96 static psTime* convertTimeTTTAI(psTime* time); 97 static psTime* convertTimeUTCUT1(psTime* time); 76 98 77 99 /** Removes leading and trailing whitespace and # characters from a string. The cleaned string is a new null … … 83 105 char *cleaned = NULL; 84 106 85 86 107 ptrB = inString; 87 108 88 / * Skip over leading # or whitespace */109 // Skip over leading # or whitespace 89 110 while (isspace(*ptrB) || *ptrB=='#') { 90 111 ptrB++; 91 112 } 92 113 93 / * Skip over trailing whitespace, null terminators, and # characters */94 ptrE = inString + sLen ;114 // Skip over trailing whitespace, null terminators, and # characters 115 ptrE = inString + sLen - 1; 95 116 while(isspace(*ptrE) || *ptrE=='\0' || *ptrE=='#') { 96 117 ptrE--; … … 113 134 int sLen = 0; 114 135 115 116 136 // Skip over leading whitespace 117 137 while(isspace(**inString)) { … … 121 141 // Length of token, not including delimiter 122 142 sLen = strcspn(*inString, delimiter); 143 123 144 if(sLen) { 124 145 … … 127 148 128 149 // Move to end of token 129 (*inString) += sLen; 150 (*inString) += (sLen+1); 151 130 152 } else if(**inString!='\0' && sLen==0) { 131 153 *status = PS_PARSE_ERROR_GENERAL; … … 148 170 149 171 150 /** Searches time tables in priority order and performs interpolation if input index value is within a table. 151 * If the index value is out of range, the status is set accordingly. */ 152 psF64 searchTables(psF64 index, psU64 column, psLookupStatusType *status, char *metadataTableNames[], psU32 nTables) 153 { 154 psU32 i = 0; 155 char *tableName = NULL; 156 psF64 result = 0.0; 157 psLookupTable *table = NULL; 158 psMetadataItem *tableMetadataItem = NULL; 159 160 172 // Searches time tables in priority order and performs interpolation if input index value is within a table. 173 // If the index value is out of range, the status is set accordingly. 174 static psF64 searchTables(psF64 index, psU64 column, char *metadataTableNames[], 175 psU32 nTables, psLookupStatusType* status) 176 { 177 char* tableName = NULL; 178 psF64 result = NAN; 179 psLookupTable* table = NULL; 180 psMetadataItem* tableMetadataItem = NULL; 161 181 162 182 // Check time metadata. Function call reports errors. 163 183 if(timeMetadata == NULL) { 164 184 if(!p_psTimeInit(p_psGetConfigFileName())) 165 return 0.0; 166 } 167 168 // Search each table in priority order: ser7, eopc,finals 169 for(i=0; i<nTables; i++) { 170 171 // Get table from metadata 185 *status = PS_LOOKUP_ERROR; 186 return NAN; 187 } 188 189 // Search each table in priority order: daily, eopc,finals 190 for(psS32 i = 0; i < nTables; i++) { 191 192 // Get table name from list of tables to search 172 193 tableName = metadataTableNames[i]; 194 195 // Lookup table name in time metadata 173 196 tableMetadataItem = psMetadataLookup(timeMetadata, tableName); 197 198 // Check if table not a metadata item 174 199 if(tableMetadataItem == NULL) { 175 200 psError(PS_ERR_BAD_PARAMETER_VALUE, true, PS_ERRORTEXT_psTime_LOOKUP_METADATA_FAILED, 176 201 tableName); 177 return 0.0; 178 } 202 *status = PS_LOOKUP_ERROR; 203 return NAN; 204 } 205 206 // Get table from metadata 179 207 table = (psLookupTable*)tableMetadataItem->data.V; 180 PS_ASSERT_PTR_NON_NULL(table,0.0); 181 182 // Attempt to interpolate table 183 *status = PS_LOOKUP_SUCCESS; 184 result = psLookupTableInterpolate(table, index, 2, status); 185 if(*status == PS_LOOKUP_SUCCESS) { 186 return result; 187 } else if(*status == PS_LOOKUP_ERROR) { 188 psError(PS_ERR_BAD_PARAMETER_VALUE, true, PS_ERRORTEXT_psTime_INTERPOLATION_FAILED_NAME, 189 tableName); 190 return 0.0; 208 209 // Check that table is not NULL 210 PS_ASSERT_PTR_NON_NULL(table,NAN); 211 212 // Check if index within to/from range 213 if(index >= table->validFrom ) { 214 if(index <= table->validTo) { 215 // Attempt to interpolate table 216 result = psLookupTableInterpolate(table, index, column); 217 *status = PS_LOOKUP_SUCCESS; 218 if(!isnan(result)) { 219 break; 220 } 221 } else { 222 *status = PS_LOOKUP_PAST_BOTTOM; 223 } 224 } else { 225 *status = PS_LOOKUP_PAST_TOP; 191 226 } 192 227 } … … 197 232 bool p_psTimeInit(const char *fileName) 198 233 { 234 psS32 numLines = 0; 199 235 bool foundTable = false; 200 236 char *tableDir = NULL; 201 237 char *tableNames = NULL; 238 char *tableFormats = NULL; 202 239 char *namesPtr = NULL; 240 char *formatPtr = NULL; 203 241 char *metadataNamesPtr = NULL; 204 242 char *tableName = NULL; 243 char *tableFormat = NULL; 205 244 char *fullTableName = NULL; 206 245 psS32 i = 0; … … 210 249 psVector *tablesFrom = NULL; 211 250 psVector *tablesTo = NULL; 251 psVector *tablesIndex = NULL; 212 252 psMetadataItem *metadataItem = NULL; 213 253 psLookupTable *table = NULL; 214 254 psParseErrorType status = PS_PARSE_SUCCESS; 215 char metadataTableNames[4][MAX_STRING_LENGTH] = {" ser7", "eopc", "finals", "tai"};255 char metadataTableNames[4][MAX_STRING_LENGTH] = {"daily", "eopc", "finals", "tai"}; 216 256 217 257 // Read time config file … … 251 291 psError(PS_ERR_BAD_PARAMETER_VALUE, true, PS_ERRORTEXT_psTime_LOOKUP_METADATA_FAILED, 252 292 "psLib.time.tables.to"); 293 psFree(tablesFrom); 253 294 return false; 254 295 } … … 258 299 psFree(tablesFrom); 259 300 psFree(tablesTo); 301 return false; 302 } 303 304 // Get index columns for the tables 305 metadataItem = psMetadataLookup(timeMetadata, "psLib.time.tables.index"); 306 if(metadataItem == NULL) { 307 psError(PS_ERR_BAD_PARAMETER_VALUE,true,PS_ERRORTEXT_psTime_LOOKUP_METADATA_FAILED, 308 "psLib.time.tables.index"); 309 psFree(tablesFrom); 310 psFree(tablesTo); 311 return false; 312 } 313 tablesIndex = psVectorCopy(tablesIndex, metadataItem->data.V, PS_TYPE_S32); 314 if(tablesIndex->n != numTables) { 315 psError(PS_ERR_BAD_PARAMETER_VALUE,true,PS_ERRORTEXT_psTime_BAD_VECTOR,tablesIndex->n,numTables); 316 psFree(tablesFrom); 317 psFree(tablesTo); 318 psFree(tablesIndex); 260 319 return false; 261 320 } … … 268 327 psFree(tablesFrom); 269 328 psFree(tablesTo); 329 psFree(tablesIndex); 270 330 return false; 271 331 } … … 280 340 psFree(tablesFrom); 281 341 psFree(tablesTo); 342 psFree(tablesIndex); 282 343 psFree(tableDir); 283 344 return false; 284 345 } 285 346 tableNames = psStringCopy(metadataItem->data.V); 347 348 // Get table format strings 349 metadataItem = psMetadataLookup(timeMetadata, "psLib.time.tables.format"); 350 if(metadataItem == NULL) { 351 psError(PS_ERR_BAD_PARAMETER_VALUE,true, PS_ERRORTEXT_psTime_LOOKUP_METADATA_FAILED, 352 "psLib.time.tables.format"); 353 psFree(tablesFrom); 354 psFree(tablesTo); 355 psFree(tablesIndex); 356 psFree(tableDir); 357 psFree(tableNames); 358 return false; 359 } 360 tableFormats = psStringCopy(metadataItem->data.V); 361 formatPtr = tableFormats; 286 362 287 363 // Read time tables … … 289 365 while((tableName=getToken(&namesPtr, " ", &status)) != NULL) { 290 366 291 // Form path with table name, adding one to length for last '/' that may not occur in string in cong file 367 // Form path with table name, adding one to length for last '/' that may not occur 368 // in string in cong file 292 369 fullTableName = (char*)psAlloc(strlen(tableDir)+strlen(tableName)+1+1); 293 370 … … 298 375 strcat(fullTableName, tableName); 299 376 377 // Get table format 378 tableFormat = getToken(&formatPtr,",",&status); 379 if(tableFormat == NULL) { 380 psError(PS_ERR_BAD_PARAMETER_VALUE,true,PS_ERRORTEXT_psTime_LOOKUP_METADATA_FAILED, 381 "psLib.time.tables.format"); 382 } 383 300 384 // Create and read table 301 385 if(i < numTables) { 302 table = psLookupTableAlloc(fullTableName, tablesFrom->data.F64[i], tablesTo->data.F64[i]);303 table= psLookupTableRead(table);386 table = psLookupTableAlloc(fullTableName, (const char*)tableFormat, tablesIndex->data.S32[i]); 387 numLines = psLookupTableRead(table); 304 388 } else { 305 389 psError(PS_ERR_BAD_PARAMETER_VALUE, true, PS_ERRORTEXT_psTime_BAD_TABLE_COUNT, i+1, numTables); … … 321 405 psFree(fullTableName); 322 406 psFree(tableName); 407 psFree(tableFormat); 323 408 psFree(table); 324 409 i++; … … 333 418 psFree(tablesFrom); 334 419 psFree(tablesTo); 420 psFree(tablesIndex); 421 psFree(tableFormats); 335 422 336 423 return true; … … 351 438 psTime *outTime = NULL; 352 439 353 354 440 // Error checks 355 if(type!=PS_TIME_TAI && type!=PS_TIME_UTC) { 441 if(type!=PS_TIME_TAI && type!=PS_TIME_UTC && type!=PS_TIME_UT1 && 442 type!=PS_TIME_TT) { 356 443 psError(PS_ERR_BAD_PARAMETER_VALUE, true, 357 444 PS_ERRORTEXT_psTime_TYPE_UNKNOWN, … … 360 447 } 361 448 449 // Allocate memory for structure 362 450 outTime = (psTime*)psAlloc(sizeof(psTime)); 363 451 452 // Initialize members 364 453 outTime->sec = 0; 365 454 outTime->nsec = 0; … … 375 464 psTime *time = NULL; 376 465 377 378 466 // Allocate psTime struct 379 467 time = psTimeAlloc(type); 380 468 469 // Verify time structure allocated 470 if(time == NULL) { 471 return NULL; 472 } 473 474 // Get the system time 381 475 if (gettimeofday(&now, (struct timezone *)0) == -1) { 382 476 psError(PS_ERR_OS_CALL_FAILED, true, … … 391 485 // Add most leapseconds to UTC time to get TAI time if necessary 392 486 if(type == PS_TIME_TAI) { 393 time->sec += p sTimeGetTAIDelta(time);487 time->sec += p_psTimeGetTAIDelta(time); 394 488 } 395 489 … … 397 491 } 398 492 493 static psTime* convertTimeTAIUTC(psTime* time) 494 { 495 psF64 deltaTAI = 0.0; 496 psS64 deltaSec = 0; 497 psU32 deltaNsec = 0; 498 psF64 deltaUTC = 0.0; 499 500 // Determine delta to convert between UTC and TAI 501 deltaTAI = p_psTimeGetTAIDelta(time); 502 deltaSec = (psS64)(deltaTAI); 503 deltaNsec = (psU32)((deltaTAI - (psF64)deltaSec) * 1e9); 504 505 // Determine seconds 506 time->sec -= deltaSec; 507 508 // Check for underflow in nsec 509 if(deltaNsec > time->nsec) { 510 // Borrow second 511 time->nsec += 1e9; 512 time->sec--; 513 } 514 515 // Determine nsec 516 time->nsec -= deltaNsec; 517 518 // Check for overflow in nsec 519 if(time->nsec >= 1e9) { 520 time->nsec -= 1e9; 521 time->sec++; 522 } 523 524 // Set new type 525 time->type = PS_TIME_UTC; 526 527 // Check if leapsecond present in delta 528 deltaUTC = p_psTimeGetTAIDelta(time); 529 if(fabs(deltaTAI-deltaUTC) >= 1.0) { 530 time->sec++; 531 } 532 533 return time; 534 } 535 536 static psTime* convertTimeUTCTAI(psTime* time) 537 { 538 psF64 delta = 0.0; 539 psS64 deltaSec = 0; 540 psU32 deltaNsec = 0; 541 542 // Determine delta to convert between UTC and TAI 543 delta = p_psTimeGetTAIDelta(time); 544 545 deltaSec = (psS64)(delta); 546 deltaNsec = (psU32)((delta - (psF64)deltaSec) * 1e9); 547 548 // Determine seconds 549 time->sec += deltaSec; 550 551 // Determine nsec 552 time->nsec += deltaNsec; 553 554 // Check for overflow in nsec 555 if(time->nsec >= 1e9) { 556 time->nsec -= 1e9; 557 time->sec++; 558 } 559 560 // Set new type 561 time->type = PS_TIME_TAI; 562 563 return time; 564 } 565 566 static psTime* convertTimeTAITT(psTime* time) 567 { 568 // Add TT offset 569 time->sec += TAI_TT_OFFSET_SECONDS; 570 time->nsec += TAI_TT_OFFSET_NANOSECONDS; 571 572 // Check for overflow in nsec 573 if(time->nsec >= 1e9) { 574 time->nsec -= 1e9; 575 time->sec++; 576 } 577 578 // Set new type 579 time->type = PS_TIME_TT; 580 581 return time; 582 } 583 584 static psTime* convertTimeTTTAI(psTime* time) 585 { 586 // Subtract TT offset 587 time->sec -= TAI_TT_OFFSET_SECONDS; 588 589 // Check for nsec underflow 590 if(TAI_TT_OFFSET_NANOSECONDS > time->nsec) { 591 // Borrow second 592 time->sec--; 593 time->nsec += 1e9; 594 } 595 time->nsec -= TAI_TT_OFFSET_NANOSECONDS; 596 597 // Check for overflow in nsec 598 if(time->nsec >= 1e9) { 599 time->nsec -= 1e9; 600 time->sec++; 601 } 602 603 // Set new type 604 time->type = PS_TIME_TAI; 605 606 return time; 607 } 608 609 static psTime* convertTimeUTCUT1(psTime* time) 610 { 611 psS64 ut1utc = 0; 612 613 // Get UT1-UTC value 614 ut1utc = (psS64)(psTimeGetUT1Delta(time,PS_IERS_A) * 1e9); 615 616 // Since UTC is within 0.9 sec of UT1 then nsec member is the member affected 617 if((ut1utc < 0) && (abs(ut1utc) > time->nsec)) { 618 // Borrow from sec 619 time->sec--; 620 if(time->leapsecond) { 621 time->leapsecond = false; 622 } else { 623 time->leapsecond = psTimeIsLeapSecond(time); 624 } 625 // Add to nsec 626 time->nsec += 1e9; 627 } 628 time->nsec += ut1utc; 629 630 // Check for overflow in nsec 631 if(time->nsec >= 1e9) { 632 time->nsec -= 1e9; 633 time->sec++; 634 if(time->leapsecond) { 635 time->leapsecond = false; 636 time->sec--; 637 } else { 638 time->leapsecond = psTimeIsLeapSecond(time); 639 } 640 } 641 642 // Set new type 643 time->type = PS_TIME_UT1; 644 645 return time; 646 } 647 399 648 psTime* psTimeConvert(psTime *time, psTimeType type) 400 649 { 401 double delta = 0.0;402 403 404 650 // Error checks 405 651 PS_ASSERT_PTR_NON_NULL(time,NULL); 406 PS_ASSERT_INT_WITHIN_RANGE(time->nsec,0,1e9-1,NULL); 407 408 if (time->type == type) { // time already right type. That was easy! 652 PS_ASSERT_INT_WITHIN_RANGE(time->nsec,0,(psU32)((1e9)-1),time); 653 654 // If the input type is UT1 then return time and generate error message 655 if(time->type == PS_TIME_UT1) { 656 psError(PS_ERR_BAD_PARAMETER_VALUE,true,"Cannot convert from UT1 time type"); 409 657 return time; 410 658 } 411 659 412 delta = psTimeGetTAIDelta(time); 413 414 if (type == PS_TIME_UTC) { 415 time->sec = time->sec - delta; // User wants UTC time. Subtract leapseconds. 416 } else if(type == PS_TIME_TAI) { 417 time->sec = time->sec + delta; // User wants TAI time. Add leapseconds. 660 // If the time to convert to is the same as psTime the return time 661 if (time->type == type) { 662 return time; 663 } 664 665 // Convert from TAI to UTC, TT, UT1 666 if(time->type == PS_TIME_TAI) { 667 // Convert from TAI to UTC 668 if(type == PS_TIME_UTC) { 669 time = convertTimeTAIUTC(time); 670 // Convert from TAI to TT 671 } else if(type == PS_TIME_TT) { 672 time = convertTimeTAITT(time); 673 // Convert from TAI to UT1 674 } else if(type == PS_TIME_UT1) { 675 // Convert to UTC first 676 time = convertTimeTAIUTC(time); 677 // Convert UTC to UT1 678 time = convertTimeUTCUT1(time); 679 // Convert from TAI to unknown time type 680 } else { 681 psError(PS_ERR_BAD_PARAMETER_VALUE, true, PS_ERRORTEXT_psTime_TYPE_UNKNOWN, type); 682 } 683 // Convert from TT to TAI, UTC, UT1 684 } else if(time->type == PS_TIME_TT) { 685 // Convert from TT to UTC 686 if(type == PS_TIME_UTC) { 687 // Convert to TAI time first 688 time = convertTimeTTTAI(time); 689 // Convert from TAI to UTC 690 time = convertTimeTAIUTC(time); 691 // Convert from TT to TAI 692 } else if(type == PS_TIME_TAI) { 693 time = convertTimeTTTAI(time); 694 // Convert from TT to UT1 695 } else if(type == PS_TIME_UT1) { 696 // Convert to UTC first 697 // Convert to TAI time first 698 time = convertTimeTTTAI(time); 699 // Convert from TAI to UTC 700 time = convertTimeTAIUTC(time); 701 // Convert from UTC to UT1 702 time = convertTimeUTCUT1(time); 703 // Convert from TT to unknown time type 704 } else { 705 psError(PS_ERR_BAD_PARAMETER_VALUE, true, PS_ERRORTEXT_psTime_TYPE_UNKNOWN, type); 706 } 707 // Convert from UTC to TAI, TT, UT1 708 } else if(time->type == PS_TIME_UTC) { 709 // Convert UTC to TAI 710 if(type == PS_TIME_TAI) { 711 time = convertTimeUTCTAI(time); 712 // Convert UTC to TT 713 } else if(type == PS_TIME_TT) { 714 // Convert to TAI time first 715 time = convertTimeUTCTAI(time); 716 // Convert TAI to TT 717 time = convertTimeTAITT(time); 718 // Convert UTC to UT1 719 } else if(type == PS_TIME_UT1) { 720 time = convertTimeUTCUT1(time); 721 // Convert UTC to unknown time type 722 } else { 723 psError(PS_ERR_BAD_PARAMETER_VALUE, true, PS_ERRORTEXT_psTime_TYPE_UNKNOWN, type); 724 } 725 // Convert unknown time type 418 726 } else { 419 psError(PS_ERR_BAD_PARAMETER_VALUE, true, PS_ERRORTEXT_psTime_TYPE_UNKNOWN, t ype);727 psError(PS_ERR_BAD_PARAMETER_VALUE, true, PS_ERRORTEXT_psTime_TYPE_UNKNOWN, time->type); 420 728 } 421 729 … … 423 731 } 424 732 425 double psTimeToLMST(psTime *time, doublelongitude)733 psF64 psTimeToLMST(psTime *time, psF64 longitude) 426 734 { 427 735 psF64 jdTdtDays = 0.0; … … 433 741 psF64 t = 0.0; 434 742 psF64 tu = 0.0; 435 psF64 ut1UtcDbl = 0.0;436 743 psF64 const1 = 24110.5493771; 437 744 psF64 const2 = 8639877.3173760; … … 440 747 psF64 const5 = -0.0000062; 441 748 psF64 const6 = 0.0000013; 442 psTime *ut1UtcDelta = NULL;443 749 psTime *tdtTime = NULL; 444 psTime *taiTime = NULL;445 psTime *utcTime = NULL;446 750 psTime *ut1Time = NULL; 447 448 751 449 752 // Error checks 450 753 PS_ASSERT_PTR_NON_NULL(time,NAN); 451 PS_ASSERT_INT_WITHIN_RANGE(time->nsec,0, 1e9-1,NAN);452 453 // Calculate TAI or UTC time based on type of time user passes454 if(time->type == PS_TIME_ TAI) {455 taiTime = psMemIncrRefCounter(time);456 utcTime = psTimeAlloc(PS_TIME_UTC);457 utcTime->sec = taiTime->sec - psTimeGetTAIDelta(time);458 utcTime->nsec = taiTime->nsec; 459 } else if(time->type == PS_TIME_UTC) {460 utcTime = psMemIncrRefCounter(time);461 taiTime = psTimeAlloc(PS_TIME_TAI);462 taiTime->sec = utcTime->sec + psTimeGetTAIDelta(time);463 taiTime->nsec = utcTime->nsec;464 }465 466 // Convert Universal Time (UTC) toUT1467 ut1 UtcDbl = psTimeGetUT1Delta(taiTime);468 ut cTime->type = PS_TIME_TAI; // Don't allow addition of leapseconds to ut1Time469 ut1Time = psTimeMath(utcTime, ut1UtcDbl);470 ut cTime->type = PS_TIME_UTC;471 754 PS_ASSERT_INT_WITHIN_RANGE(time->nsec,0,(psU32)((1e9)-1),NAN); 755 756 // Verify input time is not in UT1 seconds 757 if(time->type == PS_TIME_UT1) { 758 psError(PS_ERR_BAD_PARAMETER_VALUE,true,PS_ERRORTEXT_psTime_TYPE_INCORRECT,time->type); 759 return NAN; 760 } 761 762 // Determine time reference to TT 763 tdtTime = psTimeAlloc(time->type); 764 tdtTime->sec = time->sec; 765 tdtTime->nsec = time->nsec; 766 tdtTime->leapsecond = time->leapsecond; 767 tdtTime = psTimeConvert(tdtTime,PS_TIME_TT); 768 769 // Determine time reference to UT1 770 ut1Time = psTimeAlloc(time->type); 771 ut1Time->sec = time->sec; 772 ut1Time->nsec = time->nsec; 773 ut1Time->leapsecond = time->leapsecond; 774 ut1Time = psTimeConvert(ut1Time,PS_TIME_UT1); 472 775 473 776 // Calculate UT1 as Julian Centuries since J2000.0 … … 476 779 t = (jdUt1Days - 2451545.0)/36525.0; 477 780 478 // Calculate Terrestial Dynamical Time (TDT)479 tdtTime = psTimeMath(taiTime, 32.184);480 481 781 // Calculate TDT as Julian centuries since J2000.0 482 782 jdTdtDays = psTimeToJD(tdtTime); … … 486 786 fracDays = fmod(mjdUt1Days, 1.0); 487 787 488 // Calculate Greenwich Mean Sidereal Time (GMST) in radians. Equation set up to minimize multiplications. 489 gmstRad = fracDays*TWOPI+(const1+const2*tu+t*(const3+t*(const4+t*(const5+const6*t))))*S2R; 788 // Calculate Greenwich Mean Sidereal Time (GMST) in radians. 789 // Equation set up to minimize multiplications. 790 gmstRad = fracDays*TWOPI 791 + (const1+const2*tu+t*(const3+t*(const4+t*(const5+const6*t))))*S2R; 490 792 491 793 // Place GMST between 0 and 2*pi … … 496 798 497 799 // Free temporary structs 498 psFree(ut1UtcDelta);499 800 psFree(ut1Time); 500 801 psFree(tdtTime); 501 psFree(utcTime);502 psFree(taiTime);503 802 504 803 return lmstRad; 505 804 } 506 805 507 double psTimeGetUT1Delta(const psTime *time)508 { 509 psU32 nTables = 3;510 psF64 mjd= 0.0;511 psF64 result= 0.0;512 ps F64 dut2ut1 = 0.0;513 psF64 t= 0.0;514 ps Vector *dut = NULL;515 ps MetadataItem *tableMetadataItem= NULL;516 ps LookupStatusType status = PS_LOOKUP_SUCCESS;517 char *metadataTableNames[3] = {"ser7Table", "eopcTable", "finalsTable"};518 806 psF64 psTimeGetUT1Delta(const psTime *time, psTimeBulletin bulletin) 807 { 808 psU32 nTables = 2; 809 psF64 mjd = 0.0; 810 psF64 result = 0.0; 811 psU64 tableColumn = 0; 812 psF64 dut2ut1 = 0.0; 813 psF64 t = 0.0; 814 psVector* dut = NULL; 815 psMetadataItem* tableMetadataItem = NULL; 816 psLookupStatusType status = PS_LOOKUP_SUCCESS; 817 char* metadataTableNames[2] = {"dailyTable", "finalsTable"}; 519 818 520 819 // Error checks 521 820 PS_ASSERT_PTR_NON_NULL(time,NAN); 522 PS_ASSERT_INT_WITHIN_RANGE(time->nsec,0,1e9-1,NAN); 523 524 if(time->type != PS_TIME_TAI) { 525 psError(PS_ERR_BAD_PARAMETER_VALUE, true, PS_ERRORTEXT_psTime_TYPE_INCORRECT, time->type); 526 return 0.0; 821 PS_ASSERT_INT_WITHIN_RANGE(time->nsec,0,(psU32)((1e9)-1),NAN); 822 823 // Check for invalid bulletin specified 824 if((bulletin != PS_IERS_A) && (bulletin != PS_IERS_B)) { 825 psError(PS_ERR_BAD_PARAMETER_VALUE,true,"Invalid bulletin specified %d",bulletin); 826 return NAN; 827 } 828 829 // Set lookup table column based on Bullentin 830 if(bulletin == PS_IERS_A) { 831 tableColumn = 3; 832 } else { 833 tableColumn = 6; 527 834 } 528 835 529 836 // Attempt to find value through table lookup and interpolation 530 837 mjd = psTimeToMJD(time); 531 result = searchTables(mjd, 0, &status, metadataTableNames, nTables);838 result = searchTables(mjd,tableColumn,metadataTableNames,nTables,&status); 532 839 533 840 // Value could not be found through table lookup and interpolation … … 535 842 536 843 // Date too early for tables. Get default time delta value from metadata, and issue warning. 537 psError(PS_ERR_BAD_PARAMETER_VALUE, true, PS_ERRORTEXT_psTime_TIME_PREDATES_TABLES, mjd, "UT1-UTC"); 538 844 psLogMsg(__func__,PS_LOG_WARN,PS_ERRORTEXT_psTime_TIME_PREDATES_TABLES,mjd,"UT1-UTC"); 845 846 // Lookup value from time metadata loaded from psTime.config 539 847 tableMetadataItem = psMetadataLookup(timeMetadata, "psLib.time.before.dut"); 540 848 if(tableMetadataItem == NULL) { 541 psError(PS_ERR_BAD_PARAMETER_VALUE, true, PS_ERRORTEXT_psTime_LOOKUP_METADATA_FAILED, "psLib.time.before.dut"); 542 return 0.0; 849 psError(PS_ERR_BAD_PARAMETER_VALUE, true, PS_ERRORTEXT_psTime_LOOKUP_METADATA_FAILED, 850 "psLib.time.before.dut"); 851 return NAN; 543 852 } 544 853 result = tableMetadataItem->data.F64; … … 552 861 t = 2000.0 + (MJD - 51544.03)/365.2422 553 862 */ 554 psError(PS_ERR_BAD_PARAMETER_VALUE, true, PS_ERRORTEXT_psTime_TIME_POSTDATES_TABLES, mjd, "UT1-UTC"); 555 863 // Generate warning of postdate information 864 psLogMsg(__func__,PS_LOG_WARN,PS_ERRORTEXT_psTime_TIME_POSTDATES_TABLES, mjd, "UT1-UTC"); 865 866 // Lookup values to calculate prediction 556 867 tableMetadataItem = psMetadataLookup(timeMetadata, "psLib.time.predict.dut"); 557 868 if(tableMetadataItem == NULL) { 558 psError(PS_ERR_BAD_PARAMETER_VALUE, true, PS_ERRORTEXT_psTime_LOOKUP_METADATA_FAILED, "psLib.time.predict.dut"); 559 return 0.0; 869 psError(PS_ERR_BAD_PARAMETER_VALUE, true, PS_ERRORTEXT_psTime_LOOKUP_METADATA_FAILED, 870 "psLib.time.predict.dut"); 871 return NAN; 560 872 } 561 873 dut = (psVector*)tableMetadataItem->data.V; 562 PS_ASSERT_PTR_NON_NULL(dut,0.0); 563 874 PS_ASSERT_PTR_NON_NULL(dut,NAN); 875 876 // Calculate predication of future UT1-UTC 564 877 t = 2000.0 + (mjd - 51544.03)/365.2422; 565 878 dut2ut1 = 0.022*sin(TWOPI*t) - 0.012*cos(TWOPI*t) - 0.006*sin(4.0*M_PI*t) + 0.007*cos(4.0*M_PI*t); … … 568 881 } else if(status != PS_LOOKUP_SUCCESS) { 569 882 psError(PS_ERR_BAD_PARAMETER_VALUE, true, PS_ERRORTEXT_psTime_INTERPOLATION_FAILED); 570 return 0.0;883 return NAN; 571 884 } 572 885 … … 574 887 } 575 888 576 struct psSphere* p sTimeGetPoleCoords(const psTime* time)889 struct psSphere* p_psTimeGetPoleCoords(const psTime* time) 577 890 { 578 891 psU32 nTables = 3; … … 587 900 psLookupStatusType yStatus = PS_LOOKUP_SUCCESS; 588 901 psMetadataItem *tableMetadataItem = NULL; 589 char *metadataTableNames[3] = {" ser7Table", "eopcTable", "finalsTable"};902 char *metadataTableNames[3] = {"dailyTable", "eopcTable", "finalsTable"}; 590 903 psVector *xp = NULL; 591 904 psVector *yp = NULL; … … 593 906 // Error checks 594 907 PS_ASSERT_PTR_NON_NULL(time,NULL); 595 PS_ASSERT_INT_WITHIN_RANGE(time->nsec,0, 1e9-1,NULL);908 PS_ASSERT_INT_WITHIN_RANGE(time->nsec,0,(psU32)((1e9)-1),NULL); 596 909 597 910 if(time->type != PS_TIME_TAI) … … 603 916 // Attempt to find value through table lookup and interpolation 604 917 mjd = psTimeToMJD(time); 605 x = searchTables(mjd, 0, &xStatus, metadataTableNames, nTables); 606 y = searchTables(mjd, 0, &yStatus, metadataTableNames, nTables); 918 // x = searchTables(mjd, 0, &xStatus, metadataTableNames, nTables); 919 x = searchTables(mjd, 0, metadataTableNames, nTables,&xStatus); 920 // y = searchTables(mjd, 0, &yStatus, metadataTableNames, nTables); 921 y = searchTables(mjd, 0, metadataTableNames, nTables,&yStatus); 607 922 608 923 // Value could not be found through table lookup and interpolation … … 641 956 psError(PS_ERR_BAD_PARAMETER_VALUE, true, PS_ERRORTEXT_psTime_TIME_POSTDATES_TABLES, mjd, "polar motion"); 642 957 643 644 958 // Get predicted MJD 645 959 tableMetadataItem = psMetadataLookup(timeMetadata, "psLib.time.predict.mjd"); … … 692 1006 } 693 1007 694 // Create output sphere and convert arcsec to radians (i.e. x/60/60* M_PI/180)1008 // Create output sphere and convert arcsec to radians (i.e. x/60/60*PS_PI/180) 695 1009 output = psAlloc(sizeof(psSphere)); 696 1010 output->r = x * M_PI / 648000.0; … … 700 1014 } 701 1015 702 double psTimeGetTAIDelta(const psTime *time) 703 { 704 psU64 i = 0; 1016 psF64 p_psTimeGetTAIDelta(const psTime *time) 1017 { 705 1018 psF64 jd = 0.0; 706 1019 psF64 mjd = 0.0; … … 711 1024 psLookupTable* table = NULL; 712 1025 psMetadataItem *tableMetadataItem = NULL; 713 psVector *stats = NULL;714 1026 psVector *results = NULL; 715 1027 716 1028 // Error checks 717 1029 PS_ASSERT_PTR_NON_NULL(time,NAN); 718 PS_ASSERT_INT_WITHIN_RANGE(time->nsec,0, 1e9-1,NAN);1030 PS_ASSERT_INT_WITHIN_RANGE(time->nsec,0,(psU32)((1e9)-1),NAN); 719 1031 720 1032 // Check time metadata … … 739 1051 mjd = psTimeToMJD(time); 740 1052 741 stats = psVectorAlloc(table->numCols, PS_TYPE_U32); 742 results = psLookupTableInterpolateAll(table, jd, stats); 1053 // Set ceiling of the julian date to the last entry in the lookup table 1054 if(table->validTo < jd) { 1055 jd = table->validTo; 1056 } 1057 1058 // Interpolation of look up table 1059 results = psLookupTableInterpolateAll(table, jd); 743 1060 744 1061 // Check for successful interpolation 745 for(i=0; i<stats->n; i++) { 746 if(stats->data.U32[i] == PS_LOOKUP_ERROR) { 747 psError(PS_ERR_BAD_PARAMETER_VALUE, true, PS_ERRORTEXT_psTime_INTERPOLATION_FAILED); 748 } 749 } 750 751 const1 = results->data.F64[0]; 752 const2 = results->data.F64[1]; 753 const3 = results->data.F64[2]; 754 out = const1 + (mjd - const2) * const3; 755 756 psFree(stats); 1062 if(results == NULL) { 1063 psError(PS_ERR_BAD_PARAMETER_VALUE, true, PS_ERRORTEXT_psTime_INTERPOLATION_FAILED); 1064 } 1065 1066 // Set constants from table 1067 const1 = results->data.F64[1]; 1068 const2 = results->data.F64[2]; 1069 const3 = results->data.F64[3]; 1070 1071 // If const3 not equal to zero solve for difference else floor of const1 1072 if(fabs(const3-0.0) > FLT_EPSILON) { 1073 out = const1 + (mjd - const2) * const3; 1074 } else { 1075 out = floor(const1); 1076 } 1077 757 1078 psFree(results); 758 1079 … … 760 1081 } 761 1082 762 763 1083 psS64 psTimeLeapSecondDelta(const psTime *time1, const psTime *time2) 764 1084 { 765 1085 psS64 diff = 0; 766 767 1086 768 1087 // Error checks 769 1088 PS_ASSERT_PTR_NON_NULL(time1,0); 770 1089 PS_ASSERT_PTR_NON_NULL(time2,0); 771 PS_ASSERT_INT_WITHIN_RANGE(time1->nsec,0, 1e9-1,0);772 PS_ASSERT_INT_WITHIN_RANGE(time2->nsec,0, 1e9-1,0);773 diff = abs((psS64)p sTimeGetTAIDelta((psTime*)time1)-(psS64)psTimeGetTAIDelta((psTime*)time2));1090 PS_ASSERT_INT_WITHIN_RANGE(time1->nsec,0,(psU32)((1e9)-1),0); 1091 PS_ASSERT_INT_WITHIN_RANGE(time2->nsec,0,(psU32)((1e9)-1),0); 1092 diff = abs((psS64)p_psTimeGetTAIDelta((psTime*)time1)-(psS64)p_psTimeGetTAIDelta((psTime*)time2)); 774 1093 775 1094 return diff; 776 1095 } 777 1096 778 double psTimeToJD(const psTime *time) 779 { 780 double jd = 0.0; 1097 psBool psTimeIsLeapSecond(const psTime* utc) 1098 { 1099 psTime* prevUtc = NULL; 1100 psBool returnValue = false; 1101 1102 // Check for valid time 1103 PS_ASSERT_PTR_NON_NULL(utc,false); 1104 1105 // Verify time is UTC type 1106 if(utc->type != PS_TIME_UTC) { 1107 psError(PS_ERR_BAD_PARAMETER_VALUE,true,PS_ERRORTEXT_psTime_TYPE_INCORRECT,utc->type); 1108 return false; 1109 } 1110 1111 // Allocate time to hold utc - 1 second 1112 prevUtc = psTimeAlloc(PS_TIME_UTC); 1113 prevUtc->sec = utc->sec - 1; 1114 1115 // Check the absolute difference between the two times for leapsecond 1116 if(psTimeLeapSecondDelta(utc,prevUtc) >= 1.0) { 1117 returnValue = true; 1118 } else { 1119 returnValue = false; 1120 } 1121 1122 // Free prevUtc 1123 psFree(prevUtc); 1124 1125 return returnValue; 1126 } 1127 1128 psF64 psTimeToJD(const psTime *time) 1129 { 1130 psF64 jd = NAN; 781 1131 782 1132 // Error checks 783 1133 PS_ASSERT_PTR_NON_NULL(time,NAN); 784 PS_ASSERT_INT_WITHIN_RANGE(time->nsec,0, 1e9-1,NAN);1134 PS_ASSERT_INT_WITHIN_RANGE(time->nsec,0,(psU32)((1e9)-1),NAN); 785 1135 786 1136 // Julian date conversion 787 1137 if(time->sec < 0) { 788 jd = time->sec / SEC_PER_DAY - time->nsec / NSEC_PER_DAY + 2440587.5; // psTime earlier than epoch 1138 // psTime earlier than epoch 1139 jd = time->sec / SEC_PER_DAY - time->nsec / NSEC_PER_DAY + JD_EPOCH_OFFSET; 789 1140 } else { 790 jd = time->sec / SEC_PER_DAY + time->nsec / NSEC_PER_DAY + 2440587.5; // psTime greater than epoch 1141 // psTime greater than epoch 1142 jd = time->sec / SEC_PER_DAY + time->nsec / NSEC_PER_DAY + JD_EPOCH_OFFSET; 791 1143 } 792 1144 … … 794 1146 } 795 1147 796 double psTimeToMJD(const psTime *time) 797 { 798 double mjd = 0.0; 799 1148 psF64 psTimeToMJD(const psTime *time) 1149 { 1150 psF64 mjd = NAN; 800 1151 801 1152 // Error checks 802 1153 PS_ASSERT_PTR_NON_NULL(time,NAN); 803 PS_ASSERT_INT_WITHIN_RANGE(time->nsec,0, 1e9-1,NAN);1154 PS_ASSERT_INT_WITHIN_RANGE(time->nsec,0,(psU32)((1e9)-1),NAN); 804 1155 805 1156 // Modified Julian date conversion 806 1157 if(time->sec < 0) { 807 mjd = time->sec / SEC_PER_DAY - time->nsec / NSEC_PER_DAY + 40587.0; // psTime earlier than epoch 1158 // psTime earlier than epoch 1159 mjd = time->sec / SEC_PER_DAY - time->nsec / NSEC_PER_DAY + MJD_EPOCH_OFFSET; 808 1160 } else { 809 mjd = time->sec / SEC_PER_DAY + time->nsec / NSEC_PER_DAY + 40587.0; // psTime greater than epoch 1161 // psTime greater than epoch 1162 mjd = time->sec / SEC_PER_DAY + time->nsec / NSEC_PER_DAY + MJD_EPOCH_OFFSET; 810 1163 } 811 1164 … … 815 1168 char* psTimeToISO(const psTime *time) 816 1169 { 817 psS32 ms = 0;1170 psS32 ds = 0; 818 1171 char *timeString = NULL; 819 1172 char *tempString = NULL; … … 821 1174 time_t sec; 822 1175 823 824 1176 // Error checks 825 1177 PS_ASSERT_PTR_NON_NULL(time,NULL); 826 PS_ASSERT_INT_WITHIN_RANGE(time->nsec,0,1e9-1,NULL); 827 1178 PS_ASSERT_INT_WITHIN_RANGE(time->nsec,0,(psU32)((1e9)-1),NULL); 1179 1180 // Check valid year range 1181 PS_ASSERT_LONG_WITHIN_RANGE(time->sec,YEAR_0000_SEC,YEAR_9999_SEC,NULL) 1182 1183 // Allocate temp strings 828 1184 tempString = psAlloc(MAX_TIME_STRING_LENGTH); 829 1185 timeString = psAlloc(MAX_TIME_STRING_LENGTH); 830 1186 831 ms = time->nsec / 1000000; 1187 // Convert nanoseconds to decaseconds 1188 ds = time->nsec / 100000000; 832 1189 sec = time->sec; 1190 1191 // If leapsecond use previous day 1192 if(time->leapsecond) { 1193 sec--; 1194 } 833 1195 834 1196 // tmTime variable is statically allocated, no need to free … … 840 1202 } 841 1203 842 if (snprintf(timeString, MAX_TIME_STRING_LENGTH, "%s.%3.3dZ", tempString, ms) < 0) { 1204 // Check if time is UTC and leapsecond 1205 if(((time->type==PS_TIME_UTC)||(time->type==PS_TIME_UT1)) && (time->leapsecond)) { 1206 // Modify second to be 60 1207 tempString[17] = '6'; 1208 tempString[18] = '0'; 1209 } 1210 1211 // Create string with milliseconds 1212 if (snprintf(timeString, MAX_TIME_STRING_LENGTH, "%s,%1dZ", tempString, ds) < 0) { 843 1213 psError(PS_ERR_OS_CALL_FAILED, true, PS_ERRORTEXT_psTime_APPEND_MSEC_FAILED); 844 1214 } … … 848 1218 } 849 1219 850 struct timeval psTimeToTimeval(const psTime *time) 851 { 852 struct timeval timevalTime; 853 854 timevalTime.tv_sec = 0; 855 timevalTime.tv_usec = 0; 1220 struct timeval* psTimeToTimeval(const psTime *time) 1221 { 1222 struct timeval *timevalTime = NULL; 856 1223 857 1224 // Error checks 858 PS_ASSERT_PTR_NON_NULL(time,timevalTime); 859 PS_ASSERT_INT_WITHIN_RANGE(time->nsec,0,1e9-1,timevalTime); 860 861 timevalTime.tv_sec = time->sec; 862 timevalTime.tv_usec = time->nsec / 1000; 1225 PS_ASSERT_PTR_NON_NULL(time,NULL); 1226 PS_ASSERT_INT_WITHIN_RANGE(time->sec,0,INT32_MAX,NULL); 1227 PS_ASSERT_INT_WITHIN_RANGE(time->nsec,0,(psU32)((1e9)-1),NULL); 1228 1229 // Allocate structure timeval 1230 timevalTime = (struct timeval*)psAlloc(sizeof(struct timeval)); 1231 1232 // Set structure members 1233 timevalTime->tv_sec = time->sec; 1234 timevalTime->tv_usec = time->nsec / 1000; 863 1235 864 1236 return timevalTime; 865 1237 } 866 1238 867 struct tm* psTimeToTM(const psTime *time) 1239 /* 1240 struct tm* p_psTimeToTM(const psTime *time) 868 1241 { 869 1242 psS64 cent = 0; … … 876 1249 psS64 temp = 0; 877 1250 struct tm* tmTime = NULL; 878 879 1251 1252 880 1253 // Error checks 881 1254 PS_ASSERT_PTR_NON_NULL(time,NULL); 882 PS_ASSERT_INT_WITHIN_RANGE(time->nsec,0, 1e9-1,NULL);883 1255 PS_ASSERT_INT_WITHIN_RANGE(time->nsec,0,(psU32)((1e9)-1),NULL); 1256 884 1257 seconds = time->sec%60; 885 1258 minute = time->sec/60%60; 886 1259 hour = time->sec/3600%24; 887 1260 day = (time->sec+62135596800)/86400; 888 1261 889 1262 // Add 306 days to make relative to Mar 1, 0; also adjust day to be within a range (1..2**28-1) where our 890 1263 // calculations will work with 32bit ints … … 898 1271 day -= temp * 146097; 899 1272 } 900 1273 901 1274 cent = (day*4-1)/146097; // Calc number of centuries day is after 29 Feb of yr 0 902 1275 day -= cent*146097/4; // 4 centuries = 146097 days … … 906 1279 day -= (month*367-1094)/12; // February of following year) 907 1280 year += cent*100+temp*400; // Get the real year, which is off by 908 1281 909 1282 // One if month is January or February 910 1283 if(month > 12) … … 913 1286 month -= 12; 914 1287 } 915 1288 916 1289 // Allocate output 917 1290 tmTime = (struct tm*)psAlloc(sizeof(struct tm)); 918 1291 919 1292 tmTime->tm_year = year - 1900; 920 1293 tmTime->tm_mon = month - 1; … … 924 1297 tmTime->tm_sec = seconds; 925 1298 tmTime->tm_isdst = -1; 926 1299 927 1300 return tmTime; 928 1301 } 929 930 psTime* psTimeFromJD(double time) 931 { 932 double days = 0.0; 933 double seconds = 0.0; 1302 */ 1303 1304 psTime* psTimeFromJD(psF64 time) 1305 { 1306 psF64 days = 0.0; 1307 psF64 seconds = 0.0; 934 1308 psTime *outTime = NULL; 935 936 1309 937 1310 // Allocate psTime struct … … 949 1322 950 1323 // Error check 951 PS_ASSERT_INT_WITHIN_RANGE(outTime->nsec,0, 1e9-1,outTime);1324 PS_ASSERT_INT_WITHIN_RANGE(outTime->nsec,0,(psU32)((1e9)-1),outTime); 952 1325 953 1326 return outTime; 954 1327 } 955 1328 956 psTime* psTimeFromMJD( doubletime)957 { 958 doubledays = 0.0;959 doubleseconds = 0.0;1329 psTime* psTimeFromMJD(psF64 time) 1330 { 1331 psF64 days = 0.0; 1332 psF64 seconds = 0.0; 960 1333 psTime *outTime = NULL; 961 962 1334 963 1335 // Allocate psTime struct … … 967 1339 days = time - 40587.0; 968 1340 seconds = days * SEC_PER_DAY; 1341 969 1342 if(seconds < 0.0) { 970 1343 outTime->nsec = (seconds - (psS64)seconds) * -1000000000.0; // psTime earlier than epoch … … 975 1348 976 1349 // Error check 977 PS_ASSERT_INT_WITHIN_RANGE(outTime->nsec,0, 1e9-1,outTime);1350 PS_ASSERT_INT_WITHIN_RANGE(outTime->nsec,0,(psU32)((1e9)-1),NULL); 978 1351 979 1352 return outTime; … … 986 1359 psTime *outTime = NULL; 987 1360 1361 // Check for NULL string 1362 PS_ASSERT_PTR_NON_NULL(time,NULL); 1363 988 1364 // Convert YYYY-MM-DDThh:mm:ss.sss in string form to tm time 989 if (sscanf(time, "%d-%d-%dT%d:%d:%d .%d", &tmTime.tm_year, &tmTime.tm_mon, &tmTime.tm_mday,1365 if (sscanf(time, "%d-%d-%dT%d:%d:%d,%d", &tmTime.tm_year, &tmTime.tm_mon, &tmTime.tm_mday, 990 1366 &tmTime.tm_hour, &tmTime.tm_min, &tmTime.tm_sec,&millisecond) < 7) { 991 1367 psError(PS_ERR_BAD_PARAMETER_VALUE, true, PS_ERRORTEXT_psTime_ISOTIME_MALFORMED, time); … … 1006 1382 1007 1383 // Convert tm time to psTime 1008 outTime = p sTimeFromTM(&tmTime);1384 outTime = p_psTimeFromTM(&tmTime); 1009 1385 outTime->nsec = millisecond * 1000000; 1386 1387 return outTime; 1388 } 1389 1390 psTime* psTimeFromTT(psS64 sec, psU32 nsec) 1391 { 1392 psTime* outTime = NULL; 1393 1394 // Verify nsec within range 1395 PS_ASSERT_INT_WITHIN_RANGE(nsec,0,(psU32)((1e9)-1),NULL); 1396 1397 // Allocate psTime data 1398 outTime = psTimeAlloc(PS_TIME_TT); 1399 1400 // Set data members 1401 outTime->sec = sec; 1402 outTime->nsec = nsec; 1403 1404 // Return data structure 1405 return outTime; 1406 } 1407 1408 psTime* psTimeFromUTC(psS64 sec, psU32 nsec, psBool leapsecond) 1409 { 1410 psTime* outTime = NULL; 1411 1412 // Verify nsec within range 1413 PS_ASSERT_INT_WITHIN_RANGE(nsec,0,(psU32)((1e9)-1),NULL); 1414 1415 // Allocate psTime data 1416 outTime = psTimeAlloc(PS_TIME_UTC); 1417 1418 // Set data members 1419 outTime->sec = sec; 1420 outTime->nsec = nsec; 1421 1422 // Set leapsecond flag if necessary 1423 outTime->leapsecond = psTimeIsLeapSecond(outTime); 1010 1424 1011 1425 return outTime; … … 1028 1442 1029 1443 // Error check 1030 PS_ASSERT_INT_WITHIN_RANGE(outTime->nsec,0, 1e9-1,outTime);1444 PS_ASSERT_INT_WITHIN_RANGE(outTime->nsec,0,(psU32)((1e9)-1),outTime); 1031 1445 1032 1446 return outTime; 1033 1447 } 1034 1448 1035 psTime* p sTimeFromTM(const struct tm* time)1449 psTime* p_psTimeFromTM(const struct tm* time) 1036 1450 { 1037 1451 psS64 year; … … 1044 1458 psTime *outTime = NULL; 1045 1459 1046 1047 1460 // Error check 1048 1461 PS_ASSERT_PTR_NON_NULL(time,NULL); … … 1062 1475 if( month <= 2 ) 1063 1476 { 1064 year -= (temp = (14 - month) / 12); 1477 temp = (14 - month) / 12; 1478 // year -= (temp = (14 - month) / 12); 1479 year -= temp; 1065 1480 month += 12 * temp; 1066 1481 } else if(month > 14) 1067 1482 { 1068 year += (temp = (month - 3) / 12); 1483 temp = (month - 3) / 12; 1484 // year += (temp = (month - 3) / 12); 1485 year += temp; 1069 1486 month -= 12 * temp; 1070 1487 } … … 1081 1498 // days to adjust from Mar 1, year 0-relative to Jan 1, year 1-relative. Add hours, minutes, and seconds. 1082 1499 day += (month * 367 - 1094) / 12 + year % 100 * 1461 / 4 + (year/100 * 36524 + year/400) - 306; 1083 outTime->sec = (((day - 1) * SEC_PER_DAY) - 62135596800) + hour*SEC_PER_HOUR + minute*SEC_PER_MINUTE + seconds; 1500 outTime->sec = (((day - 1) * SEC_PER_DAY) - 62135596800) + hour*SEC_PER_HOUR 1501 + minute*SEC_PER_MINUTE + seconds; 1084 1502 1085 1503 // C's TM does not define a microsecond field. Microseconds must be manipulated by calling function. … … 1087 1505 1088 1506 // Error check 1089 PS_ASSERT_INT_WITHIN_RANGE(outTime->nsec,0, 1e9-1,outTime);1507 PS_ASSERT_INT_WITHIN_RANGE(outTime->nsec,0,(psU32)((1e9)-1),outTime); 1090 1508 1091 1509 return outTime; … … 1098 1516 psTime *tempTime = NULL; 1099 1517 1100 1101 1518 // Error checks 1102 1519 PS_ASSERT_PTR_NON_NULL(time,NULL); 1103 PS_ASSERT_INT_WITHIN_RANGE(time->nsec,0, 1e9-1,NULL);1520 PS_ASSERT_INT_WITHIN_RANGE(time->nsec,0,(psU32)((1e9)-1),NULL); 1104 1521 1105 1522 // Convert time to TAI if necessary, but without changing input arguments … … 1109 1526 tempTime->nsec = time->nsec; 1110 1527 tempTime = psTimeConvert(tempTime, PS_TIME_TAI); 1528 outTime = psTimeAlloc(PS_TIME_TAI); 1111 1529 } else { 1112 1530 tempTime = psMemIncrRefCounter((psTime*)time); 1531 outTime = psTimeAlloc(time->type); 1113 1532 } 1114 1533 1115 1534 // Create output time 1116 outTime = psTimeAlloc(PS_TIME_TAI);1117 1535 sec = delta + (psF64)tempTime->sec + (psF64)tempTime->nsec/1e9; 1118 outTime->sec = sec; 1119 outTime->nsec = (sec - outTime->sec)*1e9; 1536 PS_ASSERT_LONG_WITHIN_RANGE((psS64)sec,0,PS_MAX_S64,outTime); 1537 outTime->sec = (psS64)sec; 1538 outTime->nsec = (psU32)((sec - (psF64)outTime->sec)*1e9); 1120 1539 1121 1540 // Error check 1122 PS_ASSERT_INT_WITHIN_RANGE(outTime->nsec,0, 1e9-1,outTime);1541 PS_ASSERT_INT_WITHIN_RANGE(outTime->nsec,0,(psU32)((1e9)-1),outTime); 1123 1542 1124 1543 // Convert result to same time type as input … … 1140 1559 psTime *tempTime2 = NULL; 1141 1560 1142 1143 1561 // Error checks 1144 1562 PS_ASSERT_PTR_NON_NULL(time1,0.0); 1145 PS_ASSERT_INT_WITHIN_RANGE(time1->nsec,0, 1e9-1,0.0);1563 PS_ASSERT_INT_WITHIN_RANGE(time1->nsec,0,(psU32)((1e9)-1),0.0); 1146 1564 PS_ASSERT_PTR_NON_NULL(time2,0.0); 1147 PS_ASSERT_INT_WITHIN_RANGE(time2->nsec,0,1e9-1,0.0); 1565 PS_ASSERT_INT_WITHIN_RANGE(time2->nsec,0,(psU32)((1e9)-1),0.0); 1566 1567 // Verify both times of the same type 1568 if(time1->type != time2->type) { 1569 psError(PS_ERR_BAD_PARAMETER_VALUE,true,PS_ERRORTEXT_psTime_TYPE_INCORRECT,time1->type); 1570 return out; 1571 } 1148 1572 1149 1573 // Convert time to TAI if necessary, but without changing input arguments -
trunk/psLib/src/astronomy/psTime.h
r3713 r4051 1 1 /** @file psTime.h 2 2 * 3 * @brief Definitions for time, time utilities, and conversion functions for use with psLib astronomy 4 * functions. 5 * 6 * A collection of functions are required by psLib to manipulate time data. These functions primarily consist 7 * of conversions between specific time formats. They use the UNIX timeval time system as the 8 * base upon which International Atomic Time (TAI) and Universal Time Coordinated (UTC) are calculated. 3 * @brief Definitions for time, time utilities, and conversion functions for use 4 * with psLib astronomy functions. 5 * 6 * A collection of functions are required by psLib to manipulate time data. These 7 * functions primarily consist of conversions between specific time formats. They 8 * use the UNIX timeval time system as the base upon which International Atomic 9 * Time (TAI) and Universal Time Coordinated (UTC) are calculated. 9 10 * 10 11 * @author Ross Harman, MHPCC 11 12 * 12 * @version $Revision: 1.2 8$ $Name: not supported by cvs2svn $13 * @date $Date: 2005-0 4-19 02:44:12$13 * @version $Revision: 1.29 $ $Name: not supported by cvs2svn $ 14 * @date $Date: 2005-05-31 21:47:46 $ 14 15 * 15 16 * Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii 16 17 */ 17 18 18 19 19 #ifndef PSTIME_H … … 88 88 /** Allocate time struct. 89 89 * 90 * Allocates an empty time struct. User must specify the psTimeType (PS_TIME_TAI or PS_TIME_UTC) in the argument. 91 * The seconds and microseconds members of the struct are set to zero. 90 * Allocates an empty time struct. User must specify the psTimeType 91 * (PS_TIME_TAI or PS_TIME_UTC) in the argument. The seconds and microseconds members 92 * of the struct are set to zero. 92 93 * 93 94 * @return psTime*: Struct with empty time. … … 99 100 /** Get current time. 100 101 * 101 * Gets current time from the system clock. User must specify the psTimeType (PS_TIME_TAI or PS_TIME_UTC) in102 * the argument.102 * Gets current time from the system clock. User must specify the psTimeType 103 * (PS_TIME_TAI or PS_TIME_UTC) in the argument. 103 104 * 104 105 * @return psTime*: Struct with current time. … … 121 122 /** Convert psTime to Local Mean Sidereal Time (LMST). 122 123 * 123 * Converts psTime at the given longitude to LMST time. If the input time is not in UTC format, then it is124 * converted.125 * 126 * @return double: LST Time.127 */ 128 doublepsTimeToLMST(124 * Converts psTime at the given longitude to LMST time. If the input time is not 125 * in UTC format, then it is converted. 126 * 127 * @return psF64: LST Time. 128 */ 129 psF64 psTimeToLMST( 129 130 psTime *time, ///< psTime to be converted. 130 doublelongitude ///< Longitude.131 psF64 longitude ///< Longitude. 131 132 ); 132 133 … … 135 136 * This function is necessary to for various SLALIB functions. 136 137 * 137 * @return double: Time difference. 138 */ 139 double psTimeGetUT1Delta( 138 * @return psF64: Time difference. 139 */ 140 psF64 psTimeGetUT1Delta( 141 const psTime *time, ///< psTime to be looked up. 142 psTimeBulletin bulletin ///< IERS bulletin to use 143 ); 144 145 /** Determine TAI - UTC from table lookup. 146 * 147 * This function is necessary to for various psTime functions. 148 * 149 * @return psF64: Time difference. 150 */ 151 psF64 p_psTimeGetTAIDelta( 140 152 const psTime *time ///< psTime to be looked up. 141 153 ); 142 154 143 /** Determine TAI - UTC from table lookup.144 *145 * This function is necessary to for various psTime functions.146 *147 * @return double: Time difference.148 */149 double psTimeGetTAIDelta(150 const psTime *time ///< psTime to be looked up.151 );152 153 155 /** Determine polar coordinates at a given time. 154 156 * … … 157 159 * @return psSphere*: Spherical coordinates of Earth's polar axias. 158 160 */ 159 struct psSphere* p sTimeGetPoleCoords(160 const psTime *time ///< psTime determine polar orientation.161 struct psSphere* p_psTimeGetPoleCoords( 162 const psTime *time ///< psTime determine polar orientation. 161 163 ); 162 164 … … 172 174 ); 173 175 176 /** Determine if UTC time is a leapsecond. 177 * 178 * Determines if the specified UTC time is a valid leapsecond. 179 * 180 * @return psBool: valid leap second 181 */ 182 psBool psTimeIsLeapSecond( 183 const psTime* utc ///< UTC to verify if leap second 184 ); 185 174 186 /** Convert psTime to Julian date time. 175 187 * 176 * Converts psTime to Julian date (JD) time. This function does not add or subtract leapseconds. 177 * 178 * @return double: Julian Date (JD) time. 179 */ 180 double psTimeToJD( 188 * Converts psTime to Julian date (JD) time. This function does not add or 189 * subtract leapseconds. 190 * 191 * @return psF64: Julian Date (JD) time. 192 */ 193 psF64 psTimeToJD( 181 194 const psTime* time ///< Input time to be converted. 182 195 ); 183 196 /** Convert psTime to modified Julian date time. 184 197 * 185 * Converts psTime to modified Julian date (MJD) time. This function does not add or subtract leapseconds. 186 * 187 * @return double: Modified Julian Days (MJD) time. 188 */ 189 double psTimeToMJD( 198 * Converts psTime to modified Julian date (MJD) time. This function does not 199 * add or subtract leapseconds. 200 * 201 * @return psF64: Modified Julian Days (MJD) time. 202 */ 203 psF64 psTimeToMJD( 190 204 const psTime* time ///< Input time to be converted. 191 205 ); … … 193 207 /** Convert psTime to ISO8601 formatted string. 194 208 * 195 * Converts psTime to a null terminated string in the form of YYYY-MM-DDThh:mm:ss.sss. This function does not196 * add or subtract leapseconds.209 * Converts psTime to a null terminated string in the form of YYYY-MM-DDThh:mm:ss.sss. 210 * This function does not add or subtract leapseconds. 197 211 * 198 212 * @return char*: Pointer null terminated array of chars in ISO time. … … 206 220 * Converts psTime to timeval time. This function does not add or subtract leapseconds. 207 221 * 208 * @return timeval : timeval struct time.209 */ 210 struct timeval psTimeToTimeval(211 const psTime* time ///< Input time to be converted.222 * @return timeval*: timeval struct time. 223 */ 224 struct timeval* psTimeToTimeval( 225 const psTime* time ///< Input time to be converted. 212 226 ); 213 227 214 /** Convert psTime to tm time. 215 * 216 * Converts psTime to tm time. This function is based on a Perl algorithm availble in the Pan-STARRS Image 217 * processing Algorithm Design Description (ADD). This function does not add or subtract leapseconds. 228 /* 229 * Convert psTime to tm time. 230 * 231 * Converts psTime to tm time. This function is based on a Perl algorithm availble 232 * in the Pan-STARRS Image processing Algorithm Design Description (ADD). This function 233 * does not add or subtract leapseconds. 218 234 * 219 235 * @return tm: tm struct time. 220 * /221 struct tm* p sTimeToTM(222 const psTime *time ///< Input time to be converted.236 * 237 struct tm* p_psTimeToTM( 238 const psTime *time ///< Input time to be converted. 223 239 ); 224 240 */ 225 241 /** Convert JD to psTime. 226 242 * … … 230 246 */ 231 247 psTime* psTimeFromJD( 232 double time///< Input time to be converted.248 psF64 time ///< Input time to be converted. 233 249 ); 234 250 … … 240 256 */ 241 257 psTime* psTimeFromMJD( 242 double time///< Input time to be converted.258 psF64 time ///< Input time to be converted. 243 259 ); 244 260 … … 250 266 */ 251 267 psTime* psTimeFromISO( 252 const char* time ///< Input time to be converted.268 const char* time ///< Input time to be converted. 253 269 ); 254 270 … … 260 276 */ 261 277 psTime* psTimeFromTimeval( 262 const struct timeval *time ///< Input time to be converted. 278 const struct timeval *time ///< Input time to be converted. 279 ); 280 281 /** Convert Terrestrial Time to psTime 282 * 283 * Converts Terrestial Time to psTime. This function assumes resultant time is of type TT. 284 * 285 * @return psTime*: time (TT) 286 */ 287 psTime* psTimeFromTT( 288 psS64 sec, ///< Input terrestrial time in seconds 289 psU32 nsec ///< Input terrestrial time fraction of seconds (nanoseconds) 290 ); 291 292 /** Convert UTC time to psTime 293 * 294 * Converts UTC time to psTime. It will verify if time specified is a leapsecond. 295 * 296 * @return psTime*: time (UTC) 297 */ 298 psTime* psTimeFromUTC( 299 psS64 sec, ///< Input time in seconds 300 psU32 nsec, ///< Input time fraction of seconds (nanoseconds) 301 psBool leapsecond ///< Input time is a leapsecond 263 302 ); 264 303 265 304 /** Convert tm time to psTime. 266 305 * 267 * Converts tm time to psTime. This function is based on a Perl algorithm availble in the Pan-STARRS Image 268 * processing Algorithm Design Description (ADD). This function does not add or subtract leapseconds. 306 * Converts tm time to psTime. This function is based on a Perl algorithm availble 307 * in the Pan-STARRS Image processing Algorithm Design Description (ADD). This function 308 * does not add or subtract leapseconds. 269 309 * 270 310 * @return psTime*: time. 271 311 */ 272 psTime* p sTimeFromTM(273 const struct tm *time ///< Input time to be converted.312 psTime* p_psTimeFromTM( 313 const struct tm *time ///< Input time to be converted. 274 314 ); 275 315 … … 281 321 */ 282 322 psTime* psTimeMath( 283 const psTime *time, ///< Time.284 psF64 delta ///< Time delta.323 const psTime *time, ///< Time. 324 psF64 delta ///< Time delta. 285 325 ); 286 326 … … 292 332 */ 293 333 psF64 psTimeDelta( 294 const psTime *time1, ///< First time.295 const psTime *time2 ///< Second time.334 const psTime *time1, ///< First time. 335 const psTime *time2 ///< Second time. 296 336 ); 297 337 -
trunk/psLib/src/dataManip/psConstants.h
r4049 r4051 6 6 * @author GLG, MHPCC 7 7 * 8 * @version $Revision: 1.7 0$ $Name: not supported by cvs2svn $9 * @date $Date: 2005-05-31 21: 25:27$8 * @version $Revision: 1.71 $ $Name: not supported by cvs2svn $ 9 * @date $Date: 2005-05-31 21:48:13 $ 10 10 * 11 11 * Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii … … 150 150 } 151 151 152 // Return an error if the arg lies outside the supplied range 153 #define PS_ASSERT_LONG_WITHIN_RANGE(NAME, LOWER, UPPER, RVAL) \ 154 if ((NAME) < (LOWER) || (NAME) > (UPPER)) { \ 155 psError(PS_ERR_BAD_PARAMETER_VALUE, true, \ 156 "Error: %s, %lld, is out of range.", \ 157 #NAME, NAME, LOWER, UPPER); \ 158 return RVAL; \ 159 } 160 152 161 /***************************************************************************** 153 162 Macros which take a generic psLib type and determine if it is NULL, or has -
trunk/psLib/src/math/psConstants.h
r4049 r4051 6 6 * @author GLG, MHPCC 7 7 * 8 * @version $Revision: 1.7 0$ $Name: not supported by cvs2svn $9 * @date $Date: 2005-05-31 21: 25:27$8 * @version $Revision: 1.71 $ $Name: not supported by cvs2svn $ 9 * @date $Date: 2005-05-31 21:48:13 $ 10 10 * 11 11 * Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii … … 150 150 } 151 151 152 // Return an error if the arg lies outside the supplied range 153 #define PS_ASSERT_LONG_WITHIN_RANGE(NAME, LOWER, UPPER, RVAL) \ 154 if ((NAME) < (LOWER) || (NAME) > (UPPER)) { \ 155 psError(PS_ERR_BAD_PARAMETER_VALUE, true, \ 156 "Error: %s, %lld, is out of range.", \ 157 #NAME, NAME, LOWER, UPPER); \ 158 return RVAL; \ 159 } 160 152 161 /***************************************************************************** 153 162 Macros which take a generic psLib type and determine if it is NULL, or has
Note:
See TracChangeset
for help on using the changeset viewer.
