IPP Software Navigation Tools IPP Links Communication Pan-STARRS Links

Ignore:
Timestamp:
Mar 5, 2009, 11:13:29 AM (17 years ago)
Author:
beaumont
Message:

Finished ppStack visualization. Unified the way in which visualizations are invoked, plotting windows are closed, etc

Location:
branches/cnb_branches/cnb_branch_20090215
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • branches/cnb_branches/cnb_branch_20090215

  • branches/cnb_branches/cnb_branch_20090215/psLib/src/astro/psTime.c

    r20595 r23197  
    99 *
    1010 *  @author Ross Harman, MHPCC
     11 *  @author Paul Price, IfA
    1112 *
    12  *  @version $Revision: 1.117 $ $Name: not supported by cvs2svn $
    13  *  @date $Date: 2008-11-09 00:30:07 $
    14  *
    15  *  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
     13 *  Copyright 2004-2009 Institute for Astronomy, University of Hawaii
    1614 */
    1715
    1816#ifdef HAVE_CONFIG_H
    19 # include "config.h"
     17#include "config.h"
    2018#endif
    2119
     
    3937#include "psAssert.h"
    4038
    41 #define MAX_STRING_LENGTH 256
    42 
    43 /** Sidereal angular conversion from seconds to radians for GMST in seconds (i.e. pi/(180*240)) */
    44 #define S2R (7.272205216643039903848711535369e-5)
    45 
    46 /** Two times pi with double precision accuracy */
    47 #define TWOPI (2.0*M_PI)
    48 
    49 /** Conversion from radians to degrees */
    50 #define R2DEG = (180.0/M_PI)
    51 
    52 /** Maximum length of time string */
    53 #define MAX_TIME_STRING_LENGTH 256
    54 
    55 /** Seconds per minute */
    56 #define  SEC_PER_MINUTE 60.0
    57 
    58 /** Seconds per hour */
    59 #define  SEC_PER_HOUR (60.0*SEC_PER_MINUTE)
    60 
    61 /** Seconds per day */
    62 #define  SEC_PER_DAY (24.0*SEC_PER_HOUR)
    63 
    64 /** Seconds per year */
    65 #define  SEC_PER_YEAR (365.0*SEC_PER_DAY)
    66 
    67 /** Microseconds per day */
    68 #define NSEC_PER_DAY 86400000000000.0
    69 
    70 // Time config file path
    71 static char *timeConfig = NULL;
    72 
    73 /** Time metadata read from config file */
    74 static psMetadata *timeMetadata = NULL;
    75 
    76 // Offset to convert terrestrial time(TT) to international atomic time(TAI)
    77 #define  TAI_TT_OFFSET_SECONDS        32
    78 #define  TAI_TT_OFFSET_NANOSECONDS    184000000
    79 
    80 // Offset from converting to MJD
    81 #define  MJD_EPOCH_OFFSET             40587.0
    82 
    83 // Offset for converting to JD
    84 #define  JD_EPOCH_OFFSET              2440587.5
    85 
    86 // Offset of year 0000 from epoch
    87 #define YEAR_0000_SEC                 -62125920000
    88 
    89 // Offset of year 9999 from epoch
    90 #define YEAR_9999_SEC                 253202544000
     39
     40#define S2R (M_PI / (180.0 * 240.0))    /// Sidereal conversion: GMST in seconds to radians
     41#define R2DEG = (180.0/M_PI)            /// Conversion from radians to degrees
     42#define MAX_STRING_LENGTH 256           /// Maximum length of string
     43#define MAX_TIME_STRING_LENGTH 30       /// Maximum length of time string: 1234-67-90T23:56:89.123456789
     44#define SEC_PER_MINUTE 60.0             /// Seconds per minute
     45#define SEC_PER_HOUR (60.0*SEC_PER_MINUTE) /// Seconds per hour
     46#define SEC_PER_DAY (24.0*SEC_PER_HOUR) /// Seconds per day
     47#define SEC_PER_YEAR (365.0*SEC_PER_DAY) /// Seconds per year
     48#define NSEC_PER_DAY (SEC_PER_DAY * 1000000000.0) /// Nanoseconds per day
     49
     50#define MJD_EPOCH_OFFSET 40587.0        // Offset from converting to MJD
     51#define JD_EPOCH_OFFSET 2440587.5       // Offset for converting to JD
     52#define YEAR_0000_SEC -62125920000      // Offset of year 0000 from epoch
     53#define YEAR_9999_SEC 253202544000      // Offset of year 9999 from epoch
     54
     55// Offset to convert terrestrial time (TT) to international atomic time (TAI)
     56#define TAI_TT_OFFSET_SECONDS        32
     57#define TAI_TT_OFFSET_NANOSECONDS    184000000
     58
     59
     60// Static global variables
     61static char *timeConfig = NULL;         // Time config file path
     62static psMetadata *timeMetadata = NULL; // Time metadata read from config file
     63static int isoDecimals = 6;             // Number of decimals to use in a string by psTimeToISO
     64
    9165
    9266/** Static function prototypes */
    9367static char *cleanString(char *inString, int sLen);
    9468static char* getToken(char **inString, char *delimiter, psParseErrorType *status);
    95 static psTime* convertTimeTAIUTC(psTime* time);
    96 static psTime* convertTimeUTCTAI(psTime* time);
    97 static psTime* convertTimeTAITT(psTime* time);
    98 static psTime* convertTimeTTTAI(psTime* time);
    99 static psTime* convertTimeUTCUT1(psTime* time);
    100 
    101 static bool p_psTimeInit(const char *fileName);
     69static bool convertTimeTAIUTC(psTime* time);
     70static bool convertTimeUTCTAI(psTime* time);
     71static bool convertTimeTAITT(psTime* time);
     72static bool convertTimeTTTAI(psTime* time);
     73static bool convertTimeUTCUT1(psTime* time);
     74
     75static bool timeInit(const char *fileName);
    10276
    10377/** Removes leading and trailing whitespace and # characters from a string. The cleaned string is a new null
    10478 *  terminated copy of the original input string. */
    105 static char *cleanString(char *inString,
    106                          int sLen)
    107 {
    108     char *ptrB = NULL;
    109     char *ptrE = NULL;
    110     char *cleaned = NULL;
    111 
    112     ptrB = inString;
     79static char *cleanString(char *inString,// Input string
     80                         int sLen       // Length of string
     81                         )
     82{
     83    char *ptrB = inString;              // Pointer to start
    11384
    11485    // Skip over leading # or whitespace
    115     while (isspace(*ptrB) || *ptrB=='#') {
     86    while (isspace(*ptrB) || *ptrB == '#') {
    11687        ptrB++;
    11788    }
    11889
    11990    // Skip over trailing whitespace, null terminators, and # characters
    120     ptrE = inString + sLen - 1;
    121     while(isspace(*ptrE) || *ptrE=='\0' || *ptrE=='#') {
     91    char *ptrE = inString + sLen - 1;   // Pointer to end
     92    while (isspace(*ptrE) || *ptrE == '\0' || *ptrE == '#') {
    12293        ptrE--;
    12394    }
     
    12798
    12899    // Adds '\0' to end of string and +1 to sLen
    129     cleaned = psStringNCopy(ptrB, sLen);
    130 
    131     return cleaned;
     100    return psStringNCopy(ptrB, sLen);
    132101}
    133102
    134103/** Returns cleaned token based on delimiter, but not including delimiter. Also changes the pointer location
    135104 * the beginning of the string. Tokens are newly allocated null terminated strings. */
    136 static char* getToken(char **inString,
    137                       char *delimiter,
    138                       psParseErrorType *status)
    139 {
    140     char *cleanToken = NULL;
    141     int sLen = 0;
    142 
     105static char* getToken(char **inString,  // Input string
     106                      char *delimiter,  // Delimiter
     107                      psParseErrorType *status // Parsing status, returned
     108                      )
     109{
    143110    // Skip over leading whitespace
    144     while(isspace(**inString)) {
     111    while (isspace(**inString)) {
    145112        (*inString)++;
    146113    }
    147114
    148     // Length of token, not including delimiter
    149     sLen = strcspn(*inString, delimiter);
    150 
    151     if(sLen) {
    152 
     115    int sLen = strcspn(*inString, delimiter); // Length of token, not including delimiter
     116    char *cleanToken = NULL;            // Token, cleaned of delimiters
     117    if (sLen) {
    153118        // Create new, cleaned, and null terminated token
    154119        cleanToken = cleanString(*inString, sLen);
    155120
    156121        // Move to end of token
    157         //        (*inString) += (sLen+1);
    158122        (*inString) += sLen;
    159123        if (**inString != '\0' ) {
    160124            (*inString)++;
    161125        }
    162 
    163     } else if(**inString!='\0' && sLen==0) {
     126    } else if (**inString != '\0' && sLen == 0) {
    164127        *status = PS_PARSE_ERROR_GENERAL;
    165128    }
     
    210173
    211174    // Check if psTime tables are already loaded
    212     if(!p_psTimeInit(p_psTimeConfigFilename(NULL))) {
     175    if (!timeInit(p_psTimeConfigFilename(NULL))) {
    213176        *status = PS_LOOKUP_ERROR;
    214177        return NAN;
     
    225188
    226189        // Check if table not a metadata item
    227         if(tableMetadataItem == NULL) {
     190        if (tableMetadataItem == NULL) {
    228191            psError(PS_ERR_BAD_PARAMETER_VALUE, true, _("Failed find '%s' in time metadata."),
    229192                    tableName);
     
    239202
    240203        // Check if index within to/from range
    241         if(index >= table->validFrom ) {
    242             if(index <= table->validTo) {
     204        if (index >= table->validFrom ) {
     205            if (index <= table->validTo) {
    243206                // Attempt to interpolate table
    244207                result = psLookupTableInterpolate(table, index, column);
    245208                *status = PS_LOOKUP_SUCCESS;
    246                 if(!isnan(result)) {
     209                if (!isnan(result)) {
    247210                    break;
    248211                }
     
    258221}
    259222
    260 bool p_psTimeInit(const char *fileName)
     223static bool timeInit(const char *fileName)
    261224{
    262225    psS32 numLines = 0;
     
    270233    char *tableName = NULL;
    271234    char *tableFormat = NULL;
    272     char *fullTableName = NULL;
    273     psS32 i = 0;
    274     psS32 j = 0;
    275235    psS32 numTables = 0;
    276236    psU32 nFail = 0;
     
    283243    char metadataTableNames[4][MAX_STRING_LENGTH] = {"daily", "eopc",  "finals", "tai"};
    284244
    285     // Check if the p_psTimeInit has already been ran
    286     if (timeMetadata != NULL) {
     245    // Check if the timeInit has already been run
     246    if (timeMetadata) {
    287247        return true;
    288248    }
    289249
     250    // All memory allocated below is "persistent"
    290251    // XXX this is not thread safe as the persistence setting is global
    291     const bool initialPersistence =
    292         p_psMemAllocatePersistent(true); // All memory allocated below is "persistent"
     252    const bool initialPersistence = p_psMemAllocatePersistent(true); // Initial setting of persistence
    293253
    294254    // Read config file
    295255    timeMetadata = psMetadataConfigRead(timeMetadata, &nFail, fileName, true);
    296     if(timeMetadata == NULL) {
     256    if (!timeMetadata) {
     257        psError(PS_ERR_IO, false, "Unable to read time configuration file %s", fileName);
    297258        return false;
    298     } else if(nFail != 0) {
     259    } else if (nFail != 0) {
     260        psError(PS_ERR_IO, false, "Failed to parse %d lines reading time configuration file %s",
     261                nFail, fileName);
    299262        return false;
    300263    }
     
    302265    // Get number of tables
    303266    metadataItem = psMetadataLookup(timeMetadata, "psLib.time.tables.n");
    304     if(metadataItem == NULL) {
     267    if (metadataItem == NULL) {
    305268        p_psMemAllocatePersistent(initialPersistence);
    306269        psError(PS_ERR_BAD_PARAMETER_VALUE, true, _("Failed find '%s' in time metadata."),
     
    312275    // Get lower range of tables
    313276    metadataItem = psMetadataLookup(timeMetadata, "psLib.time.tables.from");
    314     if(metadataItem == NULL) {
     277    if (metadataItem == NULL) {
    315278        p_psMemAllocatePersistent(initialPersistence);
    316279        psError(PS_ERR_BAD_PARAMETER_VALUE, true, _("Failed find '%s' in time metadata."),
     
    319282    }
    320283    tablesFrom = psVectorCopy(tablesFrom, metadataItem->data.V, PS_TYPE_F64);
    321     if(tablesFrom->n != numTables) {
     284    if (tablesFrom->n != numTables) {
    322285        p_psMemAllocatePersistent(initialPersistence);
    323286        psError(PS_ERR_BAD_PARAMETER_VALUE, true, _("Incorrect vector size. Size: %ld, Expected %d."), tablesFrom->n, numTables);
     
    328291    // Get upper range of tables
    329292    metadataItem = psMetadataLookup(timeMetadata, "psLib.time.tables.to");
    330     if(metadataItem == NULL) {
     293    if (metadataItem == NULL) {
    331294        p_psMemAllocatePersistent(initialPersistence);
    332295        psError(PS_ERR_BAD_PARAMETER_VALUE, true, _("Failed find '%s' in time metadata."),
     
    336299    }
    337300    tablesTo = psVectorCopy(tablesTo, metadataItem->data.V, PS_TYPE_F64);
    338     if(tablesTo->n != numTables) {
     301    if (tablesTo->n != numTables) {
    339302        p_psMemAllocatePersistent(initialPersistence);
    340303        psError(PS_ERR_BAD_PARAMETER_VALUE, true, _("Incorrect vector size. Size: %ld, Expected %d."), tablesTo->n, numTables);
     
    346309    // Get index columns for the tables
    347310    metadataItem = psMetadataLookup(timeMetadata, "psLib.time.tables.index");
    348     if(metadataItem == NULL) {
     311    if (metadataItem == NULL) {
    349312        p_psMemAllocatePersistent(initialPersistence);
    350313        psError(PS_ERR_BAD_PARAMETER_VALUE,true,_("Failed find '%s' in time metadata."),
     
    355318    }
    356319    tablesIndex = psVectorCopy(tablesIndex, metadataItem->data.V, PS_TYPE_S32);
    357     if(tablesIndex->n != numTables) {
     320    if (tablesIndex->n != numTables) {
    358321        p_psMemAllocatePersistent(initialPersistence);
    359322        psError(PS_ERR_BAD_PARAMETER_VALUE,true,_("Incorrect vector size. Size: %ld, Expected %d."),tablesIndex->n,numTables);
     
    366329    // Get path to time data files
    367330    metadataItem = psMetadataLookup(timeMetadata, "psLib.time.tables.dir");
    368     if(metadataItem == NULL) {
     331    if (metadataItem == NULL) {
    369332        p_psMemAllocatePersistent(initialPersistence);
    370333        psError(PS_ERR_BAD_PARAMETER_VALUE, true, _("Failed find '%s' in time metadata."),
     
    379342    // Table file names
    380343    metadataItem = psMetadataLookup(timeMetadata, "psLib.time.tables.files");
    381     if(metadataItem == NULL) {
     344    if (metadataItem == NULL) {
    382345        p_psMemAllocatePersistent(initialPersistence);
    383346        psError(PS_ERR_BAD_PARAMETER_VALUE, true, _("Failed find '%s' in time metadata."),
     
    394357    // Get table format strings
    395358    metadataItem = psMetadataLookup(timeMetadata, "psLib.time.tables.format");
    396     if(metadataItem == NULL) {
     359    if (metadataItem == NULL) {
    397360        p_psMemAllocatePersistent(initialPersistence);
    398361        psError(PS_ERR_BAD_PARAMETER_VALUE,true, _("Failed find '%s' in time metadata."),
     
    411374    bool no_problem = true;  // True if we've detected no errors
    412375    namesPtr = tableNames;
    413     while((tableName=getToken(&namesPtr, " ", &status)) != NULL) {
    414 
    415         // Form path with table name, adding one to length for last '/' that may not occur
    416         // in string in cong file
    417         fullTableName = (char*)psAlloc(strlen(tableDir)+strlen(tableName)+1+1);
    418 
    419         // Old strings may come back from psAlloc(), so set initial position to EOL
    420         fullTableName[0]='\0';
    421         strcat(fullTableName, tableDir);
    422         strcat(fullTableName, "/");
    423         strcat(fullTableName, tableName);
     376    int i;                              // Iterator
     377    for (i = 0; (tableName = getToken(&namesPtr, " ", &status)) != NULL; i++) {
     378        psString fullTableName = NULL;  // Full path for table
     379        psStringAppend(&fullTableName, "%s/%s", tableDir, tableName);
    424380
    425381        // Get table format
    426         tableFormat = getToken(&formatPtr,",",&status);
    427         if(tableFormat == NULL) {
    428             psError(PS_ERR_BAD_PARAMETER_VALUE,no_problem,_("Failed find '%s' in time metadata."),
     382        tableFormat = getToken(&formatPtr, ",", &status);
     383        if (!tableFormat) {
     384            psError(PS_ERR_BAD_PARAMETER_VALUE, no_problem, _("Failed find '%s' in time metadata."),
    429385                    "psLib.time.tables.format");
    430386            no_problem = false;
     
    432388
    433389        // Create and read table
    434         if(i < numTables) {
     390        if (i < numTables) {
    435391            table = psLookupTableAlloc(fullTableName, (const char*)tableFormat, tablesIndex->data.S32[i]);
    436392            numLines = psLookupTableRead(table);
    437393        } else {
    438394            psError(PS_ERR_BAD_PARAMETER_VALUE, no_problem,
    439                     _("Incorrect number of table files entered. Found: %d. Expected: %d."), i+1, numTables);
     395                    _("Incorrect number of table files entered. Found: %d. Expected: %d."), i + 1, numTables);
    440396            no_problem = false;
    441397        }
     
    443399        // Place tables into metadata slightly altered names as keys to create consistent naming conventions
    444400        foundTable = false;
    445         for(j=0; j<numTables; j++) {
     401        for (int j = 0; j < numTables; j++) {
    446402            metadataNamesPtr = strstr(tableName, metadataTableNames[j]);
    447             if(metadataNamesPtr != NULL) {
     403            if (metadataNamesPtr != NULL) {
    448404                psMetadataAdd(timeMetadata, PS_LIST_TAIL, strcat(metadataTableNames[j], "Table"),
    449405                              PS_DATA_LOOKUPTABLE, NULL, table);
    450406                foundTable = true;
    451             } else if(foundTable==false && j==numTables-1) {
     407            } else if (foundTable == false && j == numTables - 1) {
    452408                psError(PS_ERR_BAD_PARAMETER_VALUE, no_problem,
    453409                        _("Incorrect number of table files entered. Found: %d. Expected: %d."), j, numTables);
     
    460416        psFree(tableFormat);
    461417        psFree(table);
    462         i++;
    463418    }
    464419
    465420    p_psMemAllocatePersistent(initialPersistence);
    466421
    467     if(numTables != i) {
    468         psError(PS_ERR_BAD_PARAMETER_VALUE, no_problem, _("Incorrect number of table files entered. Found: %d. Expected: %d."), i, numTables);
     422    if (numTables != i) {
     423        psError(PS_ERR_BAD_PARAMETER_VALUE, no_problem,
     424                _("Incorrect number of table files entered. Found: %d. Expected: %d."),
     425                i, numTables);
    469426    }
    470427
     
    481438bool p_psTimeFinalize(void)
    482439{
    483     if(timeMetadata != NULL) {
     440    if (timeMetadata != NULL) {
    484441        psFree(timeMetadata);
    485442        timeMetadata = NULL;
     
    496453psTime* psTimeAlloc(psTimeType type)
    497454{
    498     psTime *outTime = NULL;
    499 
    500455    // Error checks
    501     if(type!=PS_TIME_TAI && type!=PS_TIME_UTC && type!=PS_TIME_UT1 &&
    502             type!=PS_TIME_TT) {
    503         psError(PS_ERR_BAD_PARAMETER_VALUE, true,
    504                 _("Specified type, %d, is not supported."),
    505                 type);
    506         return NULL;
     456    switch (type) {
     457      case PS_TIME_TAI:
     458      case PS_TIME_UTC:
     459      case PS_TIME_UT1:
     460      case PS_TIME_TT:
     461        // No action
     462        break;
     463      default:
     464        // Since we can never return NULL from an allocator
     465        psAbort("Specified type, %d, is not supported.", type);
    507466    }
    508467
    509468    // Allocate memory for structure
    510     outTime = (psTime*)psAlloc(sizeof(psTime));
     469    psTime *outTime = psAlloc(sizeof(psTime));
    511470    psMemSetDeallocator(outTime, (psFreeFunc)timeFree);
     471
    512472    // Initialize members
    513473    outTime->sec = 0;
     
    522482bool psMemCheckTime(psPtr ptr)
    523483{
    524     return ( psMemGetDeallocator(ptr) == (psFreeFunc)timeFree );
     484    return (psMemGetDeallocator(ptr) == (psFreeFunc)timeFree);
    525485}
    526486
     
    528488psTime* psTimeGetNow(psTimeType type)
    529489{
    530     struct timeval now;
    531     psTime *time = NULL;
    532 
    533     // Allocate psTime struct
    534     time = psTimeAlloc(type);
    535 
    536     // Verify time structure allocated
    537     if(time == NULL) {
    538         return NULL;
    539     }
    540 
    541490    // Get the system time
    542     //    if (gettimeofday(&now, (struct timezone *)0) == -1) {
     491    struct timeval now;                 // Current time
    543492    if (gettimeofday(&now, 0) == -1) {
    544493        psError(PS_ERR_OS_CALL_FAILED, true,
     
    547496    }
    548497
     498    // Allocate psTime struct
     499    psTime *time = psTimeAlloc(type);   // Container for current time
     500
    549501    // Convert timeval time to psTime
    550502    time->sec = now.tv_sec;
    551     time->nsec = now.tv_usec*1000;
     503    time->nsec = now.tv_usec * 1000;
    552504
    553505    // Add most leapseconds to UTC time to get TAI time if necessary
    554     if(type == PS_TIME_TAI) {
     506    if (type == PS_TIME_TAI) {
    555507        time->sec += p_psTimeGetTAIDelta(time);
    556508    }
     
    559511}
    560512
    561 static psTime* convertTimeTAIUTC(psTime* time)
     513static bool convertTimeTAIUTC(psTime* time)
    562514{
    563515    psF64  deltaTAI     = 0.0;
     
    575527
    576528    // Check for underflow in nsec
    577     if(deltaNsec > time->nsec) {
     529    if (deltaNsec > time->nsec) {
    578530        // Borrow second
    579531        time->nsec += 1e9;
     
    585537
    586538    // Check for overflow in nsec
    587     if(time->nsec >= 1e9) {
     539    if (time->nsec >= 1e9) {
    588540        time->nsec -= 1e9;
    589541        time->sec++;
     
    595547    // Check if leapsecond present in delta
    596548    deltaUTC = p_psTimeGetTAIDelta(time);
    597     if(fabs(deltaTAI-deltaUTC) >= 1.0) {
     549    if (fabs(deltaTAI-deltaUTC) >= 1.0) {
    598550        time->sec++;
    599551    }
    600552
    601     return time;
    602 }
    603 
    604 static psTime* convertTimeUTCTAI(psTime* time)
     553    return true;
     554}
     555
     556static bool convertTimeUTCTAI(psTime* time)
    605557{
    606558    psF64  delta     = 0.0;
     
    621573
    622574    // Check for overflow in nsec
    623     if(time->nsec >= 1e9) {
     575    if (time->nsec >= 1e9) {
    624576        time->nsec -= 1e9;
    625577        time->sec++;
     
    629581    time->type = PS_TIME_TAI;
    630582
    631     //XXX: Set leapseconds to TRUE
    632     //    time->leapsecond = true;
    633     return time;
    634 }
    635 
    636 static psTime* convertTimeTAITT(psTime* time)
     583    return true;
     584}
     585
     586static bool convertTimeTAITT(psTime* time)
    637587{
    638588    // Add TT offset
     
    641591
    642592    // Check for overflow in nsec
    643     if(time->nsec >= 1e9) {
     593    if (time->nsec >= 1e9) {
    644594        time->nsec -= 1e9;
    645595        time->sec++;
     
    649599    time->type = PS_TIME_TT;
    650600
    651     return time;
    652 }
    653 
    654 static psTime* convertTimeTTTAI(psTime* time)
     601    return true;
     602}
     603
     604static bool convertTimeTTTAI(psTime* time)
    655605{
    656606    // Subtract TT offset
     
    658608
    659609    // Check for nsec underflow
    660     if(TAI_TT_OFFSET_NANOSECONDS > time->nsec) {
     610    if (TAI_TT_OFFSET_NANOSECONDS > time->nsec) {
    661611        // Borrow second
    662612        time->sec--;
     
    666616
    667617    // Check for overflow in nsec
    668     if(time->nsec >= 1e9) {
     618    if (time->nsec >= 1e9) {
    669619        time->nsec -= 1e9;
    670620        time->sec++;
     
    674624    time->type = PS_TIME_TAI;
    675625
    676     return time;
    677 }
    678 
    679 static psTime* convertTimeUTCUT1(psTime* time)
     626    return true;
     627}
     628
     629static bool convertTimeUTCUT1(psTime* time)
    680630{
    681631    psS64   ut1utc  = 0;
     
    685635
    686636    // Since UTC is within 0.9 sec of UT1 then nsec member is the member affected
    687     if((ut1utc < 0) && (abs(ut1utc) > time->nsec)) {
     637    if ((ut1utc < 0) && (abs(ut1utc) > time->nsec)) {
    688638        // Borrow from sec
    689639        time->sec--;
    690         if(time->leapsecond) {
     640        if (time->leapsecond) {
    691641            time->leapsecond = false;
    692642        } else {
     
    699649
    700650    // Check for overflow in nsec
    701     if(time->nsec >= 1e9) {
     651    if (time->nsec >= 1e9) {
    702652        time->nsec -= 1e9;
    703653        time->sec++;
    704         if(time->leapsecond) {
     654        if (time->leapsecond) {
    705655            time->leapsecond = false;
    706656            time->sec--;
     
    713663    time->type = PS_TIME_UT1;
    714664
    715     return time;
    716 }
    717 
    718 psTime* psTimeConvert(psTime *time,
    719                       psTimeType type)
     665    return true;
     666}
     667
     668bool psTimeConvert(psTime *time, psTimeType type)
    720669{
    721670    // Error checks
    722     PS_ASSERT_PTR_NON_NULL(time,NULL);
    723     PS_ASSERT_INT_WITHIN_RANGE(time->nsec,0,(psU32)((1e9)-1), NULL);
    724 
    725     // If the input type is UT1 then return time and generate error message
    726     if(time->type == PS_TIME_UT1) {
    727         psError(PS_ERR_BAD_PARAMETER_VALUE,true,"Cannot convert from UT1 time type");
    728         return NULL;
    729     }
    730 
    731     // If the time to convert to is the same as psTime the return time
     671    PS_ASSERT_PTR_NON_NULL(time, false);
     672    PS_ASSERT_INT_WITHIN_RANGE(time->nsec, 0, (psU32)((1e9)-1), false);
     673
     674    if (time->type == PS_TIME_UT1) {
     675        psError(PS_ERR_BAD_PARAMETER_VALUE, true, "Cannot convert from UT1 time type");
     676        return false;
     677    }
    732678    if (time->type == type) {
    733         return time;
    734     }
    735 
    736     // Convert from TAI to UTC, TT, UT1
    737     if(time->type == PS_TIME_TAI) {
    738         // Convert from TAI to UTC
    739         if(type == PS_TIME_UTC) {
    740             time = convertTimeTAIUTC(time);
    741             // Convert from TAI to TT
    742         } else if(type == PS_TIME_TT) {
    743             time = convertTimeTAITT(time);
    744             // Convert from TAI to UT1
    745         } else if(type == PS_TIME_UT1) {
    746             // Convert to UTC first
    747             time = convertTimeTAIUTC(time);
    748             // Convert UTC to UT1
    749             time = convertTimeUTCUT1(time);
    750             // Convert from TAI to unknown time type
    751         } else {
     679        // No action required
     680        return true;
     681    }
     682
     683    switch (time->type) {
     684      case PS_TIME_TAI:
     685        switch (type) {
     686          case PS_TIME_UTC:
     687            return convertTimeTAIUTC(time);
     688          case PS_TIME_TT:
     689            return convertTimeTAITT(time);
     690          case PS_TIME_UT1:
     691            convertTimeTAIUTC(time);
     692            return convertTimeUTCUT1(time);
     693          default:
     694            psError(PS_ERR_BAD_PARAMETER_VALUE, true, _("Specified type, %d, is not supported."), type);
     695            return false;
     696        }
     697        break;
     698      case PS_TIME_TT:
     699        switch (type) {
     700          case PS_TIME_UTC:
     701            convertTimeTTTAI(time);
     702            return convertTimeTAIUTC(time);
     703          case PS_TIME_TAI:
     704            return convertTimeTTTAI(time);
     705          case PS_TIME_UT1:
     706            convertTimeTTTAI(time);
     707            convertTimeTAIUTC(time);
     708            return convertTimeUTCUT1(time);
     709          default:
    752710            psError(PS_ERR_BAD_PARAMETER_VALUE, true, _("Specified type, %d, is not supported."), type);
    753711            return NULL;
    754712        }
    755         // Convert from TT to TAI, UTC, UT1
    756     } else if(time->type == PS_TIME_TT) {
    757         // Convert from TT to UTC
    758         if(type == PS_TIME_UTC) {
    759             // Convert to TAI time first
    760             time = convertTimeTTTAI(time);
    761             // Convert from TAI to UTC
    762             time = convertTimeTAIUTC(time);
    763             // Convert from TT to TAI
    764         } else if(type == PS_TIME_TAI) {
    765             time = convertTimeTTTAI(time);
    766             // Convert from TT to UT1
    767         } else if(type == PS_TIME_UT1) {
    768             // Convert to UTC first
    769             // Convert to TAI time first
    770             time = convertTimeTTTAI(time);
    771             // Convert from TAI to UTC
    772             time = convertTimeTAIUTC(time);
    773             // Convert from UTC to UT1
    774             time = convertTimeUTCUT1(time);
    775             // Convert from TT to unknown time type
    776         } else {
     713        break;
     714      case PS_TIME_UTC:
     715        switch (type) {
     716          case PS_TIME_TAI:
     717            return convertTimeUTCTAI(time);
     718          case PS_TIME_TT:
     719            convertTimeUTCTAI(time);
     720            return convertTimeTAITT(time);
     721          case PS_TIME_UT1:
     722            return convertTimeUTCUT1(time);
     723          default:
    777724            psError(PS_ERR_BAD_PARAMETER_VALUE, true, _("Specified type, %d, is not supported."), type);
    778725            return NULL;
    779726        }
    780         // Convert from UTC to TAI, TT, UT1
    781     } else if(time->type == PS_TIME_UTC) {
    782         // Convert UTC to TAI
    783         if(type == PS_TIME_TAI) {
    784             time = convertTimeUTCTAI(time);
    785             // Convert UTC to TT
    786         } else if(type == PS_TIME_TT) {
    787             // Convert to TAI time first
    788             time = convertTimeUTCTAI(time);
    789             // Convert TAI to TT
    790             time = convertTimeTAITT(time);
    791             // Convert UTC to UT1
    792         } else if(type == PS_TIME_UT1) {
    793             time = convertTimeUTCUT1(time);
    794             // Convert UTC to unknown time type
    795         } else {
    796             psError(PS_ERR_BAD_PARAMETER_VALUE, true, _("Specified type, %d, is not supported."), type);
    797             return NULL;
    798         }
    799         // Convert unknown time type
    800     } else {
     727        break;
     728      default:
    801729        psError(PS_ERR_BAD_PARAMETER_VALUE, true, _("Specified type, %d, is not supported."), time->type);
    802730        return NULL;
    803731    }
    804732
    805     return time;
     733    psAbort("Should never reach here.");
     734    return false;
    806735}
    807736
     
    831760
    832761    // Verify input time is not in UT1 seconds
    833     if(time->type == PS_TIME_UT1) {
     762    if (time->type == PS_TIME_UT1) {
    834763        psError(PS_ERR_BAD_PARAMETER_VALUE,true,_("Specified type, %d, is incorrect."),time->type);
    835764        return NAN;
     
    841770    tdtTime->nsec = time->nsec;
    842771    tdtTime->leapsecond = time->leapsecond;
    843     tdtTime = psTimeConvert(tdtTime,PS_TIME_TT);
     772    psTimeConvert(tdtTime,PS_TIME_TT);
    844773
    845774    // Determine time reference to UT1
     
    848777    ut1Time->nsec = time->nsec;
    849778    ut1Time->leapsecond = time->leapsecond;
    850     ut1Time = psTimeConvert(ut1Time,PS_TIME_UT1);
     779    psTimeConvert(ut1Time,PS_TIME_UT1);
    851780
    852781    // Calculate UT1 as Julian Centuries since J2000.0
     
    864793    // Calculate Greenwich Mean Sidereal Time (GMST) in radians.
    865794    // Equation set up to minimize multiplications.
    866     gmstRad = fracDays*TWOPI
    867               + (const1+const2*tu+t*(const3+t*(const4+t*(const5+const6*t))))*S2R;
     795    gmstRad = fracDays * 2 * M_PI +
     796        (const1 + const2 * tu + t * (const3 + t * (const4 + t * (const5 + const6 * t)))) * S2R;
    868797
    869798    // Place GMST between 0 and 2*pi
    870     gmstRad = fmod(gmstRad, TWOPI);
     799    gmstRad = fmod(gmstRad, 2 * M_PI);
    871800
    872801    // Calculate Local Mean Sidereal Time (LMST) in radians
     
    899828
    900829    // Check for invalid bulletin specified
    901     if((bulletin != PS_IERS_A) && (bulletin != PS_IERS_B)) {
     830    if ((bulletin != PS_IERS_A) && (bulletin != PS_IERS_B)) {
    902831        psError(PS_ERR_BAD_PARAMETER_VALUE,true,"Invalid bulletin specified %d",bulletin);
    903832        return NAN;
     
    905834
    906835    // Check if psTime tables are already loaded
    907     if(!p_psTimeInit(p_psTimeConfigFilename(NULL))) {
     836    if (!timeInit(p_psTimeConfigFilename(NULL))) {
    908837        psError(PS_ERR_UNKNOWN, true, "failed to init time tables.");
    909838        return NAN;
     
    911840
    912841    // Set lookup table column based on Bullentin
    913     if(bulletin == PS_IERS_A) {
     842    if (bulletin == PS_IERS_A) {
    914843        tableColumn = 3;
    915844    } else {
     
    922851
    923852    // Value could not be found through table lookup and interpolation
    924     if(status == PS_LOOKUP_PAST_TOP) {
     853    if (status == PS_LOOKUP_PAST_TOP) {
    925854
    926855        // Date too early for tables. Get default time delta value from metadata, and issue warning.
     
    929858        // Lookup value from time metadata loaded from pslib.config
    930859        tableMetadataItem = psMetadataLookup(timeMetadata, "psLib.time.before.dut");
    931         if(tableMetadataItem == NULL) {
     860        if (tableMetadataItem == NULL) {
    932861            psError(PS_ERR_BAD_PARAMETER_VALUE, true, _("Failed find '%s' in time metadata."),
    933862                    "psLib.time.before.dut");
     
    936865        result = tableMetadataItem->data.F64;
    937866
    938     } else if(status == PS_LOOKUP_PAST_BOTTOM) {
     867    } else if (status == PS_LOOKUP_PAST_BOTTOM) {
    939868        /* Date too late for tables. Issue warning and use following formulae for predicting
    940869           ahead of the most recent available table entry.
     
    949878        // Lookup values to calculate prediction
    950879        tableMetadataItem = psMetadataLookup(timeMetadata, "psLib.time.predict.dut");
    951         if(tableMetadataItem == NULL) {
     880        if (tableMetadataItem == NULL) {
    952881            psError(PS_ERR_BAD_PARAMETER_VALUE, true, _("Failed find '%s' in time metadata."),
    953882                    "psLib.time.predict.dut");
     
    958887
    959888        // Calculate predication of future UT1-UTC
    960         t = 2000.0 + (mjd - 51544.03)/365.2422;
    961         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);
    962         result = dut->data.F64[0] + dut->data.F64[1]*(mjd - dut->data.F64[2]) - dut2ut1;
    963 
    964     } else if(status != PS_LOOKUP_SUCCESS) {
     889        t = 2000.0 + (mjd - 51544.03) / 365.2422;
     890        dut2ut1 = 0.022 * sin(2 * M_PI * t) - 0.012 * cos(2 * M_PI * t) -
     891            0.006 * sin(4.0 * M_PI * t) + 0.007 * cos(4.0 * M_PI * t);
     892        result = dut->data.F64[0] + dut->data.F64[1] * (mjd - dut->data.F64[2]) - dut2ut1;
     893
     894    } else if (status != PS_LOOKUP_SUCCESS) {
    965895        psError(PS_ERR_BAD_PARAMETER_VALUE, true, _("Failed time table interpolation."));
    966896        return NAN;
     
    1044974    *out = *time;
    1045975    if (out->type != PS_TIME_UT1) {
    1046         out = psTimeConvert(out, PS_TIME_UT1);
     976        psTimeConvert(out, PS_TIME_UT1);
    1047977    }
    1048978    //see if corrections include seconds or just nano-seconds
     
    10861016    PS_ASSERT_INT_WITHIN_RANGE(time->nsec,0,(psU32)((1e9)-1),NULL);
    10871017
    1088     if(time->type != PS_TIME_TAI) {
     1018    if (time->type != PS_TIME_TAI) {
    10891019        psError(PS_ERR_BAD_PARAMETER_VALUE, true, _("Specified type, %d, is incorrect."), time->type);
    10901020        return NULL;
     
    10921022
    10931023    // Check if psTime tables are already loaded
    1094     if(!p_psTimeInit(p_psTimeConfigFilename(NULL))) {
     1024    if (!timeInit(p_psTimeConfigFilename(NULL))) {
    10951025        psError(PS_ERR_UNKNOWN, true, "failed to init time tables.");
    10961026        return NULL;
     
    11051035
    11061036    // Value could not be found through table lookup and interpolation
    1107     if(xStatus==PS_LOOKUP_PAST_TOP && yStatus==PS_LOOKUP_PAST_TOP) {
     1037    if (xStatus==PS_LOOKUP_PAST_TOP && yStatus==PS_LOOKUP_PAST_TOP) {
    11081038
    11091039        // Date too earlier for tables. Get default polar coodinate values from metadata, and issue warning.
     
    11171047
    11181048        tableMetadataItem = psMetadataLookup(timeMetadata, "psLib.time.before.xp");
    1119         if(tableMetadataItem == NULL) {
     1049        if (tableMetadataItem == NULL) {
    11201050            psError(PS_ERR_BAD_PARAMETER_VALUE, true,
    11211051                    _("Failed find '%s' in time metadata."), "psLib.time.before.xp");
     
    11251055
    11261056        tableMetadataItem = psMetadataLookup(timeMetadata, "psLib.time.before.yp");
    1127         if(tableMetadataItem == NULL) {
     1057        if (tableMetadataItem == NULL) {
    11281058            psError(PS_ERR_BAD_PARAMETER_VALUE, true, _("Failed find '%s' in time metadata."), "psLib.time.before.yp");
    11291059            return NULL;
     
    11311061        y = tableMetadataItem->data.F64;
    11321062
    1133     } else if(xStatus==PS_LOOKUP_PAST_BOTTOM && yStatus==PS_LOOKUP_PAST_BOTTOM) {
     1063    } else if (xStatus==PS_LOOKUP_PAST_BOTTOM && yStatus==PS_LOOKUP_PAST_BOTTOM) {
    11341064
    11351065        /* Date too late for tables. Issue warning and use following formulae for predicting
     
    11541084        // Get predicted MJD
    11551085        tableMetadataItem = psMetadataLookup(timeMetadata, "psLib.time.predict.mjd");
    1156         if(tableMetadataItem == NULL) {
     1086        if (tableMetadataItem == NULL) {
    11571087            psError(PS_ERR_BAD_PARAMETER_VALUE, true, _("Failed find '%s' in time metadata."),
    11581088                    "psLib.time.predict.mjd");
     
    11631093        // Get xp
    11641094        tableMetadataItem = psMetadataLookup(timeMetadata, "psLib.time.predict.xp");
    1165         if(tableMetadataItem == NULL) {
     1095        if (tableMetadataItem == NULL) {
    11661096            psError(PS_ERR_BAD_PARAMETER_VALUE, true, _("Failed find '%s' in time metadata."), "psLib.time.predict.xp");
    11671097            return NULL;
     
    11721102        // Get yp
    11731103        tableMetadataItem = psMetadataLookup(timeMetadata, "psLib.time.predict.yp");
    1174         if(tableMetadataItem == NULL) {
     1104        if (tableMetadataItem == NULL) {
    11751105            psError(PS_ERR_BAD_PARAMETER_VALUE, true, _("Failed find '%s' in time metadata."), "psLib.time.predict.yp");
    11761106            return NULL;
     
    11801110
    11811111        // Calculate "a" and "c" constants
    1182         a = TWOPI*(mjd - mjdPred)/365.25;
    1183         c = TWOPI*(mjd - mjdPred)/435.0;
     1112        a = 2 * M_PI * (mjd - mjdPred) / 365.25;
     1113        c = 2 * M_PI * (mjd - mjdPred) / 435.0;
    11841114
    11851115        // Calculate x and y polar coordinates
     
    11961126            yp->data.F64[4]*sin(c);
    11971127
    1198     } else if(xStatus!=PS_LOOKUP_SUCCESS || yStatus!=PS_LOOKUP_SUCCESS) {
     1128    } else if (xStatus!=PS_LOOKUP_SUCCESS || yStatus!=PS_LOOKUP_SUCCESS) {
    11991129        psError(PS_ERR_BAD_PARAMETER_VALUE, true, _("Failed time table interpolation."));
    12001130        return NULL;
     
    12261156
    12271157    // Check if psTime tables are loaded/loadable
    1228     if (!p_psTimeInit(p_psTimeConfigFilename(NULL))) {
     1158    if (!timeInit(p_psTimeConfigFilename(NULL))) {
    12291159        psError(PS_ERR_BAD_PARAMETER_VALUE, true, _("Failed to open file %s."),
    12301160                p_psTimeConfigFilename(NULL));
     
    12341164    // Get table from metadata
    12351165    tableMetadataItem = psMetadataLookup(timeMetadata, "taiTable");
    1236     if(tableMetadataItem == NULL) {
     1166    if (tableMetadataItem == NULL) {
    12371167        psError(PS_ERR_BAD_PARAMETER_VALUE, true, _("Failed find '%s' in time metadata."), "taiTable");
    12381168        return NAN;
     
    12421172
    12431173    // Determine Julian and modified Julian dates used in table lookup and time delta calculation
    1244     if(time->sec < 0) {
     1174    if (time->sec < 0) {
    12451175        // psTime earlier than epoch
    12461176        jd = time->sec / SEC_PER_DAY - time->nsec / NSEC_PER_DAY + JD_EPOCH_OFFSET;
     
    12531183
    12541184    // Set ceiling of the julian date to the last entry in the lookup table
    1255     if(table->validTo < jd) {
     1185    if (table->validTo < jd) {
    12561186        jd = table->validTo;
    12571187    }
     
    12611191
    12621192    // Check for successful interpolation
    1263     if(results == NULL) {
     1193    if (results == NULL) {
    12641194        psError(PS_ERR_BAD_PARAMETER_VALUE, true, _("Failed time table interpolation."));
    12651195        return NAN;
     
    12721202
    12731203    // If const3 not equal to zero solve for difference else floor of const1
    1274     if(fabs(const3-0.0) > FLT_EPSILON) {
     1204    if (fabs(const3-0.0) > FLT_EPSILON) {
    12751205        out = const1 + (mjd - const2) * const3;
    12761206    } else {
     
    13061236
    13071237    // Verify time is UTC type
    1308     if(utc->type != PS_TIME_UTC) {
     1238    if (utc->type != PS_TIME_UTC) {
    13091239        psError(PS_ERR_BAD_PARAMETER_VALUE,true,_("Specified type, %d, is incorrect."),utc->type);
    13101240        return false;
     
    13161246
    13171247    // Check the absolute difference between the two times for leapsecond
    1318     if(psTimeLeapSecondDelta(utc,prevUtc) >= 1.0) {
     1248    if (psTimeLeapSecondDelta(utc,prevUtc) >= 1.0) {
    13191249        returnValue = true;
    13201250    } else {
     
    13301260double psTimeToJD(const psTime *time)
    13311261{
    1332     psF64 jd = NAN;
    1333 
    13341262    // Error checks
    13351263    PS_ASSERT_PTR_NON_NULL(time,NAN);
    13361264    PS_ASSERT_INT_WITHIN_RANGE(time->nsec,0,(psU32)((1e9)-1),NAN);
    13371265
     1266    // ADD says that this formula works only for PS_TIME_TAI, so adding the following:
    13381267    psTime *time2 = psTimeCopy(time);
    1339     //XXX: ADD says that this formula works only for PS_TIME_TAI, so adding the following:
    1340     if (time->type == PS_TIME_UTC || time->type == PS_TIME_TT) {
    1341         time2 = psTimeConvert(time2, PS_TIME_TAI);
    1342     }
    1343 
    1344     // Julian date conversion
    1345     if(time2->sec < 0) {
     1268    psTimeConvert(time2, PS_TIME_TAI);
     1269
     1270    double jd;                          // Julian date, to return
     1271    if (time2->sec < 0) {
    13461272        // psTime earlier than epoch
    13471273        jd = time2->sec / SEC_PER_DAY - time2->nsec / NSEC_PER_DAY + JD_EPOCH_OFFSET;
     
    13501276        jd = time2->sec / SEC_PER_DAY + time2->nsec / NSEC_PER_DAY + JD_EPOCH_OFFSET;
    13511277    }
    1352 
    13531278    psFree(time2);
     1279
    13541280    return jd;
    13551281}
     
    13571283double psTimeToMJD(const psTime *time)
    13581284{
    1359     psF64 mjd = NAN;
    1360 
    13611285    // Error checks
    13621286    PS_ASSERT_PTR_NON_NULL(time,NAN);
    13631287    PS_ASSERT_INT_WITHIN_RANGE(time->nsec,0,(psU32)((1e9)-1),NAN);
     1288
     1289    // ADD says that this formula works only for PS_TIME_TAI, so adding the following:
    13641290    psTime *time2 = psTimeCopy(time);
    1365     //XXX: ADD says that this formula works only for PS_TIME_TAI, so adding the following:
    1366     if (time->type == PS_TIME_UTC || time->type == PS_TIME_TT) {
    1367         time2 = psTimeConvert(time2, PS_TIME_TAI);
    1368     }
    1369 
    1370     // Modified Julian date conversion
    1371     if(time2->sec < 0) {
     1291    psTimeConvert(time2, PS_TIME_TAI);
     1292
     1293    double mjd;                         // Modified Julian Date, to return
     1294    if (time2->sec < 0) {
    13721295        // psTime earlier than epoch
    13731296        mjd = time2->sec / SEC_PER_DAY - time2->nsec / NSEC_PER_DAY + MJD_EPOCH_OFFSET;
     
    13771300    }
    13781301    psFree(time2);
     1302
    13791303    return mjd;
    13801304}
    13811305
    1382 psString psTimeToISO(const psTime *time)
    1383 {
    1384     psS32 ds = 0;
    1385     char *timeString = NULL;
    1386     char *tempString = NULL;
    1387 
     1306
     1307// Format a time as a string, allowing for a specified number of decimals for the seconds field
     1308static psString timeToString(const psTime *time, // Time to format as string
     1309                             int decimals // Number of decimals to permit for seconds
     1310                             )
     1311{
    13881312    // Error checks
    1389     PS_ASSERT_PTR_NON_NULL(time,NULL);
    1390     PS_ASSERT_INT_WITHIN_RANGE(time->nsec,0,(psU32)((1e9)-1),NULL);
    1391 
    1392     // Check valid year range
    1393     if ((time->sec) < ((psS64)YEAR_0000_SEC) || (time->sec) > ((psS64)YEAR_9999_SEC)) {
    1394       psError(PS_ERR_BAD_PARAMETER_VALUE, true, "Error: %s, %" PRId64 ", is out of range.  Must be between %" PRId64 " and %" PRId64 ".", "time->sec", time->sec, ((psS64)YEAR_0000_SEC), ((psS64)YEAR_9999_SEC));
    1395       return NULL;
    1396     }
    1397 
    1398     PS_ASSERT_S64_WITHIN_RANGE(time->sec, (psS64)YEAR_0000_SEC, (psS64)YEAR_9999_SEC, NULL);
    1399 
    1400     // Allocate temp strings
    1401     tempString = psAlloc(MAX_TIME_STRING_LENGTH);
    1402     timeString = psAlloc(MAX_TIME_STRING_LENGTH);
    1403 
    1404     // Convert nanoseconds to decaseconds
    1405     ds = time->nsec / 100000000;
    1406 
    1407     // tmTime variable is statically allocated, no need to free
    1408     struct tm *tmTime = psTimeToTM(time);
    1409 
    1410     // Converts psTime to YYYY-MM-DDThh:mm:ss.sss in string form
    1411     if (!strftime(tempString, MAX_TIME_STRING_LENGTH, "%Y-%m-%dT%H:%M:%S", tmTime)) {
     1313    PS_ASSERT_PTR_NON_NULL(time, NULL);
     1314    PS_ASSERT_INT_WITHIN_RANGE(time->nsec, 0, (psU32)((1e9)-1), NULL);
     1315    if (time->sec < YEAR_0000_SEC || time->sec > YEAR_9999_SEC) {
     1316        psError(PS_ERR_BAD_PARAMETER_VALUE, true,
     1317                "Time (%" PRId64 " sec) is not between year 0000 or 9999.\n", time->sec);
     1318        return NULL;
     1319    }
     1320    PS_ASSERT_INT_WITHIN_RANGE(decimals, 0, 9, NULL);
     1321
     1322    struct tm *tmTime = psTimeToTM(time); // Unix time structure
     1323
     1324    // Convert psTime to YYYY-MM-DDThh:mm:ss in string form
     1325    psString string = psStringAlloc(MAX_TIME_STRING_LENGTH); // Time string
     1326    if (!strftime(string, MAX_TIME_STRING_LENGTH, "%Y-%m-%dT%H:%M:%S", tmTime)) {
    14121327        psError(PS_ERR_OS_CALL_FAILED, true, _("Failed to convert a time via strftime function."));
    14131328        return NULL;
     
    14161331
    14171332    // Check if time is UTC and leapsecond
    1418     if(((time->type==PS_TIME_UTC)||(time->type==PS_TIME_UT1)) && (time->leapsecond)) {
     1333    if ((time->type == PS_TIME_UTC || time->type == PS_TIME_UT1) && time->leapsecond) {
    14191334        // Modify second to be 60
    1420         tempString[17] = '6';
    1421         tempString[18] = '0';
    1422     }
    1423 
    1424     // Create string with milliseconds
    1425     if (snprintf(timeString, MAX_TIME_STRING_LENGTH, "%s.%1d", tempString, ds) < 0) {
    1426         psError(PS_ERR_OS_CALL_FAILED, true, _("Failed to append millisecond to time string with snprintf function."));
    1427         return NULL;
    1428     }
    1429     psFree(tempString);
    1430 
    1431     return timeString;
     1335        string[17] = '6';
     1336        string[18] = '0';
     1337    }
     1338
     1339    // Add in the nanoseconds
     1340    if (decimals > 0) {
     1341        int partial = round((double)time->nsec / pow(10.0, 9 - decimals)); // Partial part
     1342        psString format = NULL;             // Format for printing partial part
     1343        psStringAppend(&format, ".%%0%dd", decimals);
     1344        psStringAppend(&string, format, partial);
     1345        psFree(format);
     1346    }
     1347
     1348    return string;
     1349}
     1350
     1351psString psTimeToString(const psTime *time, int decimals)
     1352{
     1353    return timeToString(time, decimals);
     1354}
     1355
     1356
     1357int psTimeSetISODecimals(int num)
     1358{
     1359    int temp = isoDecimals;          // Current value, to return
     1360    isoDecimals = num;
     1361    return temp;
     1362}
     1363
     1364int psTimeGetISODecimals(void)
     1365{
     1366    return isoDecimals;
     1367}
     1368
     1369psString psTimeToISO(const psTime *time)
     1370{
     1371    return timeToString(time, isoDecimals);
    14321372}
    14331373
     
    14871427    days = jd - 2440587.5;
    14881428    seconds = days * SEC_PER_DAY;
    1489     if(seconds < 0.0) {
     1429    if (seconds < 0.0) {
    14901430        outTime->nsec = (seconds - (psS64)seconds) * -1000000000.0;  // psTime earlier than epoch
    14911431    } else {
     
    15131453    seconds = days * SEC_PER_DAY;
    15141454
    1515     if(seconds < 0.0) {
     1455    if (seconds < 0.0) {
    15161456        outTime->nsec = (seconds - (psS64)seconds) * -1000000000.0;  // psTime earlier than epoch
    15171457    } else {
     
    17011641
    17021642    // Make month in range 3..14 (treat Jan & Feb as months 13..14 of prev year)
    1703     if( month <= 2 )
     1643    if ( month <= 2 )
    17041644    {
    17051645        temp = (14 - month) / 12;
     
    17071647        year -= temp;
    17081648        month += 12 * temp;
    1709     } else if(month > 14)
     1649    } else if (month > 14)
    17101650    {
    17111651        temp = (month - 3) / 12;
     
    17751715    }
    17761716
    1777     time->nsec += fractionalSeconds * 1e9;
     1717    time->nsec += fractionalSeconds * 1.0e9L;
    17781718    return time;
    17791719}
     
    18121752
    18131753    // Convert time to TAI if necessary, but without changing input arguments
    1814     if(time->type == PS_TIME_UTC) {
     1754    if (time->type == PS_TIME_UTC) {
    18151755        tempTime = psTimeAlloc(PS_TIME_UTC);
    18161756        tempTime->sec = time->sec;
    18171757        tempTime->nsec = time->nsec;
    1818         tempTime = psTimeConvert(tempTime, PS_TIME_TAI);
     1758        psTimeConvert(tempTime, PS_TIME_TAI);
    18191759        outTime = psTimeAlloc(PS_TIME_TAI);
    18201760    } else {
     
    18331773
    18341774    // Convert result to same time type as input
    1835     if(time->type == PS_TIME_UTC) {
    1836         outTime = psTimeConvert(outTime, PS_TIME_UTC);
     1775    if (time->type == PS_TIME_UTC) {
     1776        psTimeConvert(outTime, PS_TIME_UTC);
    18371777    }
    18381778
     
    18581798
    18591799    // Verify both times of the same type
    1860     if(time1->type != time2->type) {
     1800    if (time1->type != time2->type) {
    18611801        psError(PS_ERR_BAD_PARAMETER_VALUE,true,_("Specified type, %d, is incorrect."),time1->type);
    18621802        return NAN;
     
    18641804
    18651805    // Convert time to TAI if necessary, but without changing input arguments
    1866     if(time1->type == PS_TIME_UTC) {
     1806    if (time1->type == PS_TIME_UTC) {
    18671807        tempTime1 = psTimeAlloc(PS_TIME_UTC);
    18681808        tempTime1->sec = time1->sec;
    18691809        tempTime1->nsec = time1->nsec;
    1870         tempTime1 = psTimeConvert(tempTime1, PS_TIME_TAI);
     1810        psTimeConvert(tempTime1, PS_TIME_TAI);
    18711811    } else {
    18721812        tempTime1 = psMemIncrRefCounter((psTime*)time1);
    18731813    }
    1874     if(time2->type == PS_TIME_UTC) {
     1814    if (time2->type == PS_TIME_UTC) {
    18751815        tempTime2 = psTimeAlloc(PS_TIME_UTC);
    18761816        tempTime2->sec = time2->sec;
    18771817        tempTime2->nsec = time2->nsec;
    1878         tempTime2 = psTimeConvert(tempTime2, PS_TIME_TAI);
     1818        psTimeConvert(tempTime2, PS_TIME_TAI);
    18791819    } else {
    18801820        tempTime2 = psMemIncrRefCounter((psTime*)time2);
Note: See TracChangeset for help on using the changeset viewer.