Index: trunk/psLib/src/astronomy/psTime.c
===================================================================
--- trunk/psLib/src/astronomy/psTime.c	(revision 1223)
+++ trunk/psLib/src/astronomy/psTime.c	(revision 1247)
@@ -12,6 +12,6 @@
  *  @author Ross Harman, MHPCC
  *
- *  @version $Revision: 1.1 $ $Name: not supported by cvs2svn $
- *  @date $Date: 2004-07-15 19:02:13 $
+ *  @version $Revision: 1.2 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2004-07-21 01:29:33 $
  *
  *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
@@ -24,7 +24,11 @@
 
 #include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
 
 #include "psTime.h"
 #include "psError.h"
+#define PS_ALLOW_MALLOC
+#include "psMemory.h"
 
 /******************************************************************************/
@@ -32,6 +36,20 @@
 /******************************************************************************/
 
-// Number of available leapsecond updates
-#define NUM_LEAPSECOND_UPDATES 23
+/** Preprocessor macro to generate error for negative time in struct */
+#define CHECK_NEGATIVE_TIME_STRUCT(NAME,RETURN)                                                              \
+if(NAME.tv_sec < 0) {                                                                                        \
+    psError(__func__,"Negative seconds are not allowed: %ld", NAME.tv_sec);                                  \
+    return RETURN;                                                                                           \
+} else if(NAME.tv_usec<0) {                                                                                  \
+    psError(__func__,"Negative microseconds are not allowed: %ld", NAME.tv_usec);                            \
+    return RETURN;                                                                                           \
+}
+
+/** Preprocessor macro to generate error for negative time */
+#define CHECK_NEGATIVE_TIME(NAME,RETURN)                                                                     \
+if(NAME < 0.0) {                                                                                             \
+    psError(__func__,"Negative time is not allowed: %f", NAME);                                              \
+    return RETURN;                                                                                           \
+}                                                                                                            \
 
 /******************************************************************************/
@@ -55,30 +73,30 @@
 the psTimeGetTime() function to calculate TAI time from  UTC time.
  
- 1972 JAN  1 =JD 2441317.5  TAI-UTC=  10.0
- 1972 JUL  1 =JD 2441499.5  TAI-UTC=  11.0
- 1973 JAN  1 =JD 2441683.5  TAI-UTC=  12.0
- 1974 JAN  1 =JD 2442048.5  TAI-UTC=  13.0
- 1975 JAN  1 =JD 2442413.5  TAI-UTC=  14.0
- 1976 JAN  1 =JD 2442778.5  TAI-UTC=  15.0
- 1977 JAN  1 =JD 2443144.5  TAI-UTC=  16.0
- 1978 JAN  1 =JD 2443509.5  TAI-UTC=  17.0
- 1979 JAN  1 =JD 2443874.5  TAI-UTC=  18.0
- 1980 JAN  1 =JD 2444239.5  TAI-UTC=  19.0
- 1981 JUL  1 =JD 2444786.5  TAI-UTC=  20.0
- 1982 JUL  1 =JD 2445151.5  TAI-UTC=  21.0
- 1983 JUL  1 =JD 2445516.5  TAI-UTC=  22.0
- 1985 JUL  1 =JD 2446247.5  TAI-UTC=  23.0
- 1988 JAN  1 =JD 2447161.5  TAI-UTC=  24.0
- 1990 JAN  1 =JD 2447892.5  TAI-UTC=  25.0
- 1991 JAN  1 =JD 2448257.5  TAI-UTC=  26.0
- 1992 JUL  1 =JD 2448804.5  TAI-UTC=  27.0
- 1993 JUL  1 =JD 2449169.5  TAI-UTC=  28.0
- 1994 JUL  1 =JD 2449534.5  TAI-UTC=  29.0
- 1996 JAN  1 =JD 2450083.5  TAI-UTC=  30.0
- 1997 JUL  1 =JD 2450630.5  TAI-UTC=  31.0
- 1999 JAN  1 =JD 2451179.5  TAI-UTC=  32.0
+ 1972 JAN 1 = JD 2441317.5  TAI-UTC = 10.0
+ 1972 JUL 1 = JD 2441499.5  TAI-UTC = 11.0
+ 1973 JAN 1 = JD 2441683.5  TAI-UTC = 12.0
+ 1974 JAN 1 = JD 2442048.5  TAI-UTC = 13.0
+ 1975 JAN 1 = JD 2442413.5  TAI-UTC = 14.0
+ 1976 JAN 1 = JD 2442778.5  TAI-UTC = 15.0
+ 1977 JAN 1 = JD 2443144.5  TAI-UTC = 16.0
+ 1978 JAN 1 = JD 2443509.5  TAI-UTC = 17.0
+ 1979 JAN 1 = JD 2443874.5  TAI-UTC = 18.0
+ 1980 JAN 1 = JD 2444239.5  TAI-UTC = 19.0
+ 1981 JUL 1 = JD 2444786.5  TAI-UTC = 20.0
+ 1982 JUL 1 = JD 2445151.5  TAI-UTC = 21.0
+ 1983 JUL 1 = JD 2445516.5  TAI-UTC = 22.0
+ 1985 JUL 1 = JD 2446247.5  TAI-UTC = 23.0
+ 1988 JAN 1 = JD 2447161.5  TAI-UTC = 24.0
+ 1990 JAN 1 = JD 2447892.5  TAI-UTC = 25.0
+ 1991 JAN 1 = JD 2448257.5  TAI-UTC = 26.0
+ 1992 JUL 1 = JD 2448804.5  TAI-UTC = 27.0
+ 1993 JUL 1 = JD 2449169.5  TAI-UTC = 28.0
+ 1994 JUL 1 = JD 2449534.5  TAI-UTC = 29.0
+ 1996 JAN 1 = JD 2450083.5  TAI-UTC = 30.0
+ 1997 JUL 1 = JD 2450630.5  TAI-UTC = 31.0
+ 1999 JAN 1 = JD 2451179.5  TAI-UTC = 32.0
 */
 
