IPP Software Navigation Tools IPP Links Communication Pan-STARRS Links

Ignore:
Timestamp:
May 31, 2005, 11:48:13 AM (21 years ago)
Author:
evanalst
Message:

SDR-14 function updates.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/psLib/src/astro/psTime.c

    r4029 r4051  
    1010 *  @author Ross Harman, MHPCC
    1111 *
    12  *  @version $Revision: 1.61 $ $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 $
    1414 *
    1515 *  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
     
    2424#include "psTime.h"
    2525#include "psError.h"
     26#include "psLogMsg.h"
    2627#include "psMemory.h"
    2728#include "psAbort.h"
     
    6970                static psMetadata *timeMetadata = NULL;
    7071
     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
    7188/** Static function prototypes */
    7289static char *cleanString(char *inString, int sLen);
    7390static char* getToken(char **inString, char *delimiter, psParseErrorType *status);
    74 psF64 searchTables(psF64 index, psU64 column, psLookupStatusType *status, char *metadataTableNames[], psU32 nTables);
    75 
     91static psF64 searchTables(psF64 index, psU64 column, char *metadataTableNames[],
     92                          psU32 nTables, psLookupStatusType* status);
     93static psTime* convertTimeTAIUTC(psTime* time);
     94static psTime* convertTimeUTCTAI(psTime* time);
     95static psTime* convertTimeTAITT(psTime* time);
     96static psTime* convertTimeTTTAI(psTime* time);
     97static psTime* convertTimeUTCUT1(psTime* time);
    7698
    7799/** Removes leading and trailing whitespace and # characters from a string. The cleaned string is a new null
     
    83105    char *cleaned = NULL;
    84106
    85 
    86107    ptrB = inString;
    87108
    88     /* Skip over leading # or whitespace */
     109    // Skip over leading # or whitespace
    89110    while (isspace(*ptrB) || *ptrB=='#') {
    90111        ptrB++;
    91112    }
    92113
    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;
    95116    while(isspace(*ptrE) || *ptrE=='\0' || *ptrE=='#') {
    96117        ptrE--;
     
    113134    int sLen = 0;
    114135
    115 
    116136    // Skip over leading whitespace
    117137    while(isspace(**inString)) {
     
    121141    // Length of token, not including delimiter
    122142    sLen = strcspn(*inString, delimiter);
     143
    123144    if(sLen) {
    124145
     
    127148
    128149        // Move to end of token
    129         (*inString) += sLen;
     150        (*inString) += (sLen+1);
     151
    130152    } else if(**inString!='\0' && sLen==0) {
    131153        *status = PS_PARSE_ERROR_GENERAL;
     
    148170
    149171
    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.
     174static 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;
    161181
    162182    // Check time metadata. Function call reports errors.
    163183    if(timeMetadata == NULL) {
    164184        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
    172193        tableName = metadataTableNames[i];
     194
     195        // Lookup table name in time metadata
    173196        tableMetadataItem = psMetadataLookup(timeMetadata, tableName);
     197
     198        // Check if table not a metadata item
    174199        if(tableMetadataItem == NULL) {
    175200            psError(PS_ERR_BAD_PARAMETER_VALUE, true, PS_ERRORTEXT_psTime_LOOKUP_METADATA_FAILED,
    176201                    tableName);
    177             return 0.0;
    178         }
     202            *status = PS_LOOKUP_ERROR;
     203            return NAN;
     204        }
     205
     206        // Get table from metadata
    179207        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;
    191226        }
    192227    }
     
    197232bool p_psTimeInit(const char *fileName)
    198233{
     234    psS32 numLines = 0;
    199235    bool foundTable = false;
    200236    char *tableDir = NULL;
    201237    char *tableNames = NULL;
     238    char *tableFormats = NULL;
    202239    char *namesPtr = NULL;
     240    char *formatPtr = NULL;
    203241    char *metadataNamesPtr = NULL;
    204242    char *tableName = NULL;
     243    char *tableFormat = NULL;
    205244    char *fullTableName = NULL;
    206245    psS32 i = 0;
     
    210249    psVector *tablesFrom = NULL;
    211250    psVector *tablesTo = NULL;
     251    psVector *tablesIndex = NULL;
    212252    psMetadataItem *metadataItem = NULL;
    213253    psLookupTable *table = NULL;
    214254    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"};
    216256
    217257    // Read time config file
     
    251291        psError(PS_ERR_BAD_PARAMETER_VALUE, true, PS_ERRORTEXT_psTime_LOOKUP_METADATA_FAILED,
    252292                "psLib.time.tables.to");
     293        psFree(tablesFrom);
    253294        return false;
    254295    }
     
    258299        psFree(tablesFrom);
    259300        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);
    260319        return false;
    261320    }
     
    268327        psFree(tablesFrom);
    269328        psFree(tablesTo);
     329        psFree(tablesIndex);
    270330        return false;
    271331    }
     
    280340        psFree(tablesFrom);
    281341        psFree(tablesTo);
     342        psFree(tablesIndex);
    282343        psFree(tableDir);
    283344        return false;
    284345    }
    285346    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;
    286362
    287363    // Read time tables
     
    289365    while((tableName=getToken(&namesPtr, " ", &status)) != NULL) {
    290366
    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
    292369        fullTableName = (char*)psAlloc(strlen(tableDir)+strlen(tableName)+1+1);
    293370
     
    298375        strcat(fullTableName, tableName);
    299376
     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
    300384        // Create and read table
    301385        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);
    304388        } else {
    305389            psError(PS_ERR_BAD_PARAMETER_VALUE, true, PS_ERRORTEXT_psTime_BAD_TABLE_COUNT, i+1, numTables);
     
    321405        psFree(fullTableName);
    322406        psFree(tableName);
     407        psFree(tableFormat);
    323408        psFree(table);
    324409        i++;
     
    333418    psFree(tablesFrom);
    334419    psFree(tablesTo);
     420    psFree(tablesIndex);
     421    psFree(tableFormats);
    335422
    336423    return true;
     
    351438    psTime *outTime = NULL;
    352439
    353 
    354440    // 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) {
    356443        psError(PS_ERR_BAD_PARAMETER_VALUE, true,
    357444                PS_ERRORTEXT_psTime_TYPE_UNKNOWN,
     
    360447    }
    361448
     449    // Allocate memory for structure
    362450    outTime = (psTime*)psAlloc(sizeof(psTime));
    363451
     452    // Initialize members
    364453    outTime->sec = 0;
    365454    outTime->nsec = 0;
     
    375464    psTime *time = NULL;
    376465
    377 
    378466    // Allocate psTime struct
    379467    time = psTimeAlloc(type);
    380468
     469    // Verify time structure allocated
     470    if(time == NULL) {
     471        return NULL;
     472    }
     473
     474    // Get the system time
    381475    if (gettimeofday(&now, (struct timezone *)0) == -1) {
    382476        psError(PS_ERR_OS_CALL_FAILED, true,
     
    391485    // Add most leapseconds to UTC time to get TAI time if necessary
    392486    if(type == PS_TIME_TAI) {
    393         time->sec += psTimeGetTAIDelta(time);
     487        time->sec += p_psTimeGetTAIDelta(time);
    394488    }
    395489
     
    397491}
    398492
     493static 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
     536static 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
     566static 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
     584static 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
     609static 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
    399648psTime* psTimeConvert(psTime *time, psTimeType type)
    400649{
    401     double delta = 0.0;
    402 
    403 
    404650    // Error checks
    405651    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");
    409657        return time;
    410658    }
    411659
    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
    418726    } else {
    419         psError(PS_ERR_BAD_PARAMETER_VALUE, true, PS_ERRORTEXT_psTime_TYPE_UNKNOWN, type);
     727        psError(PS_ERR_BAD_PARAMETER_VALUE, true, PS_ERRORTEXT_psTime_TYPE_UNKNOWN, time->type);
    420728    }
    421729
     
    423731}
    424732
    425 double psTimeToLMST(psTime *time, double longitude)
     733psF64 psTimeToLMST(psTime *time, psF64 longitude)
    426734{
    427735    psF64  jdTdtDays    =  0.0;
     
    433741    psF64  t            =  0.0;
    434742    psF64  tu           =  0.0;
    435     psF64  ut1UtcDbl    =  0.0;
    436743    psF64  const1       =  24110.5493771;
    437744    psF64  const2       =  8639877.3173760;
     
    440747    psF64  const5       = -0.0000062;
    441748    psF64  const6       =  0.0000013;
    442     psTime *ut1UtcDelta = NULL;
    443749    psTime *tdtTime     = NULL;
    444     psTime *taiTime     = NULL;
    445     psTime *utcTime     = NULL;
    446750    psTime *ut1Time     = NULL;
    447 
    448751
    449752    // Error checks
    450753    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 passes
    454     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) to UT1
    467     ut1UtcDbl = psTimeGetUT1Delta(taiTime);
    468     utcTime->type = PS_TIME_TAI; // Don't allow addition of leapseconds to ut1Time
    469     ut1Time = psTimeMath(utcTime, ut1UtcDbl);
    470     utcTime->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);
    472775
    473776    // Calculate UT1 as Julian Centuries since J2000.0
     
    476779    t = (jdUt1Days - 2451545.0)/36525.0;
    477780
    478     // Calculate Terrestial Dynamical Time (TDT)
    479     tdtTime = psTimeMath(taiTime, 32.184);
    480 
    481781    // Calculate TDT as Julian centuries since J2000.0
    482782    jdTdtDays = psTimeToJD(tdtTime);
     
    486786    fracDays = fmod(mjdUt1Days, 1.0);
    487787
    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;
    490792
    491793    // Place GMST between 0 and 2*pi
     
    496798
    497799    // Free temporary structs
    498     psFree(ut1UtcDelta);
    499800    psFree(ut1Time);
    500801    psFree(tdtTime);
    501     psFree(utcTime);
    502     psFree(taiTime);
    503802
    504803    return lmstRad;
    505804}
    506805
    507 double psTimeGetUT1Delta(const psTime *time)
    508 {
    509     psU32 nTables = 3;
    510     psF64 mjd = 0.0;
    511     psF64 result = 0.0;
    512     psF64 dut2ut1 = 0.0;
    513     psF64 t = 0.0;
    514     psVector *dut = NULL;
    515     psMetadataItem *tableMetadataItem = NULL;
    516     psLookupStatusType status = PS_LOOKUP_SUCCESS;
    517     char *metadataTableNames[3] = {"ser7Table", "eopcTable",  "finalsTable"};
    518 
     806psF64 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"};
    519818
    520819    // Error checks
    521820    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;
    527834    }
    528835
    529836    // Attempt to find value through table lookup and interpolation
    530837    mjd = psTimeToMJD(time);
    531     result = searchTables(mjd, 0, &status, metadataTableNames, nTables);
     838    result = searchTables(mjd,tableColumn,metadataTableNames,nTables,&status);
    532839
    533840    // Value could not be found through table lookup and interpolation
     
    535842
    536843        // 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
    539847        tableMetadataItem = psMetadataLookup(timeMetadata, "psLib.time.before.dut");
    540848        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;
    543852        }
    544853        result = tableMetadataItem->data.F64;
     
    552861             t = 2000.0 + (MJD - 51544.03)/365.2422
    553862        */
    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
    556867        tableMetadataItem = psMetadataLookup(timeMetadata, "psLib.time.predict.dut");
    557868        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;
    560872        }
    561873        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
    564877        t = 2000.0 + (mjd - 51544.03)/365.2422;
    565878        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);
     
    568881    } else if(status != PS_LOOKUP_SUCCESS) {
    569882        psError(PS_ERR_BAD_PARAMETER_VALUE, true, PS_ERRORTEXT_psTime_INTERPOLATION_FAILED);
    570         return 0.0;
     883        return NAN;
    571884    }
    572885
     
    574887}
    575888
    576 struct psSphere* psTimeGetPoleCoords(const psTime* time)
     889struct psSphere* p_psTimeGetPoleCoords(const psTime* time)
    577890{
    578891    psU32 nTables = 3;
     
    587900    psLookupStatusType yStatus = PS_LOOKUP_SUCCESS;
    588901    psMetadataItem *tableMetadataItem = NULL;
    589     char *metadataTableNames[3] = {"ser7Table", "eopcTable",  "finalsTable"};
     902    char *metadataTableNames[3] = {"dailyTable", "eopcTable",  "finalsTable"};
    590903    psVector *xp = NULL;
    591904    psVector *yp = NULL;
     
    593906    // Error checks
    594907    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);
    596909
    597910    if(time->type != PS_TIME_TAI)
     
    603916    // Attempt to find value through table lookup and interpolation
    604917    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);
    607922
    608923    // Value could not be found through table lookup and interpolation
     
    641956        psError(PS_ERR_BAD_PARAMETER_VALUE, true, PS_ERRORTEXT_psTime_TIME_POSTDATES_TABLES, mjd, "polar motion");
    642957
    643 
    644958        // Get predicted MJD
    645959        tableMetadataItem = psMetadataLookup(timeMetadata, "psLib.time.predict.mjd");
     
    6921006    }
    6931007
    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)
    6951009    output = psAlloc(sizeof(psSphere));
    6961010    output->r = x * M_PI / 648000.0;
     
    7001014}
    7011015
    702 double psTimeGetTAIDelta(const psTime *time)
    703 {
    704     psU64 i = 0;
     1016psF64 p_psTimeGetTAIDelta(const psTime *time)
     1017{
    7051018    psF64 jd = 0.0;
    7061019    psF64 mjd = 0.0;
     
    7111024    psLookupTable* table = NULL;
    7121025    psMetadataItem *tableMetadataItem = NULL;
    713     psVector *stats = NULL;
    7141026    psVector *results = NULL;
    7151027
    7161028    // Error checks
    7171029    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);
    7191031
    7201032    // Check time metadata
     
    7391051    mjd = psTimeToMJD(time);
    7401052
    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);
    7431060
    7441061    // 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
    7571078    psFree(results);
    7581079
     
    7601081}
    7611082
    762 
    7631083psS64 psTimeLeapSecondDelta(const psTime *time1, const psTime *time2)
    7641084{
    7651085    psS64 diff = 0;
    766 
    7671086
    7681087    // Error checks
    7691088    PS_ASSERT_PTR_NON_NULL(time1,0);
    7701089    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)psTimeGetTAIDelta((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));
    7741093
    7751094    return diff;
    7761095}
    7771096
    778 double psTimeToJD(const psTime *time)
    779 {
    780     double jd = 0.0;
     1097psBool 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
     1128psF64 psTimeToJD(const psTime *time)
     1129{
     1130    psF64 jd = NAN;
    7811131
    7821132    // Error checks
    7831133    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);
    7851135
    7861136    // Julian date conversion
    7871137    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;
    7891140    } 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;
    7911143    }
    7921144
     
    7941146}
    7951147
    796 double psTimeToMJD(const psTime *time)
    797 {
    798     double mjd = 0.0;
    799 
     1148psF64 psTimeToMJD(const psTime *time)
     1149{
     1150    psF64 mjd = NAN;
    8001151
    8011152    // Error checks
    8021153    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);
    8041155
    8051156    // Modified Julian date conversion
    8061157    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;
    8081160    } 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;
    8101163    }
    8111164
     
    8151168char* psTimeToISO(const psTime *time)
    8161169{
    817     psS32 ms = 0;
     1170    psS32 ds = 0;
    8181171    char *timeString = NULL;
    8191172    char *tempString = NULL;
     
    8211174    time_t sec;
    8221175
    823 
    8241176    // Error checks
    8251177    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
    8281184    tempString = psAlloc(MAX_TIME_STRING_LENGTH);
    8291185    timeString = psAlloc(MAX_TIME_STRING_LENGTH);
    8301186
    831     ms = time->nsec / 1000000;
     1187    // Convert nanoseconds to decaseconds
     1188    ds = time->nsec / 100000000;
    8321189    sec = time->sec;
     1190
     1191    // If leapsecond use previous day
     1192    if(time->leapsecond) {
     1193        sec--;
     1194    }
    8331195
    8341196    // tmTime variable is statically allocated, no need to free
     
    8401202    }
    8411203
    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) {
    8431213        psError(PS_ERR_OS_CALL_FAILED, true, PS_ERRORTEXT_psTime_APPEND_MSEC_FAILED);
    8441214    }
     
    8481218}
    8491219
    850 struct timeval psTimeToTimeval(const psTime *time)
    851 {
    852     struct timeval timevalTime;
    853 
    854     timevalTime.tv_sec = 0;
    855     timevalTime.tv_usec = 0;
     1220struct timeval* psTimeToTimeval(const psTime *time)
     1221{
     1222    struct timeval  *timevalTime = NULL;
    8561223
    8571224    // 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;
    8631235
    8641236    return timevalTime;
    8651237}
    8661238
    867 struct tm* psTimeToTM(const psTime *time)
     1239/*
     1240struct tm* p_psTimeToTM(const psTime *time)
    8681241{
    8691242    psS64 cent = 0;
     
    8761249    psS64 temp = 0;
    8771250    struct tm* tmTime = NULL;
    878 
    879 
     1251 
     1252 
    8801253    // Error checks
    8811254    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 
    8841257    seconds = time->sec%60;
    8851258    minute = time->sec/60%60;
    8861259    hour = time->sec/3600%24;
    8871260    day = (time->sec+62135596800)/86400;
    888 
     1261 
    8891262    // Add 306 days to make relative to Mar 1, 0; also adjust day to be within a range (1..2**28-1) where our
    8901263    // calculations will work with 32bit ints
     
    8981271        day -= temp * 146097;
    8991272    }
    900 
     1273 
    9011274    cent = (day*4-1)/146097;                        // Calc number of centuries day is after 29 Feb of yr 0
    9021275    day -= cent*146097/4;                           // 4 centuries = 146097 days
     
    9061279    day -= (month*367-1094)/12;                     // February of following year)
    9071280    year += cent*100+temp*400;                      // Get the real year, which is off by
    908 
     1281 
    9091282    // One if month is January or February
    9101283    if(month > 12)
     
    9131286        month -= 12;
    9141287    }
    915 
     1288 
    9161289    // Allocate output
    9171290    tmTime = (struct tm*)psAlloc(sizeof(struct tm));
    918 
     1291 
    9191292    tmTime->tm_year = year - 1900;
    9201293    tmTime->tm_mon = month - 1;
     
    9241297    tmTime->tm_sec = seconds;
    9251298    tmTime->tm_isdst = -1;
    926 
     1299 
    9271300    return tmTime;
    9281301}
    929 
    930 psTime* psTimeFromJD(double time)
    931 {
    932     double days = 0.0;
    933     double seconds = 0.0;
     1302*/
     1303
     1304psTime* psTimeFromJD(psF64 time)
     1305{
     1306    psF64 days = 0.0;
     1307    psF64 seconds = 0.0;
    9341308    psTime *outTime = NULL;
    935 
    9361309
    9371310    // Allocate psTime struct
     
    9491322
    9501323    // 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);
    9521325
    9531326    return outTime;
    9541327}
    9551328
    956 psTime* psTimeFromMJD(double time)
    957 {
    958     double days = 0.0;
    959     double seconds = 0.0;
     1329psTime* psTimeFromMJD(psF64 time)
     1330{
     1331    psF64 days = 0.0;
     1332    psF64 seconds = 0.0;
    9601333    psTime *outTime = NULL;
    961 
    9621334
    9631335    // Allocate psTime struct
     
    9671339    days = time - 40587.0;
    9681340    seconds = days * SEC_PER_DAY;
     1341
    9691342    if(seconds < 0.0) {
    9701343        outTime->nsec = (seconds - (psS64)seconds) * -1000000000.0;  // psTime earlier than epoch
     
    9751348
    9761349    // 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);
    9781351
    9791352    return outTime;
     
    9861359    psTime *outTime = NULL;
    9871360
     1361    // Check for NULL string
     1362    PS_ASSERT_PTR_NON_NULL(time,NULL);
     1363
    9881364    // 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,
    9901366               &tmTime.tm_hour, &tmTime.tm_min, &tmTime.tm_sec,&millisecond) < 7) {
    9911367        psError(PS_ERR_BAD_PARAMETER_VALUE, true, PS_ERRORTEXT_psTime_ISOTIME_MALFORMED, time);
     
    10061382
    10071383    // Convert tm time to psTime
    1008     outTime = psTimeFromTM(&tmTime);
     1384    outTime = p_psTimeFromTM(&tmTime);
    10091385    outTime->nsec = millisecond * 1000000;
     1386
     1387    return outTime;
     1388}
     1389
     1390psTime* 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
     1408psTime* 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);
    10101424
    10111425    return outTime;
     
    10281442
    10291443    // 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);
    10311445
    10321446    return outTime;
    10331447}
    10341448
    1035 psTime* psTimeFromTM(const struct tm* time)
     1449psTime* p_psTimeFromTM(const struct tm* time)
    10361450{
    10371451    psS64 year;
     
    10441458    psTime *outTime = NULL;
    10451459
    1046 
    10471460    // Error check
    10481461    PS_ASSERT_PTR_NON_NULL(time,NULL);
     
    10621475    if( month <= 2 )
    10631476    {
    1064         year -= (temp = (14 - month) / 12);
     1477        temp = (14 - month) / 12;
     1478        //        year -= (temp = (14 - month) / 12);
     1479        year -= temp;
    10651480        month += 12 * temp;
    10661481    } else if(month > 14)
    10671482    {
    1068         year += (temp = (month - 3) / 12);
     1483        temp = (month - 3) / 12;
     1484        //        year += (temp = (month - 3) / 12);
     1485        year += temp;
    10691486        month -= 12 * temp;
    10701487    }
     
    10811498    // days to adjust from Mar 1, year 0-relative to Jan 1, year 1-relative. Add hours, minutes, and seconds.
    10821499    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;
    10841502
    10851503    // C's TM does not define a microsecond field. Microseconds must be manipulated by calling function.
     
    10871505
    10881506    // 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);
    10901508
    10911509    return outTime;
     
    10981516    psTime *tempTime = NULL;
    10991517
    1100 
    11011518    // Error checks
    11021519    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);
    11041521
    11051522    // Convert time to TAI if necessary, but without changing input arguments
     
    11091526        tempTime->nsec = time->nsec;
    11101527        tempTime = psTimeConvert(tempTime, PS_TIME_TAI);
     1528        outTime = psTimeAlloc(PS_TIME_TAI);
    11111529    } else {
    11121530        tempTime = psMemIncrRefCounter((psTime*)time);
     1531        outTime = psTimeAlloc(time->type);
    11131532    }
    11141533
    11151534    // Create output time
    1116     outTime = psTimeAlloc(PS_TIME_TAI);
    11171535    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);
    11201539
    11211540    // 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);
    11231542
    11241543    // Convert result to same time type as input
     
    11401559    psTime *tempTime2 = NULL;
    11411560
    1142 
    11431561    // Error checks
    11441562    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);
    11461564    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    }
    11481572
    11491573    // Convert time to TAI if necessary, but without changing input arguments
Note: See TracChangeset for help on using the changeset viewer.