-// Julian date of leapsecond update and current total number of leapseconds for that date
+// Table for Julian date of leapsecond update and current total number of leapseconds at that date
 static double leapseconds[NUM_LEAPSECOND_UPDATES][2] =
     {
@@ -135,5 +153,5 @@
     time.tv_usec = now.tv_usec;
 
-    // Add last known leapseconds to UTC time to get TAI time
+    // Add most current leapseconds value to UTC time to get TAI time
     time.tv_sec += leapseconds[NUM_LEAPSECOND_UPDATES][1];
 
@@ -143,7 +161,297 @@
 char* psTimeToISO(psTime time)
 {
-    struct tm *tm;
-    tm = localtime (&time.tv_sec);
-    printf("%d\n", tm->tm_sec);
-    return NULL;
-}
+    int ms = 0;
+    char *timeString = NULL;
+    char *tempString = NULL;
+    struct tm *tmTime = NULL;
+
+    CHECK_NEGATIVE_TIME_STRUCT(time,NULL);
+
+    tempString = psAlloc(MAX_TIME_STRING_LENGTH);
+    timeString = psAlloc(MAX_TIME_STRING_LENGTH);
+
+    // Converts psTime to YYYY/MM/DD,HH:MM:SS.SSS in string form
+    ms = time.tv_usec/1000;
+    tmTime = gmtime(&time.tv_sec);
+    if(!strftime(tempString, MAX_TIME_STRING_LENGTH, "%Y/%m/%d,%H:%M:%S", tmTime)) {
+        psError(__func__, " : Line %d - Failed strftime conversion", __LINE__);
+    }
+
+    if(snprintf(timeString,MAX_TIME_STRING_LENGTH,"%s.%3.3d", tempString, ms) < 0) {
+        psError(__func__, " : Line %d - Failed snprintf conversion", __LINE__);
+    }
+    psFree(tempString);
+    free(tmTime);
+
+    return timeString;
+}
+
+psTime psTimeToUTC(psTime time)
+{
+    int i = 0;
+    double jd = 0.0;
+    double ls = 0.0;
+    double *jdTable = NULL;
+    psTime outTime;
+
+    CHECK_NEGATIVE_TIME_STRUCT(time,outTime);
+
+    // Find leapseconds to subtract from psTime to get UTC time
+    jd = psTimeToJD(time);
+    jdTable = leapseconds[0];
+    for(i=0; i<NUM_LEAPSECOND_UPDATES; i++, jdTable+=2) {
+        if(jd > *jdTable) {
+            ls = *(jdTable + 1);
+        }
+    }
+
+    outTime.tv_sec = time.tv_sec - ls;
+    outTime.tv_usec = time.tv_usec;
+
+    CHECK_NEGATIVE_TIME_STRUCT(outTime,outTime);
+
+    return outTime;
+}
+
+double psTimeToMJD(psTime time)
+{
+    double mjd = 0.0;
+
+    CHECK_NEGATIVE_TIME_STRUCT(time,mjd);
+
+    // Modified Julian date conversion courtesy of Eugene Magnier
+    mjd = time.tv_sec/SEC_PER_DAY + time.tv_usec/USEC_PER_DAY + 40587.0;
+
+    return mjd;
+}
+
+double psTimeToJD(psTime time)
+{
+    double jd = 0.0;
+
+    CHECK_NEGATIVE_TIME_STRUCT(time,jd);
+
+    // Julian date conversion courtesy of Eugene Magnier
+    jd = time.tv_sec/SEC_PER_DAY + time.tv_usec/USEC_PER_DAY + 2440587.5;
+
+    return jd;
+}
+
+struct timeval psTimeToTimeval(psTime time)
+{
+    struct timeval timevalTime;
+
+    CHECK_NEGATIVE_TIME_STRUCT(time,timevalTime);
+    timevalTime.tv_sec = time.tv_sec;
+    timevalTime.tv_usec = time.tv_usec;
+
+    return timevalTime;
+}
+
+struct tm* psTimeToTM(psTime time)
+{
+    struct tm *tmTime = NULL;
+
+    CHECK_NEGATIVE_TIME_STRUCT(time,tmTime);
+    tmTime = gmtime(&time.tv_sec);
+
+    return tmTime;
+}
+
+psTime psISOToTime(char *time)
+{
+    char tempString[MAX_TIME_STRING_LENGTH];
+    int month;
+    int day;
+    int year;
+    int hour;
+    int minute;
+    int second;
+    int millisecond;
+    struct tm tmTime;
+    psTime outTime;
+
+    strncpy(tempString, time, MAX_TIME_STRING_LENGTH);
+
+    // Convert YYYY/MM/DD,HH:MM:SS.SSS in string form to tm time
+    year = atoi(strtok(tempString, "/"));
+    if(year < 0) {
+        psError(__func__,"Years less than 1900 not allowed. Value: %d", year);
+    }
+
+    month = atoi(strtok(tempString, "/"));
+    if(month<1 || month>12) {
+        psError(__func__,"Month must have a value from 0 to 11. Value: %d", month);
+    }
+
+    day = atoi(strtok(tempString, ","));
+    if(day<1 || day>31) {
+        psError(__func__,"Day must have a value from 1 to 31. Value: %d", day);
+    }
+
+    hour = atoi(strtok(tempString, ":"));
+    if(hour<0 || hour>23) {
+        psError(__func__,"Hour must have a value from 0 to 23. Value: %d", hour);
+    }
+
+    second = atoi(strtok(tempString, "."));
+    if(second<0 || second>60) {
+        psError(__func__,"Second must have a value from 0 to 59. Value: %d", second);
+    }
+
+    millisecond = atoi(strtok(tempString, "X"));
+    if(millisecond<0 || millisecond>1000) {
+        psError(__func__,"Second must have a value from 0 to 999. Value: %d", millisecond);
+    }
+
+    tmTime.tm_year = year - 1900;
+    tmTime.tm_mon = month - 1;
+    tmTime.tm_mday = day;
+    tmTime.tm_hour = hour;
+    tmTime.tm_min = minute;
+    tmTime.tm_sec = second;
+
+    // Convert tm time to psTime
+    outTime = psTMToTime(&tmTime);
+    outTime.tv_usec = millisecond*1000;
+
+    return outTime;
+}
+
+psTime psUTCToTime(psTime time)
+{
+    psTime outTime;
+
+    CHECK_NEGATIVE_TIME_STRUCT(time,outTime);
+
+    // Convert UTC time to psTime/TAI
+    outTime.tv_sec = time.tv_sec + leapseconds[NUM_LEAPSECOND_UPDATES][1];
+    ;
+    outTime.tv_usec = time.tv_usec;
+    CHECK_NEGATIVE_TIME_STRUCT(outTime,outTime);
+
+    return time;
+}
+
+psTime psMJDToTime(double time)
+{
+    psTime outTime;
+    double days = 0.0;
+    double seconds = 0.0;
+
+    CHECK_NEGATIVE_TIME(time,outTime);
+
+    // Modified Julian date conversion courtesy of Eugene Magnier
+    days = time - 40587.0;
+
+    // Convert to psTime/TAI
+    seconds = days*SEC_PER_DAY;
+    outTime.tv_usec = (seconds -(long)seconds)*1000000.0;
+    outTime.tv_sec = seconds;
+
+    CHECK_NEGATIVE_TIME_STRUCT(outTime,outTime);
+
+    return outTime;
+}
+
+psTime psJDToTime(double time)
+{
+    double days = 0.0;
+    double seconds = 0.0;
+    psTime outTime;
+
+    CHECK_NEGATIVE_TIME(time,outTime);
+
+    // Julian date conversion courtesy of Eugene Magnier
+    days = time - 2440587.5;
+
+    // Convert to psTime/TAI
+    seconds = days*SEC_PER_DAY;
+    outTime.tv_sec = seconds;
+    outTime.tv_usec = (seconds -(long)seconds)*1000000.0;
+
+    CHECK_NEGATIVE_TIME_STRUCT(outTime,outTime);
+
+    return outTime;
+}
+
+psTime psTimevalToTime(struct timeval *time)
+{
+    psTime outTime;
+    if(time == NULL)
+    {
+        psError(__func__,"Null value for timeval arg not allowed");
+        return outTime;
+    } else if(time->tv_sec < 0)
+    {
+        psError(__func__,"Negative seconds are not allowed: %ld", time->tv_sec);
+        return outTime;
+    } else if(time->tv_usec<0)
+    {
+        psError(__func__,"Negative microseconds are not allowed: %ld", time->tv_usec);
+        return outTime;
+    }
+
+    // Convert to psTime/TAI
+    outTime.tv_sec = time->tv_sec;
+    outTime.tv_usec = time->tv_usec;
+
+    CHECK_NEGATIVE_TIME_STRUCT(outTime,outTime);
+
+    return outTime;
+}
+
+
+psTime psTMToTime(struct tm *time)
+{
+    int i;
+    int m;
+    int n;
+    int y;
+    int mon [] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
+    long epoch;
+    psTime outTime;
+
+    i= 0;
+    m = 0;
+    n = 0;
+    y = 0;
+    epoch = 0;
+
+    if(time == NULL)
+    {
+        psError(__func__,"Null value for tm arg not allowed");
+        return outTime;
+    } else if(time->tm_year < 70)
+    {
+        psError(__func__,"Input times earlier than 1970 not allowed");
+        return outTime;
+    }
+
+    n = time->tm_year + 1900 - 1;
+    epoch = (time->tm_year - 70) * SEC_PER_YEAR + ((n/4 - n/100 + n/400) -
+            (1969/4 - 1969/100 + 1969/400)) * SEC_PER_DAY;
+
+    y = time->tm_year + 1900;
+
+    for(i = 0; i < time->tm_mon; i++)
+    {
+        epoch += mon [m] * SEC_PER_DAY;
+        if(m == 1 && y % 4 == 0 && (y % 100 != 0 || y % 400 == 0)) {
+            epoch += SEC_PER_DAY;
+        }
+
+        if(++m > 11) {
+            m = 0;
+            y++;
+        }
+    }
+
+    epoch += (time->tm_mday - 1) * SEC_PER_DAY;
+    epoch += time->tm_hour *SEC_PER_HOUR + time->tm_min * SEC_PER_MINUTE + time->tm_sec;
+
+    outTime.tv_usec = 0;
+    outTime.tv_sec = epoch;
+
+    return outTime;
+}
