Index: /trunk/psLib/src/astro/psTime.c
===================================================================
--- /trunk/psLib/src/astro/psTime.c	(revision 1613)
+++ /trunk/psLib/src/astro/psTime.c	(revision 1614)
@@ -1,3 +1,2 @@
-
 /** @file  psTime.c
  *
@@ -7,12 +6,54 @@
  *  A collection of functions are required by psLib to manipulate time data. These functions primarily consist
  *  of conversions between specific time formats.  PSLib currently uses the UNIX timeval time system as the
- *  base upon which International Atomic Time (TAI) time is calculated. TAI time varies over time due to the
- *  earth's rotation and the movement of the continental plates. It is currentls 32 seconds faster than
- *  UTC/timeval time.
+ *  base upon which International Atomic Time (TAI) and Universal Time Coordinated (UTC) are calculated. TAI
+ *  time varies over time due to the earth's rotation and the movement of the continental plates. It is
+ *  currentls 32 seconds faster than UTC/timeval time. The conversion between TAI and UTC time for other dates
+ *  is given in the table below, which comes from:
+ *
+ *  ftp://maia.usno.navy.mil/ser7/tai-utc.dat
+ *
+ *  This table is placed into a static array and used by the psTime functions for conversions.
+ *
+ *   1961 JAN  1 =JD 2437300.5  TAI-UTC=   1.4228180 S + (MJD - 37300.) X 0.001296 S
+ *   1961 AUG  1 =JD 2437512.5  TAI-UTC=   1.3728180 S + (MJD - 37300.) X 0.001296 S
+ *   1962 JAN  1 =JD 2437665.5  TAI-UTC=   1.8458580 S + (MJD - 37665.) X 0.0011232S
+ *   1963 NOV  1 =JD 2438334.5  TAI-UTC=   1.9458580 S + (MJD - 37665.) X 0.0011232S
+ *   1964 JAN  1 =JD 2438395.5  TAI-UTC=   3.2401300 S + (MJD - 38761.) X 0.001296 S
+ *   1964 APR  1 =JD 2438486.5  TAI-UTC=   3.3401300 S + (MJD - 38761.) X 0.001296 S
+ *   1964 SEP  1 =JD 2438639.5  TAI-UTC=   3.4401300 S + (MJD - 38761.) X 0.001296 S
+ *   1965 JAN  1 =JD 2438761.5  TAI-UTC=   3.5401300 S + (MJD - 38761.) X 0.001296 S
+ *   1965 MAR  1 =JD 2438820.5  TAI-UTC=   3.6401300 S + (MJD - 38761.) X 0.001296 S
+ *   1965 JUL  1 =JD 2438942.5  TAI-UTC=   3.7401300 S + (MJD - 38761.) X 0.001296 S
+ *   1965 SEP  1 =JD 2439004.5  TAI-UTC=   3.8401300 S + (MJD - 38761.) X 0.001296 S
+ *   1966 JAN  1 =JD 2439126.5  TAI-UTC=   4.3131700 S + (MJD - 39126.) X 0.002592 S
+ *   1968 FEB  1 =JD 2439887.5  TAI-UTC=   4.2131700 S + (MJD - 39126.) X 0.002592 S
+ *   1972 JAN  1 =JD 2441317.5  TAI-UTC=  10.0       S + (MJD - 41317.) X 0.0      S
+ *   1972 JUL  1 =JD 2441499.5  TAI-UTC=  11.0       S + (MJD - 41317.) X 0.0      S
+ *   1973 JAN  1 =JD 2441683.5  TAI-UTC=  12.0       S + (MJD - 41317.) X 0.0      S
+ *   1974 JAN  1 =JD 2442048.5  TAI-UTC=  13.0       S + (MJD - 41317.) X 0.0      S
+ *   1975 JAN  1 =JD 2442413.5  TAI-UTC=  14.0       S + (MJD - 41317.) X 0.0      S
+ *   1976 JAN  1 =JD 2442778.5  TAI-UTC=  15.0       S + (MJD - 41317.) X 0.0      S
+ *   1977 JAN  1 =JD 2443144.5  TAI-UTC=  16.0       S + (MJD - 41317.) X 0.0      S
+ *   1978 JAN  1 =JD 2443509.5  TAI-UTC=  17.0       S + (MJD - 41317.) X 0.0      S
+ *   1979 JAN  1 =JD 2443874.5  TAI-UTC=  18.0       S + (MJD - 41317.) X 0.0      S
+ *   1980 JAN  1 =JD 2444239.5  TAI-UTC=  19.0       S + (MJD - 41317.) X 0.0      S
+ *   1981 JUL  1 =JD 2444786.5  TAI-UTC=  20.0       S + (MJD - 41317.) X 0.0      S
+ *   1982 JUL  1 =JD 2445151.5  TAI-UTC=  21.0       S + (MJD - 41317.) X 0.0      S
+ *   1983 JUL  1 =JD 2445516.5  TAI-UTC=  22.0       S + (MJD - 41317.) X 0.0      S
+ *   1985 JUL  1 =JD 2446247.5  TAI-UTC=  23.0       S + (MJD - 41317.) X 0.0      S
+ *   1988 JAN  1 =JD 2447161.5  TAI-UTC=  24.0       S + (MJD - 41317.) X 0.0      S
+ *   1990 JAN  1 =JD 2447892.5  TAI-UTC=  25.0       S + (MJD - 41317.) X 0.0      S
+ *   1991 JAN  1 =JD 2448257.5  TAI-UTC=  26.0       S + (MJD - 41317.) X 0.0      S
+ *   1992 JUL  1 =JD 2448804.5  TAI-UTC=  27.0       S + (MJD - 41317.) X 0.0      S
+ *   1993 JUL  1 =JD 2449169.5  TAI-UTC=  28.0       S + (MJD - 41317.) X 0.0      S
+ *   1994 JUL  1 =JD 2449534.5  TAI-UTC=  29.0       S + (MJD - 41317.) X 0.0      S
+ *   1996 JAN  1 =JD 2450083.5  TAI-UTC=  30.0       S + (MJD - 41317.) X 0.0      S
+ *   1997 JUL  1 =JD 2450630.5  TAI-UTC=  31.0       S + (MJD - 41317.) X 0.0      S
+ *   1999 JAN  1 =JD 2451179.5  TAI-UTC=  32.0       S + (MJD - 41317.) X 0.0      S
  *
  *  @author Ross Harman, MHPCC
  *
- *  @version $Revision: 1.20 $ $Name: not supported by cvs2svn $
- *  @date $Date: 2004-08-19 18:57:49 $
+ *  @version $Revision: 1.21 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2004-08-25 01:37:34 $
  *
  *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
@@ -26,42 +67,9 @@
 #include "psError.h"
 #include "psMemory.h"
-
-/******************************************************************************/
-/*  DEFINE STATEMENTS                                                         */
-/******************************************************************************/
-/******************************************************************************/
-/*  DEFINE STATEMENTS                                                         */
-/******************************************************************************/
-
-// None
-
-/******************************************************************************/
-/*  TYPE DEFINITIONS                                                          */
-/******************************************************************************/
-
-// None
-
-/*****************************************************************************/
-/*  GLOBAL VARIABLES                                                         */
-/*****************************************************************************/
-
-// None
-
-/*****************************************************************************/
-/*  FILE STATIC VARIABLES                                                    */
-/*****************************************************************************/
-
-// None
-
-/*****************************************************************************/
-/*  FUNCTION IMPLEMENTATION - LOCAL                                          */
-/*****************************************************************************/
-
-/******************************************************************************/
-/*  DEFINE STATEMENTS                                                         */
-/******************************************************************************/
+#include "psAbort.h"
+
 
 /** Number of available leapsecond updates */
-#define NUM_LEAPSECOND_UPDATES 23
+#define NUM_UPDATES 36
 
 /** Maximum length of time string */
@@ -83,98 +91,193 @@
 #define USEC_PER_DAY 86400000000.0
 
-/** 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);                                  \
+/** Preprocessor macro to check for null psTime struct */
+#define CHECK_NULL_TIME(TIME,RETURN)                                                                         \
+if(TIME == NULL) {                                                                                           \
+    psError(__func__,"NULL value not allowed");                                                              \
     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;                                                                                           \
-}                                                                                                            \
-
-/* The table below comes from http://tycho.usno.navy.mil/leapsec.html, which reports the current state of
-the TAI/UTC leapsecond conversion times. This table is placed into a two dimensional array and used by
-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
+}
+
+/** Preprocessor macro to allocate psTime strict */
+#define ALLOC_TIME(TIME)                                                                                     \
+TIME = (psTime*)psAlloc(sizeof(psTime));                                                                 \
+if (TIME == NULL) {                                                                                      \
+    psAbort(__func__, " : Line %d - Failed to allocate memory", __LINE__);                               \
+}
+
+/*
+ The table below comes from ftp://maia.usno.navy.mil/ser7/tai-utc.dat, which reports the current state of
+ the TAI/UTC leapsecond conversion times.
 */
-static double leapseconds[NUM_LEAPSECOND_UPDATES][2] = {
-            {2441317.5, 10.0},
-            {2441499.5, 11.0},
-            {2441683.5, 12.0},
-            {2442048.5, 13.0},
-            {2442413.5, 14.0},
-            {2442778.5, 15.0},
-            {2443144.5, 16.0},
-            {2443509.5, 17.0},
-            {2443874.5, 18.0},
-            {2444239.5, 19.0},
-            {2444786.5, 20.0},
-            {2445151.5, 21.0},
-            {2445516.5, 22.0},
-            {2446247.5, 23.0},
-            {2447161.5, 24.0},
-            {2447892.5, 25.0},
-            {2448257.5, 26.0},
-            {2448804.5, 27.0},
-            {2449169.5, 28.0},
-            {2449534.5, 29.0},
-            {2450083.5, 30.0},
-            {2450630.5, 31.0},
-            {2451179.5, 32.0}
-        };
-
-psTime psTimeGetTime(void)
+static double lsTable[NUM_UPDATES][4] = {
+                                            {2437300.5,  1.422818, 37300.0, 0.0012960},
+                                            {2437512.5,  1.372818, 37300.0, 0.0012960},
+                                            {2437665.5,  1.845858, 37665.0, 0.0011232},
+                                            {2438334.5,  1.945858, 37665.0, 0.0011232},
+                                            {2438395.5,  3.240130, 38761.0, 0.0012960},
+                                            {2438486.5,  3.340130, 38761.0, 0.0012960},
+                                            {2438639.5,  3.440130, 38761.0, 0.0012960},
+                                            {2438761.5,  3.540130, 38761.0, 0.0012960},
+                                            {2438820.5,  3.640130, 38761.0, 0.0012960},
+                                            {2438942.5,  3.740130, 38761.0, 0.0012960},
+                                            {2439004.5,  3.840130, 38761.0, 0.0012960},
+                                            {2439126.5,  4.313170, 39126.0, 0.0025920},
+                                            {2439887.5,  4.213170, 39126.0, 0.0025920},
+                                            {2441317.5, 10.000000, 41317.0, 0.0000000},
+                                            {2441499.5, 11.000000, 41317.0, 0.0000000},
+                                            {2441683.5, 12.000000, 41317.0, 0.0000000},
+                                            {2442048.5, 13.000000, 41317.0, 0.0000000},
+                                            {2442413.5, 14.000000, 41317.0, 0.0000000},
+                                            {2442778.5, 15.000000, 41317.0, 0.0000000},
+                                            {2443144.5, 16.000000, 41317.0, 0.0000000},
+                                            {2443509.5, 17.000000, 41317.0, 0.0000000},
+                                            {2443874.5, 18.000000, 41317.0, 0.0000000},
+                                            {2444239.5, 19.000000, 41317.0, 0.0000000},
+                                            {2444786.5, 20.000000, 41317.0, 0.0000000},
+                                            {2445151.5, 21.000000, 41317.0, 0.0000000},
+                                            {2445516.5, 22.000000, 41317.0, 0.0000000},
+                                            {2446247.5, 23.000000, 41317.0, 0.0000000},
+                                            {2447161.5, 24.000000, 41317.0, 0.0000000},
+                                            {2447892.5, 25.000000, 41317.0, 0.0000000},
+                                            {2448257.5, 26.000000, 41317.0, 0.0000000},
+                                            {2448804.5, 27.000000, 41317.0, 0.0000000},
+                                            {2449169.5, 28.000000, 41317.0, 0.0000000},
+                                            {2449534.5, 29.000000, 41317.0, 0.0000000},
+                                            {2450083.5, 30.000000, 41317.0, 0.0000000},
+                                            {2450630.5, 31.000000, 41317.0, 0.0000000},
+                                            {2451179.5, 32.000000, 41317.0, 0.0000000}
+                                        };
+
+
+psTime* psTimeGetTime(psTimeType type)
 {
     struct timeval now;
-    psTime time;
-
-    time.tv_sec = 0;
-    time.tv_usec = 0;
+    psTime *time = NULL;
+
+    // Allocate psTime struct
+    ALLOC_TIME(time);
 
     if (gettimeofday(&now, (struct timezone *)0) == -1) {
         psError(__func__, " : Line %d - Failed to get time", __LINE__);
-        return time;
-    }
+        return NULL;
+    }
+
     // Convert timeval time to psTime
-    time.tv_sec = now.tv_sec;
-    time.tv_usec = now.tv_usec;
-
-    // Add most current leapseconds value to UTC time to get TAI time
-    time.tv_sec += leapseconds[NUM_LEAPSECOND_UPDATES - 1][1];
+    time->sec = now.tv_sec;
+    time->usec = now.tv_usec;
+    time->type = type;
+
+    // Add most leapseconds to UTC time to get TAI time if necessary
+    if(type == PS_TIME_TAI) {
+        time->sec += psGetTAIDelta(time);
+    }
 
     return time;
 }
 
-char *psTimeToISO(psTime time)
+psTime* psTimeConvert(psTime *time, psTimeType type)
+{
+    double delta = 0.0;
+
+    if(time->type == type) {
+        psError(__func__, " : Line %d - Time is already in the correct psTime format. Time type: %d", __LINE__, type);
+        return NULL;
+    }
+
+    delta = psGetTAIDelta(time);
+
+    if(type == PS_TIME_UTC) {
+        time->sec = time->sec - delta;    // User wants UTC time. Remove leapseconds.
+    } else if(type == PS_TIME_TAI) {
+        time->sec = time->sec + delta;    // User wants TAI time. Add leapseconds.
+    } else {
+        psError(__func__, " : Line %d - Invalid psTimeType: %d", __LINE__, type);
+    }
+
+    return time;
+}
+
+double psTimeToLST(psTime *time, double longitude)
+{
+    double delta = 0;
+
+    return delta;
+}
+
+psTime* psLSTToTime(double time, double longitude)
+{
+    psTime *outTime = NULL;
+
+    return outTime;
+}
+
+double psGetUT1Delta(psTime *time)
+{
+    double delta = 0;
+
+    return delta;
+}
+
+double psGetTAIDelta(psTime *time)
+{
+    int i = 0;
+    double delta = 0.0;
+    double jd = 0.0;
+    double mjd = 0.0;
+
+    // Determine Julian and modified Julian dates used in table lookup and time delta calculation
+    jd = psTimeToJD(time);
+    mjd = psTimeToMJD(time);
+
+    // Perform table lookup
+    if(jd < lsTable[0][1]) {                        // Times earlier than 1961
+        delta = 0.0;
+    } else if(jd > lsTable[NUM_UPDATES-1][1]) {      // Times greater than latest table entry
+        delta = lsTable[NUM_UPDATES-1][1] + (mjd - lsTable[NUM_UPDATES-1][2]) * lsTable[NUM_UPDATES-1][3];
+    } else {                                        // All other times
+        for (i = 0; i<NUM_UPDATES-1; i++) {
+            if (jd>lsTable[i][0] && jd<lsTable[i+1][0]) {
+                delta = lsTable[i][1] + (mjd - lsTable[i][2]) * lsTable[i][3];
+            }
+        }
+    }
+
+    return delta;
+}
+
+double psTimeToJD(psTime *time)
+{
+    double jd = 0.0;
+
+    // NULL error check
+    CHECK_NULL_TIME(time,0.0);
+
+    // Julian date conversion courtesy of Eugene Magnier
+    if(time->sec < 0) {
+        jd = time->sec / SEC_PER_DAY - time->usec / USEC_PER_DAY + 2440587.5; // psTime earlier than epoch
+    } else {
+        jd = time->sec / SEC_PER_DAY + time->usec / USEC_PER_DAY + 2440587.5; // psTime greater than epoch
+    }
+
+    return jd;
+}
+
+double psTimeToMJD(psTime *time)
+{
+    double mjd = 0.0;
+
+    // NULL error check
+    CHECK_NULL_TIME(time,0.0);
+
+    // Modified Julian date conversion courtesy of Eugene Magnier
+    if(time->sec < 0) {
+        mjd = time->sec / SEC_PER_DAY - time->usec / USEC_PER_DAY + 40587.0; // psTime earlier than epoch
+    } else {
+        mjd = time->sec / SEC_PER_DAY + time->usec / USEC_PER_DAY + 40587.0; // psTime greater than epoch
+    }
+
+    return mjd;
+}
+
+char* psTimeToISO(psTime *time)
 {
     int ms = 0;
@@ -184,20 +287,22 @@
     time_t sec;
 
-    CHECK_NEGATIVE_TIME_STRUCT(time, NULL);
+    // NULL error check
+    CHECK_NULL_TIME(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;
-
-    sec = time.tv_sec;
+    ms = time->usec / 1000;
+    sec = time->sec;
+
     // tmTime variable is statically allocated, no need to free
     tmTime = gmtime(&sec);
-    if (!strftime(tempString, MAX_TIME_STRING_LENGTH, "%Y/%m/%d,%H:%M:%S", tmTime)) {
+
+    // Converts psTime to YYYY-MM-DDThh:mm:ss.sss in string form
+    if (!strftime(tempString, MAX_TIME_STRING_LENGTH, "%Y-%m-%dT%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) {
+    if (snprintf(timeString, MAX_TIME_STRING_LENGTH, "%s.%3.3dZ", tempString, ms) < 0) {
         psError(__func__, " : Line %d - Failed snprintf conversion", __LINE__);
     }
@@ -207,73 +312,23 @@
 }
 
-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 psTimeToTimeval(psTime *time)
 {
     struct timeval timevalTime;
 
-    CHECK_NEGATIVE_TIME_STRUCT(time, timevalTime);
-    timevalTime.tv_sec = time.tv_sec;
-    timevalTime.tv_usec = time.tv_usec;
+    // NULL error check
+    CHECK_NULL_TIME(time,timevalTime);
+
+    timevalTime.tv_sec = time->sec;
+    timevalTime.tv_usec = time->usec;
 
     return timevalTime;
 }
 
-struct tm *psTimeToTM(psTime time)
+struct tm* psTimeToTM(psTime *time)
 {
     struct tm *tmTime = NULL;
     time_t sec;
 
-    CHECK_NEGATIVE_TIME_STRUCT(time, tmTime);
-    sec = time.tv_sec;
+    sec = time->sec;
     tmTime = gmtime(&sec);
 
@@ -281,5 +336,49 @@
 }
 
-psTime psISOToTime(char *time)
+psTime* psJDToTime(double time)
+{
+    double days = 0.0;
+    double seconds = 0.0;
+    psTime *outTime = NULL;
+
+    // Allocate psTime struct
+    ALLOC_TIME(outTime);
+
+    // Julian date conversion courtesy of Eugene Magnier
+    days = time - 2440587.5;
+    seconds = days * SEC_PER_DAY;
+    if(seconds < 0.0) {
+        outTime->usec = (seconds - (long)seconds) * -1000000.0;  // psTime earlier than epoch
+    } else {
+        outTime->usec = (seconds - (long)seconds) * 1000000.0;   // psTime greater than epoch
+    }
+    outTime->sec = seconds;
+
+    return outTime;
+}
+
+psTime* psMJDToTime(double time)
+{
+    double days = 0.0;
+    double seconds = 0.0;
+    psTime *outTime = NULL;
+
+    // Allocate psTime struct
+    ALLOC_TIME(outTime);
+
+    // Modified Julian date conversion courtesy of Eugene Magnier
+    days = time - 40587.0;
+    seconds = days * SEC_PER_DAY;
+    if(seconds < 0.0) {
+        outTime->usec = (seconds - (long)seconds) * -1000000.0;  // psTime earlier than epoch
+    } else {
+        outTime->usec = (seconds - (long)seconds) * 1000000.0;   // psTime greater than epoch
+    }
+    outTime->sec = seconds;
+
+    return outTime;
+}
+
+psTime* psISOToTime(char *time)
 {
     char tempString[MAX_TIME_STRING_LENGTH];
@@ -292,16 +391,17 @@
     int millisecond;
     struct tm tmTime;
-    psTime outTime;
-
+    psTime *outTime = NULL;
+
+    // Preserve input string by creating duplicate
     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 < 1900) {
-        psError(__func__, "Years less than 1900 not allowed. Value: %d", year);
-        return outTime;
-    }
-
-    month = atoi(strtok(NULL, "/"));
+    // Convert YYYY-MM-DDThh:mm:ss.sss in string form to tm time
+    year = atoi(strtok(tempString, "-"));
+    if (year < 0) {
+        psError(__func__, "Years less than 0 not allowed. Value: %d", year);
+        return outTime;
+    }
+
+    month = atoi(strtok(NULL, "-"));
     if (month < 1 || month > 12) {
         psError(__func__, "Month must have a value from 1 to 12. Value: %d", month);
@@ -309,5 +409,5 @@
     }
 
-    day = atoi(strtok(NULL, ","));
+    day = atoi(strtok(NULL, "T"));
     if (day < 1 || day > 31) {
         psError(__func__, "Day must have a value from 1 to 31. Value: %d", day);
@@ -333,5 +433,5 @@
     }
 
-    millisecond = atoi(strtok(NULL, "X"));
+    millisecond = atoi(strtok(NULL, "Z"));
     if (millisecond < 0 || millisecond > 1000) {
         psError(__func__, "Millisecond must have a value from 0 to 999. Value: %d", millisecond);
@@ -347,164 +447,136 @@
     tmTime.tm_isdst = -1;
 
+    // Allocate psTime struct
+    ALLOC_TIME(outTime)
+
     // 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][1];
-    outTime.tv_usec = time.tv_usec;
-    CHECK_NEGATIVE_TIME_STRUCT(outTime, outTime);
-
-    return outTime;
-}
-
-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 n;
-    int y;
-    int mon[] = {
-                    31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
-                };
-    long epoch;
-    psTime outTime;
-
-    i = 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. Value: %d", time->tm_year + 1900);
-        return outTime;
-    } else if (time->tm_mon < 0 || time->tm_mon > 11)
-    {
-        psError(__func__, "Month must have a value from 0 to 11. Value: %d", time->tm_mon);
-        return outTime;
-    } else if (time->tm_mday < 1 || time->tm_mday > 31)
-    {
-        psError(__func__, "Day must have a value from 1 to 31. Value: %d", time->tm_mday);
-        return outTime;
-    } else if (time->tm_hour < 0 || time->tm_hour > 23)
-    {
-        psError(__func__, "Hour must have a value from 0 to 23. Value: %d", time->tm_hour);
-        return outTime;
-    } else if (time->tm_min < 0 || time->tm_min > 59)
-    {
-        psError(__func__, "Minute must have a value from 0 to 59. Value: %d", time->tm_min);
-        return outTime;
-    } else if (time->tm_sec < 0 || time->tm_sec > 59)
-    {
-        psError(__func__, "Second must have a value from 0 to 59. Value: %d", time->tm_sec);
-        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;
-
-    // Adjust for leap years
-    for (i = 0; i < time->tm_mon; i++)
-    {
-        epoch += mon[i] * SEC_PER_DAY;
-        if (i == 1 && y % 4 == 0 && (y % 100 != 0 || y % 400 == 0)) {
-            epoch += SEC_PER_DAY;
-        }
-    }
-
-    // Add everything
-    epoch += (time->tm_mday - 1) * SEC_PER_DAY;
-    epoch += time->tm_hour * SEC_PER_HOUR + time->tm_min * SEC_PER_MINUTE + time->tm_sec;
-
-    // Create psTime
-    outTime.tv_usec = 0;
-    outTime.tv_sec = epoch;
-
-    CHECK_NEGATIVE_TIME_STRUCT(outTime, outTime);
-
-    return outTime;
-}
+    outTime->usec = millisecond * 1000;
+
+    return outTime;
+}
+
+psTime* psTimevalToTime(struct timeval *time)
+{
+    psTime *outTime = NULL;
+
+    // NULL error check
+    CHECK_NULL_TIME(time,NULL);
+
+    // Allocate psTime struct
+    ALLOC_TIME(outTime);
+
+    // Convert to psTime
+    outTime->sec = time->tv_sec;
+    outTime->usec = time->tv_usec;
+
+    return outTime;
+}
+
+psTime* psTMToTime(struct tm* time)
+{
+    time_t localTimeInSeconds = 0;
+    time_t temp = 0;
+    struct tm *localTMTime = NULL;
+    psTime *outTime = NULL;
+
+    // NULL error check
+    CHECK_NULL_TIME(time,NULL);
+
+    // Allocate psTime struct
+    ALLOC_TIME(outTime);
+
+    // The mktime function returns seconds since last epoch in local time, so get local time and offset
+    localTimeInSeconds = mktime(time);
+    localTMTime = localtime(&temp);
+
+    // Convert to psTime
+    outTime->usec = 0;
+    outTime->sec = localTMTime->tm_gmtoff + localTimeInSeconds;
+
+    return outTime;
+}
+
+psTime* psTAIAdd(psTime *tai1, psTime *tai2)
+{
+    psTime *outTime = NULL;
+
+    if(tai1->type != PS_TIME_TAI) {
+        psError(__func__, " : Line %d - First argument is not PS_TIME_TAI type. Type: %d", __LINE__, tai1->type);
+        return NULL;
+    }
+
+    if(tai2->type != PS_TIME_TAI) {
+        psError(__func__, " : Line %d - Second argument is not PS_TIME_TAI type. Type: %d", __LINE__, tai2->type);
+        return NULL;
+    }
+
+    ALLOC_TIME(outTime);
+
+    outTime->sec = tai1->sec + tai2->sec;
+    outTime->usec = tai1->usec + tai2->usec;
+
+    // Increment seconds in case of microsecond overflow after addition
+    if(outTime->usec<tai1->usec || outTime->usec<tai2->usec) {
+        outTime->sec++;
+    }
+
+    return outTime;
+}
+
+psTime* psTAISub(psTime *tai1, psTime *tai2)
+{
+    psTime *outTime = NULL;
+
+    if(tai1->type != PS_TIME_TAI) {
+        psError(__func__, " : Line %d - First argument is not PS_TIME_TAI type. Type: %d", __LINE__, tai1->type);
+        return NULL;
+    }
+
+    if(tai2->type != PS_TIME_TAI) {
+        psError(__func__, " : Line %d - Second argument is not PS_TIME_TAI type. Type: %d", __LINE__, tai2->type);
+        return NULL;
+    }
+
+    ALLOC_TIME(outTime);
+
+    outTime->sec = tai1->sec - tai2->sec;
+    outTime->usec = tai1->usec - tai2->usec;
+
+    // Decrement seconds in case of microsecond underflow after subtraction
+    if(outTime->usec>tai1->usec || outTime->usec>tai2->usec) {
+        outTime->sec--;
+    }
+
+    return outTime;
+}
+
+psTime* psTAIDelta(psTime *tai1, psTime *tai2)
+{
+    psTime *outTime = NULL;
+
+    if(tai1->type != PS_TIME_TAI) {
+        psError(__func__, " : Line %d - First argument is not PS_TIME_TAI type. Type: %d", __LINE__, tai1->type);
+        return NULL;
+    }
+
+    if(tai2->type != PS_TIME_TAI) {
+        psError(__func__, " : Line %d - Second argument is not PS_TIME_TAI type. Type: %d", __LINE__, tai2->type);
+        return NULL;
+    }
+
+    ALLOC_TIME(outTime);
+
+    outTime->sec = tai1->sec - tai2->sec;
+    outTime->usec = tai1->usec - tai2->usec;
+
+    // Decrement seconds in case of microsecond underflow after subtraction
+    if(outTime->usec>tai1->usec || outTime->usec>tai2->usec) {
+        outTime->sec--;
+    }
+
+    outTime->sec = abs(outTime->sec);
+
+
+    return outTime;
+}
Index: /trunk/psLib/src/astro/psTime.h
===================================================================
--- /trunk/psLib/src/astro/psTime.h	(revision 1613)
+++ /trunk/psLib/src/astro/psTime.h	(revision 1614)
@@ -1,3 +1,2 @@
-
 /** @file  psTime.h
  *
@@ -7,12 +6,54 @@
  *  A collection of functions are required by psLib to manipulate time data. These functions primarily consist
  *  of conversions between specific time formats.  PSLib currently uses the UNIX timeval time system as the
- *  base upon which International Atomic Time (TAI) time is calculated. All time conversion functions within
- *  psLib, except those noted, are calculated in terms of TAI time, which is approxinmately 32 seconds faster
- *  than UTC/timeval.
+ *  base upon which International Atomic Time (TAI) and Universal Time Coordinated (UTC) are calculated. TAI
+ *  time varies over time due to the earth's rotation and the movement of the continental plates. It is
+ *  currentls 32 seconds faster than UTC/timeval time. The conversion between TAI and UTC time for other dates
+ *  is given in the table below, which comes from:
+ *
+ *  ftp://maia.usno.navy.mil/ser7/tai-utc.dat
+ *
+ *  This table is placed into a static array and used by the psTime functions for conversions.
+ *
+ *   1961 JAN  1 =JD 2437300.5  TAI-UTC=   1.4228180 S + (MJD - 37300.) X 0.001296 S
+ *   1961 AUG  1 =JD 2437512.5  TAI-UTC=   1.3728180 S + (MJD - 37300.) X 0.001296 S
+ *   1962 JAN  1 =JD 2437665.5  TAI-UTC=   1.8458580 S + (MJD - 37665.) X 0.0011232S
+ *   1963 NOV  1 =JD 2438334.5  TAI-UTC=   1.9458580 S + (MJD - 37665.) X 0.0011232S
+ *   1964 JAN  1 =JD 2438395.5  TAI-UTC=   3.2401300 S + (MJD - 38761.) X 0.001296 S
+ *   1964 APR  1 =JD 2438486.5  TAI-UTC=   3.3401300 S + (MJD - 38761.) X 0.001296 S
+ *   1964 SEP  1 =JD 2438639.5  TAI-UTC=   3.4401300 S + (MJD - 38761.) X 0.001296 S
+ *   1965 JAN  1 =JD 2438761.5  TAI-UTC=   3.5401300 S + (MJD - 38761.) X 0.001296 S
+ *   1965 MAR  1 =JD 2438820.5  TAI-UTC=   3.6401300 S + (MJD - 38761.) X 0.001296 S
+ *   1965 JUL  1 =JD 2438942.5  TAI-UTC=   3.7401300 S + (MJD - 38761.) X 0.001296 S
+ *   1965 SEP  1 =JD 2439004.5  TAI-UTC=   3.8401300 S + (MJD - 38761.) X 0.001296 S
+ *   1966 JAN  1 =JD 2439126.5  TAI-UTC=   4.3131700 S + (MJD - 39126.) X 0.002592 S
+ *   1968 FEB  1 =JD 2439887.5  TAI-UTC=   4.2131700 S + (MJD - 39126.) X 0.002592 S
+ *   1972 JAN  1 =JD 2441317.5  TAI-UTC=  10.0       S + (MJD - 41317.) X 0.0      S
+ *   1972 JUL  1 =JD 2441499.5  TAI-UTC=  11.0       S + (MJD - 41317.) X 0.0      S
+ *   1973 JAN  1 =JD 2441683.5  TAI-UTC=  12.0       S + (MJD - 41317.) X 0.0      S
+ *   1974 JAN  1 =JD 2442048.5  TAI-UTC=  13.0       S + (MJD - 41317.) X 0.0      S
+ *   1975 JAN  1 =JD 2442413.5  TAI-UTC=  14.0       S + (MJD - 41317.) X 0.0      S
+ *   1976 JAN  1 =JD 2442778.5  TAI-UTC=  15.0       S + (MJD - 41317.) X 0.0      S
+ *   1977 JAN  1 =JD 2443144.5  TAI-UTC=  16.0       S + (MJD - 41317.) X 0.0      S
+ *   1978 JAN  1 =JD 2443509.5  TAI-UTC=  17.0       S + (MJD - 41317.) X 0.0      S
+ *   1979 JAN  1 =JD 2443874.5  TAI-UTC=  18.0       S + (MJD - 41317.) X 0.0      S
+ *   1980 JAN  1 =JD 2444239.5  TAI-UTC=  19.0       S + (MJD - 41317.) X 0.0      S
+ *   1981 JUL  1 =JD 2444786.5  TAI-UTC=  20.0       S + (MJD - 41317.) X 0.0      S
+ *   1982 JUL  1 =JD 2445151.5  TAI-UTC=  21.0       S + (MJD - 41317.) X 0.0      S
+ *   1983 JUL  1 =JD 2445516.5  TAI-UTC=  22.0       S + (MJD - 41317.) X 0.0      S
+ *   1985 JUL  1 =JD 2446247.5  TAI-UTC=  23.0       S + (MJD - 41317.) X 0.0      S
+ *   1988 JAN  1 =JD 2447161.5  TAI-UTC=  24.0       S + (MJD - 41317.) X 0.0      S
+ *   1990 JAN  1 =JD 2447892.5  TAI-UTC=  25.0       S + (MJD - 41317.) X 0.0      S
+ *   1991 JAN  1 =JD 2448257.5  TAI-UTC=  26.0       S + (MJD - 41317.) X 0.0      S
+ *   1992 JUL  1 =JD 2448804.5  TAI-UTC=  27.0       S + (MJD - 41317.) X 0.0      S
+ *   1993 JUL  1 =JD 2449169.5  TAI-UTC=  28.0       S + (MJD - 41317.) X 0.0      S
+ *   1994 JUL  1 =JD 2449534.5  TAI-UTC=  29.0       S + (MJD - 41317.) X 0.0      S
+ *   1996 JAN  1 =JD 2450083.5  TAI-UTC=  30.0       S + (MJD - 41317.) X 0.0      S
+ *   1997 JUL  1 =JD 2450630.5  TAI-UTC=  31.0       S + (MJD - 41317.) X 0.0      S
+ *   1999 JAN  1 =JD 2451179.5  TAI-UTC=  32.0       S + (MJD - 41317.) X 0.0      S
  *
  *  @author Ross Harman, MHPCC
  *
- *  @version $Revision: 1.12 $ $Name: not supported by cvs2svn $
- *  @date $Date: 2004-08-13 22:08:51 $
+ *  @version $Revision: 1.13 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2004-08-25 01:37:45 $
  *
  *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
@@ -31,172 +72,238 @@
 /// @{
 
-/******************************************************************************/
-
-/*  TYPE DEFINITIONS                                                          */
-
-/******************************************************************************/
+
+/** Time type.
+ *
+ * Enumeration for psTime types, TAI or UTC time.
+ */
+typedef enum {
+    PS_TIME_TAI,        ///< Temps Atomique International (TAI) time (time with leapseconds).
+    PS_TIME_UTC,        ///< Universal Time Coordinated (UTC) time (time without leapseconds).
+} psTimeType;
 
 /** Definition of psTime.
  *
- *  The psTime struct is used by psLib to represent time values critical to 
- *  astronomical calculations.  This structure represents a time which is 
- *  equivalent to TAI (International Atomic Time) and is measured in both 
+ *  The psTime struct is used by psLib to represent time values critical to
+ *  astronomical calculations.  This structure represents a time which is
+ *  equivalent to TAI (International Atomic Time) and is measured in both
  *  seconds and microseconds.
  */
-typedef struct timeval psTime;
-
-/*****************************************************************************/
-
-/* FUNCTION PROTOTYPES                                                       */
-
-/*****************************************************************************/
-
-/** Get current TAI time.
- *
- * Gets current time from the system clock in correct TAI units.
- *
- *  @return  psTime: Struct with current time.
- */
-
-psTime psTimeGetTime(void);
-
-/** Convert psTime to ISO time in TAI units.
- *
- *  Converts psTime to a null terminated string in the form of: 
- *  YYYY/MM/DD,HH:MM:SS.SSS. This function assumes the input time already is 
- *  in TAI time and does not add or subtract leapseconds.
+typedef struct psTime
+{
+    psS64 sec;          ///< Seconds since epoch, Jan 1, 1970.
+    psU32 usec;         ///< Microseconds since last second.
+    psTimeType type;    ///< Type of time.
+}
+psTime;
+
+/** Get current time.
+ *
+ * Gets current time from the system clock. User must specify the psTimeType (PS_TIME_TAI or PS_TIME_UTC) in
+ * the argument.
+ *
+ *  @return  psTime*: Struct with current time.
+ */
+psTime* psTimeGetTime(
+    psTimeType type     ///< Type of time to get (UTC or TAI).
+);
+
+
+/** Convert psTime to UTC or TAI time.
+ *
+ *  Converts psTime to UTC or TAI time based on the psTimeType argument.
+ *
+ *  @return  psTime*: Pointer to psTime.
+ */
+psTime* psTimeConvert(
+    psTime *time,
+    psTimeType type
+);
+
+/** Convert psTime to Local Mean Sidereal Time (LST).
+ *
+ *  Converts psTime at the given longitude to LST time. If the input time is not in UTC format, then it is
+ *  converted.
+ *
+ *  @return  double: LST Time.
+ */
+double psTimeToLST(
+    psTime *time,       ///< psTime to be converted.
+    double longitude    ///< Longitude.
+);
+
+/** Convert Local Mean Sidereal Time (LST) to psTime.
+ *
+ *  Converts LST time to psTime.
+ *
+ *  @return  psTime*: Pointer to psTime.
+ */
+psTime* psLSTToTime(
+    double time,       ///< LST time to be converted.
+    double longitude   ///< Longitude.
+);
+
+/** Determine UT1 - UTC from table lookup.
+ *
+ *  This function is necessary to for various SLALIB functions.
+ *
+ *  @return  double: Time difference.
+ */
+double psGetUT1Delta(
+    psTime *time      ///< psTime to be looked up.
+);
+
+/** Determine TAI - UTC from table lookup.
+ *
+ *  This function is necessary to for various psTime functions.
+ *
+ *  @return  double: Time difference.
+ */
+double psGetTAIDelta(
+    psTime *time      ///< psTime to be looked up.
+);
+
+/** Determine polar coordinates at a given time.
+ *
+ *  Determines the orientation of the polar axis at the given time.
+ *
+ *  @return  psSphere*: Spherical coordinates of Earth's polar axias.
+ */
+/*psSphere* psGetPoleCoords(
+    psTime *time      ///< psTime determine polar orientation.
+);*/
+
+/** Convert psTime to Julian date time.
+ *
+ *  Converts psTime to Julian date (JD) time. This function does not add or subtract leapseconds.
+ *
+ *  @return  double: Julian Date (JD) time.
+ */
+double psTimeToJD(
+    psTime *time                        ///< Input time to be converted.
+);
+/** Convert psTime to modified Julian date time.
+ *
+ *  Converts psTime to modified Julian date (MJD) time. This function does not add or subtract leapseconds.
+ *
+ *  @return  double: Modified Julian Days (MJD) time.
+ */
+double psTimeToMJD(
+    psTime *time                        ///< Input time to be converted.
+);
+
+/** Convert psTime to ISO8601 formatted string.
+ *
+ *  Converts psTime to a null terminated string in the form of YYYY-MM-DDThh:mm:ss.sss. This function does not
+ *  add or subtract leapseconds.
  *
  *  @return  char*: Pointer null terminated array of chars in ISO time.
  */
-
-char *psTimeToISO(
-    psTime time                        ///< Input time to be converted.
-);
-
-/** Convert psTime to UTC time.
- *
- *  Converts psTime to UTC time in double precision floating point notation. 
- *  The input to this must already be int TAI time. The result from this 
- *  function is not in TAI units, but that of UTC, which does not contain
- *  leapseconds.
- *
- *  @return  psTime: UTC time psTime format.
- */
-
-psTime psTimeToUTC(
-    psTime time                        ///< Input time to be converted.
-);
-
-/** Convert psTime to modified Julian date time.
- *
- *  Converts psTime to modified Julian date (MJD) time. This function assumes 
- *  the input time already is in TAI time and does not add or subtract 
- *  leapseconds.
- *
- *  @return  double: Modified Julian Days (MJD) time.
- */
-double psTimeToMJD(
-    psTime time                        ///< Input time to be converted.
-);
-
-/** Convert psTime to Julian date time.
- *
- *  Converts psTime to Julian date (JD) time. This function assumes the input 
- *  time already is in TAI time and does not add or subtract leapseconds.
- *
- *  @return  double: Julian Date (JD) time.
- */
-double psTimeToJD(
-    psTime time                        ///< Input time to be converted.
+char* psTimeToISO(
+    psTime *time                        ///< Input time to be converted.
 );
 
 /** Convert psTime to timeval time.
  *
- *  Converts psTime to timeval time. This function assumes the input time 
- *  already is in TAI time and does not add or subtract leapseconds.
+ *  Converts psTime to timeval time. This function does not add or subtract leapseconds.
  *
  *  @return  timeval: timeval struct time.
  */
 struct timeval psTimeToTimeval(
-                psTime time                        ///< Input time to be converted.
+                psTime *time                        ///< Input time to be converted.
             );
 
 /** Convert psTime to tm time.
  *
- * Converts psTime to tm time. This function assumes the input time already is in TAI time and does not add or
- * subtract leapseconds.
+ * Converts psTime to tm time. This function does not add or subtract leapseconds.
  *
  *  @return  tm: tm struct time.
  */
-struct tm *psTimeToTM(
-                psTime time                        ///< Input time to be converted.
+struct tm* psTimeToTM(
+                psTime *time                        ///< Input time to be converted.
             );
 
+/** Convert JD to psTime.
+ *
+ *  Converts JD time to psTime. This function does not add or subtract leapseconds.
+ *
+ *  @return  psTime: time.
+ */
+psTime* psJDToTime(
+    double time                         ///< Input time to be converted.
+);
+
+/** Convert MJD to psTime.
+ *
+ *  Converts MJD time to psTime. This function does not add or subtract leapseconds.
+ *
+ *  @return  psTime: time.
+ */
+psTime* psMJDToTime(
+    double time                         ///< Input time to be converted.
+);
+
 /** Convert ISO to psTime.
  *
- *  Converts ISO time to psTime. This function assumes the input time already 
- *  is in TAI time and does not add or subtract leapseconds.
- *
- *  @return  psTime: time
- */
-psTime psISOToTime(
+ *  Converts ISO time to psTime. This function does not add or subtract leapseconds.
+ *
+ *  @return  psTime*: time
+ */
+psTime* psISOToTime(
     char *time                         ///< Input time to be converted.
 );
 
-/** Convert UTC to psTime.
- *
- *  Converts UTC time to psTime. This function assumes the input time already 
- *  is in TAI time and add or subtracts the necessary leapseconds.
- *
- *  @return  psTime: time in TAI units.
- */
-psTime psUTCToTime(
-    psTime time                        ///< Input time to be converted.
-);
-
-/** Convert MJD to psTime.
- *
- *  Converts MJD time to psTime. This function assumes the input time already 
- *  is in TAI time and does not add or subtract leapseconds.
- *
- *  @return  psTime: time.
- */
-psTime psMJDToTime(
-    double time                        ///< Input time to be converted.
-);
-
-/** Convert JD to psTime.
- *
- *  Converts JD time to psTime. This function assumes the input time already 
- *  is in TAI time and does not add or subtract leapseconds.
- *
- *  @return  psTime: time.
- */
-psTime psJDToTime(
-    double time                        ///< Input time to be converted.
-);
-
 /** Convert timeval to psTime.
  *
- *  Converts timeval time to psTime. This function assumes the input time 
- *  already is in TAI time and does not add or subtract leapseconds.
- *
- *  @return  psTime: time.
- */
-psTime psTimevalToTime(
-    struct timeval *time               ///< Input time to be converted.
+ *  Converts timeval time to psTime. This function does not add or subtract leapseconds.
+ *
+ *  @return  psTime*: time.
+ */
+psTime* psTimevalToTime(
+    struct timeval *time                ///< Input time to be converted.
 );
 
 /** Convert tm time to psTime.
  *
- *  Converts tm time to psTime. This function assumes the input time already 
- *  is in TAI time and does not add or subtract leapseconds.
- *
- *  @return  psTime: time.
- */
-psTime psTMToTime(
+ *  Converts tm time to psTime. This function does not add or subtract leapseconds.
+ *
+ *  @return  psTime*: time.
+ */
+psTime* psTMToTime(
     struct tm *time                    ///< Input time to be converted.
 );
 
+/** Add two TAI times.
+ *
+ *  Adds two TAI times. This function does not add or subtract leapseconds.
+ *
+ *  @return  psTime*: time.
+ */
+psTime* psTAIAdd(
+    psTime *tai1,                    ///< First TAI time.
+    psTime *tai2                     ///< Second TAI time.
+);
+
+/** Subtract two TAI times.
+ *
+ *  Subtracts two TAI times. This function does not add or subtract leapseconds.
+ *
+ *  @return  psTime*: time.
+ */
+psTime* psTAISub(
+    psTime *tai1,                    ///< First TAI time.
+    psTime *tai2                     ///< Second TAI time.
+);
+
+
+/** Find delta of two TAI times.
+ *
+ *  Finds the absolute difference of two TAI times. This function does not add or subtract leapseconds.
+ *
+ *  @return  psTime*: time.
+ */
+psTime* psTAIDelta(
+    psTime *tai1,                    ///< First TAI time.
+    psTime *tai2                     ///< Second TAI time.
+);
 /// @}
 
Index: /trunk/psLib/src/astronomy/psTime.c
===================================================================
--- /trunk/psLib/src/astronomy/psTime.c	(revision 1613)
+++ /trunk/psLib/src/astronomy/psTime.c	(revision 1614)
@@ -1,3 +1,2 @@
-
 /** @file  psTime.c
  *
@@ -7,12 +6,54 @@
  *  A collection of functions are required by psLib to manipulate time data. These functions primarily consist
  *  of conversions between specific time formats.  PSLib currently uses the UNIX timeval time system as the
- *  base upon which International Atomic Time (TAI) time is calculated. TAI time varies over time due to the
- *  earth's rotation and the movement of the continental plates. It is currentls 32 seconds faster than
- *  UTC/timeval time.
+ *  base upon which International Atomic Time (TAI) and Universal Time Coordinated (UTC) are calculated. TAI
+ *  time varies over time due to the earth's rotation and the movement of the continental plates. It is
+ *  currentls 32 seconds faster than UTC/timeval time. The conversion between TAI and UTC time for other dates
+ *  is given in the table below, which comes from:
+ *
+ *  ftp://maia.usno.navy.mil/ser7/tai-utc.dat
+ *
+ *  This table is placed into a static array and used by the psTime functions for conversions.
+ *
+ *   1961 JAN  1 =JD 2437300.5  TAI-UTC=   1.4228180 S + (MJD - 37300.) X 0.001296 S
+ *   1961 AUG  1 =JD 2437512.5  TAI-UTC=   1.3728180 S + (MJD - 37300.) X 0.001296 S
+ *   1962 JAN  1 =JD 2437665.5  TAI-UTC=   1.8458580 S + (MJD - 37665.) X 0.0011232S
+ *   1963 NOV  1 =JD 2438334.5  TAI-UTC=   1.9458580 S + (MJD - 37665.) X 0.0011232S
+ *   1964 JAN  1 =JD 2438395.5  TAI-UTC=   3.2401300 S + (MJD - 38761.) X 0.001296 S
+ *   1964 APR  1 =JD 2438486.5  TAI-UTC=   3.3401300 S + (MJD - 38761.) X 0.001296 S
+ *   1964 SEP  1 =JD 2438639.5  TAI-UTC=   3.4401300 S + (MJD - 38761.) X 0.001296 S
+ *   1965 JAN  1 =JD 2438761.5  TAI-UTC=   3.5401300 S + (MJD - 38761.) X 0.001296 S
+ *   1965 MAR  1 =JD 2438820.5  TAI-UTC=   3.6401300 S + (MJD - 38761.) X 0.001296 S
+ *   1965 JUL  1 =JD 2438942.5  TAI-UTC=   3.7401300 S + (MJD - 38761.) X 0.001296 S
+ *   1965 SEP  1 =JD 2439004.5  TAI-UTC=   3.8401300 S + (MJD - 38761.) X 0.001296 S
+ *   1966 JAN  1 =JD 2439126.5  TAI-UTC=   4.3131700 S + (MJD - 39126.) X 0.002592 S
+ *   1968 FEB  1 =JD 2439887.5  TAI-UTC=   4.2131700 S + (MJD - 39126.) X 0.002592 S
+ *   1972 JAN  1 =JD 2441317.5  TAI-UTC=  10.0       S + (MJD - 41317.) X 0.0      S
+ *   1972 JUL  1 =JD 2441499.5  TAI-UTC=  11.0       S + (MJD - 41317.) X 0.0      S
+ *   1973 JAN  1 =JD 2441683.5  TAI-UTC=  12.0       S + (MJD - 41317.) X 0.0      S
+ *   1974 JAN  1 =JD 2442048.5  TAI-UTC=  13.0       S + (MJD - 41317.) X 0.0      S
+ *   1975 JAN  1 =JD 2442413.5  TAI-UTC=  14.0       S + (MJD - 41317.) X 0.0      S
+ *   1976 JAN  1 =JD 2442778.5  TAI-UTC=  15.0       S + (MJD - 41317.) X 0.0      S
+ *   1977 JAN  1 =JD 2443144.5  TAI-UTC=  16.0       S + (MJD - 41317.) X 0.0      S
+ *   1978 JAN  1 =JD 2443509.5  TAI-UTC=  17.0       S + (MJD - 41317.) X 0.0      S
+ *   1979 JAN  1 =JD 2443874.5  TAI-UTC=  18.0       S + (MJD - 41317.) X 0.0      S
+ *   1980 JAN  1 =JD 2444239.5  TAI-UTC=  19.0       S + (MJD - 41317.) X 0.0      S
+ *   1981 JUL  1 =JD 2444786.5  TAI-UTC=  20.0       S + (MJD - 41317.) X 0.0      S
+ *   1982 JUL  1 =JD 2445151.5  TAI-UTC=  21.0       S + (MJD - 41317.) X 0.0      S
+ *   1983 JUL  1 =JD 2445516.5  TAI-UTC=  22.0       S + (MJD - 41317.) X 0.0      S
+ *   1985 JUL  1 =JD 2446247.5  TAI-UTC=  23.0       S + (MJD - 41317.) X 0.0      S
+ *   1988 JAN  1 =JD 2447161.5  TAI-UTC=  24.0       S + (MJD - 41317.) X 0.0      S
+ *   1990 JAN  1 =JD 2447892.5  TAI-UTC=  25.0       S + (MJD - 41317.) X 0.0      S
+ *   1991 JAN  1 =JD 2448257.5  TAI-UTC=  26.0       S + (MJD - 41317.) X 0.0      S
+ *   1992 JUL  1 =JD 2448804.5  TAI-UTC=  27.0       S + (MJD - 41317.) X 0.0      S
+ *   1993 JUL  1 =JD 2449169.5  TAI-UTC=  28.0       S + (MJD - 41317.) X 0.0      S
+ *   1994 JUL  1 =JD 2449534.5  TAI-UTC=  29.0       S + (MJD - 41317.) X 0.0      S
+ *   1996 JAN  1 =JD 2450083.5  TAI-UTC=  30.0       S + (MJD - 41317.) X 0.0      S
+ *   1997 JUL  1 =JD 2450630.5  TAI-UTC=  31.0       S + (MJD - 41317.) X 0.0      S
+ *   1999 JAN  1 =JD 2451179.5  TAI-UTC=  32.0       S + (MJD - 41317.) X 0.0      S
  *
  *  @author Ross Harman, MHPCC
  *
- *  @version $Revision: 1.20 $ $Name: not supported by cvs2svn $
- *  @date $Date: 2004-08-19 18:57:49 $
+ *  @version $Revision: 1.21 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2004-08-25 01:37:34 $
  *
  *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
@@ -26,42 +67,9 @@
 #include "psError.h"
 #include "psMemory.h"
-
-/******************************************************************************/
-/*  DEFINE STATEMENTS                                                         */
-/******************************************************************************/
-/******************************************************************************/
-/*  DEFINE STATEMENTS                                                         */
-/******************************************************************************/
-
-// None
-
-/******************************************************************************/
-/*  TYPE DEFINITIONS                                                          */
-/******************************************************************************/
-
-// None
-
-/*****************************************************************************/
-/*  GLOBAL VARIABLES                                                         */
-/*****************************************************************************/
-
-// None
-
-/*****************************************************************************/
-/*  FILE STATIC VARIABLES                                                    */
-/*****************************************************************************/
-
-// None
-
-/*****************************************************************************/
-/*  FUNCTION IMPLEMENTATION - LOCAL                                          */
-/*****************************************************************************/
-
-/******************************************************************************/
-/*  DEFINE STATEMENTS                                                         */
-/******************************************************************************/
+#include "psAbort.h"
+
 
 /** Number of available leapsecond updates */
-#define NUM_LEAPSECOND_UPDATES 23
+#define NUM_UPDATES 36
 
 /** Maximum length of time string */
@@ -83,98 +91,193 @@
 #define USEC_PER_DAY 86400000000.0
 
-/** 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);                                  \
+/** Preprocessor macro to check for null psTime struct */
+#define CHECK_NULL_TIME(TIME,RETURN)                                                                         \
+if(TIME == NULL) {                                                                                           \
+    psError(__func__,"NULL value not allowed");                                                              \
     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;                                                                                           \
-}                                                                                                            \
-
-/* The table below comes from http://tycho.usno.navy.mil/leapsec.html, which reports the current state of
-the TAI/UTC leapsecond conversion times. This table is placed into a two dimensional array and used by
-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
+}
+
+/** Preprocessor macro to allocate psTime strict */
+#define ALLOC_TIME(TIME)                                                                                     \
+TIME = (psTime*)psAlloc(sizeof(psTime));                                                                 \
+if (TIME == NULL) {                                                                                      \
+    psAbort(__func__, " : Line %d - Failed to allocate memory", __LINE__);                               \
+}
+
+/*
+ The table below comes from ftp://maia.usno.navy.mil/ser7/tai-utc.dat, which reports the current state of
+ the TAI/UTC leapsecond conversion times.
 */
-static double leapseconds[NUM_LEAPSECOND_UPDATES][2] = {
-            {2441317.5, 10.0},
-            {2441499.5, 11.0},
-            {2441683.5, 12.0},
-            {2442048.5, 13.0},
-            {2442413.5, 14.0},
-            {2442778.5, 15.0},
-            {2443144.5, 16.0},
-            {2443509.5, 17.0},
-            {2443874.5, 18.0},
-            {2444239.5, 19.0},
-            {2444786.5, 20.0},
-            {2445151.5, 21.0},
-            {2445516.5, 22.0},
-            {2446247.5, 23.0},
-            {2447161.5, 24.0},
-            {2447892.5, 25.0},
-            {2448257.5, 26.0},
-            {2448804.5, 27.0},
-            {2449169.5, 28.0},
-            {2449534.5, 29.0},
-            {2450083.5, 30.0},
-            {2450630.5, 31.0},
-            {2451179.5, 32.0}
-        };
-
-psTime psTimeGetTime(void)
+static double lsTable[NUM_UPDATES][4] = {
+                                            {2437300.5,  1.422818, 37300.0, 0.0012960},
+                                            {2437512.5,  1.372818, 37300.0, 0.0012960},
+                                            {2437665.5,  1.845858, 37665.0, 0.0011232},
+                                            {2438334.5,  1.945858, 37665.0, 0.0011232},
+                                            {2438395.5,  3.240130, 38761.0, 0.0012960},
+                                            {2438486.5,  3.340130, 38761.0, 0.0012960},
+                                            {2438639.5,  3.440130, 38761.0, 0.0012960},
+                                            {2438761.5,  3.540130, 38761.0, 0.0012960},
+                                            {2438820.5,  3.640130, 38761.0, 0.0012960},
+                                            {2438942.5,  3.740130, 38761.0, 0.0012960},
+                                            {2439004.5,  3.840130, 38761.0, 0.0012960},
+                                            {2439126.5,  4.313170, 39126.0, 0.0025920},
+                                            {2439887.5,  4.213170, 39126.0, 0.0025920},
+                                            {2441317.5, 10.000000, 41317.0, 0.0000000},
+                                            {2441499.5, 11.000000, 41317.0, 0.0000000},
+                                            {2441683.5, 12.000000, 41317.0, 0.0000000},
+                                            {2442048.5, 13.000000, 41317.0, 0.0000000},
+                                            {2442413.5, 14.000000, 41317.0, 0.0000000},
+                                            {2442778.5, 15.000000, 41317.0, 0.0000000},
+                                            {2443144.5, 16.000000, 41317.0, 0.0000000},
+                                            {2443509.5, 17.000000, 41317.0, 0.0000000},
+                                            {2443874.5, 18.000000, 41317.0, 0.0000000},
+                                            {2444239.5, 19.000000, 41317.0, 0.0000000},
+                                            {2444786.5, 20.000000, 41317.0, 0.0000000},
+                                            {2445151.5, 21.000000, 41317.0, 0.0000000},
+                                            {2445516.5, 22.000000, 41317.0, 0.0000000},
+                                            {2446247.5, 23.000000, 41317.0, 0.0000000},
+                                            {2447161.5, 24.000000, 41317.0, 0.0000000},
+                                            {2447892.5, 25.000000, 41317.0, 0.0000000},
+                                            {2448257.5, 26.000000, 41317.0, 0.0000000},
+                                            {2448804.5, 27.000000, 41317.0, 0.0000000},
+                                            {2449169.5, 28.000000, 41317.0, 0.0000000},
+                                            {2449534.5, 29.000000, 41317.0, 0.0000000},
+                                            {2450083.5, 30.000000, 41317.0, 0.0000000},
+                                            {2450630.5, 31.000000, 41317.0, 0.0000000},
+                                            {2451179.5, 32.000000, 41317.0, 0.0000000}
+                                        };
+
+
+psTime* psTimeGetTime(psTimeType type)
 {
     struct timeval now;
-    psTime time;
-
-    time.tv_sec = 0;
-    time.tv_usec = 0;
+    psTime *time = NULL;
+
+    // Allocate psTime struct
+    ALLOC_TIME(time);
 
     if (gettimeofday(&now, (struct timezone *)0) == -1) {
         psError(__func__, " : Line %d - Failed to get time", __LINE__);
-        return time;
-    }
+        return NULL;
+    }
+
     // Convert timeval time to psTime
-    time.tv_sec = now.tv_sec;
-    time.tv_usec = now.tv_usec;
-
-    // Add most current leapseconds value to UTC time to get TAI time
-    time.tv_sec += leapseconds[NUM_LEAPSECOND_UPDATES - 1][1];
+    time->sec = now.tv_sec;
+    time->usec = now.tv_usec;
+    time->type = type;
+
+    // Add most leapseconds to UTC time to get TAI time if necessary
+    if(type == PS_TIME_TAI) {
+        time->sec += psGetTAIDelta(time);
+    }
 
     return time;
 }
 
-char *psTimeToISO(psTime time)
+psTime* psTimeConvert(psTime *time, psTimeType type)
+{
+    double delta = 0.0;
+
+    if(time->type == type) {
+        psError(__func__, " : Line %d - Time is already in the correct psTime format. Time type: %d", __LINE__, type);
+        return NULL;
+    }
+
+    delta = psGetTAIDelta(time);
+
+    if(type == PS_TIME_UTC) {
+        time->sec = time->sec - delta;    // User wants UTC time. Remove leapseconds.
+    } else if(type == PS_TIME_TAI) {
+        time->sec = time->sec + delta;    // User wants TAI time. Add leapseconds.
+    } else {
+        psError(__func__, " : Line %d - Invalid psTimeType: %d", __LINE__, type);
+    }
+
+    return time;
+}
+
+double psTimeToLST(psTime *time, double longitude)
+{
+    double delta = 0;
+
+    return delta;
+}
+
+psTime* psLSTToTime(double time, double longitude)
+{
+    psTime *outTime = NULL;
+
+    return outTime;
+}
+
+double psGetUT1Delta(psTime *time)
+{
+    double delta = 0;
+
+    return delta;
+}
+
+double psGetTAIDelta(psTime *time)
+{
+    int i = 0;
+    double delta = 0.0;
+    double jd = 0.0;
+    double mjd = 0.0;
+
+    // Determine Julian and modified Julian dates used in table lookup and time delta calculation
+    jd = psTimeToJD(time);
+    mjd = psTimeToMJD(time);
+
+    // Perform table lookup
+    if(jd < lsTable[0][1]) {                        // Times earlier than 1961
+        delta = 0.0;
+    } else if(jd > lsTable[NUM_UPDATES-1][1]) {      // Times greater than latest table entry
+        delta = lsTable[NUM_UPDATES-1][1] + (mjd - lsTable[NUM_UPDATES-1][2]) * lsTable[NUM_UPDATES-1][3];
+    } else {                                        // All other times
+        for (i = 0; i<NUM_UPDATES-1; i++) {
+            if (jd>lsTable[i][0] && jd<lsTable[i+1][0]) {
+                delta = lsTable[i][1] + (mjd - lsTable[i][2]) * lsTable[i][3];
+            }
+        }
+    }
+
+    return delta;
+}
+
+double psTimeToJD(psTime *time)
+{
+    double jd = 0.0;
+
+    // NULL error check
+    CHECK_NULL_TIME(time,0.0);
+
+    // Julian date conversion courtesy of Eugene Magnier
+    if(time->sec < 0) {
+        jd = time->sec / SEC_PER_DAY - time->usec / USEC_PER_DAY + 2440587.5; // psTime earlier than epoch
+    } else {
+        jd = time->sec / SEC_PER_DAY + time->usec / USEC_PER_DAY + 2440587.5; // psTime greater than epoch
+    }
+
+    return jd;
+}
+
+double psTimeToMJD(psTime *time)
+{
+    double mjd = 0.0;
+
+    // NULL error check
+    CHECK_NULL_TIME(time,0.0);
+
+    // Modified Julian date conversion courtesy of Eugene Magnier
+    if(time->sec < 0) {
+        mjd = time->sec / SEC_PER_DAY - time->usec / USEC_PER_DAY + 40587.0; // psTime earlier than epoch
+    } else {
+        mjd = time->sec / SEC_PER_DAY + time->usec / USEC_PER_DAY + 40587.0; // psTime greater than epoch
+    }
+
+    return mjd;
+}
+
+char* psTimeToISO(psTime *time)
 {
     int ms = 0;
@@ -184,20 +287,22 @@
     time_t sec;
 
-    CHECK_NEGATIVE_TIME_STRUCT(time, NULL);
+    // NULL error check
+    CHECK_NULL_TIME(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;
-
-    sec = time.tv_sec;
+    ms = time->usec / 1000;
+    sec = time->sec;
+
     // tmTime variable is statically allocated, no need to free
     tmTime = gmtime(&sec);
-    if (!strftime(tempString, MAX_TIME_STRING_LENGTH, "%Y/%m/%d,%H:%M:%S", tmTime)) {
+
+    // Converts psTime to YYYY-MM-DDThh:mm:ss.sss in string form
+    if (!strftime(tempString, MAX_TIME_STRING_LENGTH, "%Y-%m-%dT%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) {
+    if (snprintf(timeString, MAX_TIME_STRING_LENGTH, "%s.%3.3dZ", tempString, ms) < 0) {
         psError(__func__, " : Line %d - Failed snprintf conversion", __LINE__);
     }
@@ -207,73 +312,23 @@
 }
 
-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 psTimeToTimeval(psTime *time)
 {
     struct timeval timevalTime;
 
-    CHECK_NEGATIVE_TIME_STRUCT(time, timevalTime);
-    timevalTime.tv_sec = time.tv_sec;
-    timevalTime.tv_usec = time.tv_usec;
+    // NULL error check
+    CHECK_NULL_TIME(time,timevalTime);
+
+    timevalTime.tv_sec = time->sec;
+    timevalTime.tv_usec = time->usec;
 
     return timevalTime;
 }
 
-struct tm *psTimeToTM(psTime time)
+struct tm* psTimeToTM(psTime *time)
 {
     struct tm *tmTime = NULL;
     time_t sec;
 
-    CHECK_NEGATIVE_TIME_STRUCT(time, tmTime);
-    sec = time.tv_sec;
+    sec = time->sec;
     tmTime = gmtime(&sec);
 
@@ -281,5 +336,49 @@
 }
 
-psTime psISOToTime(char *time)
+psTime* psJDToTime(double time)
+{
+    double days = 0.0;
+    double seconds = 0.0;
+    psTime *outTime = NULL;
+
+    // Allocate psTime struct
+    ALLOC_TIME(outTime);
+
+    // Julian date conversion courtesy of Eugene Magnier
+    days = time - 2440587.5;
+    seconds = days * SEC_PER_DAY;
+    if(seconds < 0.0) {
+        outTime->usec = (seconds - (long)seconds) * -1000000.0;  // psTime earlier than epoch
+    } else {
+        outTime->usec = (seconds - (long)seconds) * 1000000.0;   // psTime greater than epoch
+    }
+    outTime->sec = seconds;
+
+    return outTime;
+}
+
+psTime* psMJDToTime(double time)
+{
+    double days = 0.0;
+    double seconds = 0.0;
+    psTime *outTime = NULL;
+
+    // Allocate psTime struct
+    ALLOC_TIME(outTime);
+
+    // Modified Julian date conversion courtesy of Eugene Magnier
+    days = time - 40587.0;
+    seconds = days * SEC_PER_DAY;
+    if(seconds < 0.0) {
+        outTime->usec = (seconds - (long)seconds) * -1000000.0;  // psTime earlier than epoch
+    } else {
+        outTime->usec = (seconds - (long)seconds) * 1000000.0;   // psTime greater than epoch
+    }
+    outTime->sec = seconds;
+
+    return outTime;
+}
+
+psTime* psISOToTime(char *time)
 {
     char tempString[MAX_TIME_STRING_LENGTH];
@@ -292,16 +391,17 @@
     int millisecond;
     struct tm tmTime;
-    psTime outTime;
-
+    psTime *outTime = NULL;
+
+    // Preserve input string by creating duplicate
     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 < 1900) {
-        psError(__func__, "Years less than 1900 not allowed. Value: %d", year);
-        return outTime;
-    }
-
-    month = atoi(strtok(NULL, "/"));
+    // Convert YYYY-MM-DDThh:mm:ss.sss in string form to tm time
+    year = atoi(strtok(tempString, "-"));
+    if (year < 0) {
+        psError(__func__, "Years less than 0 not allowed. Value: %d", year);
+        return outTime;
+    }
+
+    month = atoi(strtok(NULL, "-"));
     if (month < 1 || month > 12) {
         psError(__func__, "Month must have a value from 1 to 12. Value: %d", month);
@@ -309,5 +409,5 @@
     }
 
-    day = atoi(strtok(NULL, ","));
+    day = atoi(strtok(NULL, "T"));
     if (day < 1 || day > 31) {
         psError(__func__, "Day must have a value from 1 to 31. Value: %d", day);
@@ -333,5 +433,5 @@
     }
 
-    millisecond = atoi(strtok(NULL, "X"));
+    millisecond = atoi(strtok(NULL, "Z"));
     if (millisecond < 0 || millisecond > 1000) {
         psError(__func__, "Millisecond must have a value from 0 to 999. Value: %d", millisecond);
@@ -347,164 +447,136 @@
     tmTime.tm_isdst = -1;
 
+    // Allocate psTime struct
+    ALLOC_TIME(outTime)
+
     // 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][1];
-    outTime.tv_usec = time.tv_usec;
-    CHECK_NEGATIVE_TIME_STRUCT(outTime, outTime);
-
-    return outTime;
-}
-
-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 n;
-    int y;
-    int mon[] = {
-                    31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
-                };
-    long epoch;
-    psTime outTime;
-
-    i = 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. Value: %d", time->tm_year + 1900);
-        return outTime;
-    } else if (time->tm_mon < 0 || time->tm_mon > 11)
-    {
-        psError(__func__, "Month must have a value from 0 to 11. Value: %d", time->tm_mon);
-        return outTime;
-    } else if (time->tm_mday < 1 || time->tm_mday > 31)
-    {
-        psError(__func__, "Day must have a value from 1 to 31. Value: %d", time->tm_mday);
-        return outTime;
-    } else if (time->tm_hour < 0 || time->tm_hour > 23)
-    {
-        psError(__func__, "Hour must have a value from 0 to 23. Value: %d", time->tm_hour);
-        return outTime;
-    } else if (time->tm_min < 0 || time->tm_min > 59)
-    {
-        psError(__func__, "Minute must have a value from 0 to 59. Value: %d", time->tm_min);
-        return outTime;
-    } else if (time->tm_sec < 0 || time->tm_sec > 59)
-    {
-        psError(__func__, "Second must have a value from 0 to 59. Value: %d", time->tm_sec);
-        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;
-
-    // Adjust for leap years
-    for (i = 0; i < time->tm_mon; i++)
-    {
-        epoch += mon[i] * SEC_PER_DAY;
-        if (i == 1 && y % 4 == 0 && (y % 100 != 0 || y % 400 == 0)) {
-            epoch += SEC_PER_DAY;
-        }
-    }
-
-    // Add everything
-    epoch += (time->tm_mday - 1) * SEC_PER_DAY;
-    epoch += time->tm_hour * SEC_PER_HOUR + time->tm_min * SEC_PER_MINUTE + time->tm_sec;
-
-    // Create psTime
-    outTime.tv_usec = 0;
-    outTime.tv_sec = epoch;
-
-    CHECK_NEGATIVE_TIME_STRUCT(outTime, outTime);
-
-    return outTime;
-}
+    outTime->usec = millisecond * 1000;
+
+    return outTime;
+}
+
+psTime* psTimevalToTime(struct timeval *time)
+{
+    psTime *outTime = NULL;
+
+    // NULL error check
+    CHECK_NULL_TIME(time,NULL);
+
+    // Allocate psTime struct
+    ALLOC_TIME(outTime);
+
+    // Convert to psTime
+    outTime->sec = time->tv_sec;
+    outTime->usec = time->tv_usec;
+
+    return outTime;
+}
+
+psTime* psTMToTime(struct tm* time)
+{
+    time_t localTimeInSeconds = 0;
+    time_t temp = 0;
+    struct tm *localTMTime = NULL;
+    psTime *outTime = NULL;
+
+    // NULL error check
+    CHECK_NULL_TIME(time,NULL);
+
+    // Allocate psTime struct
+    ALLOC_TIME(outTime);
+
+    // The mktime function returns seconds since last epoch in local time, so get local time and offset
+    localTimeInSeconds = mktime(time);
+    localTMTime = localtime(&temp);
+
+    // Convert to psTime
+    outTime->usec = 0;
+    outTime->sec = localTMTime->tm_gmtoff + localTimeInSeconds;
+
+    return outTime;
+}
+
+psTime* psTAIAdd(psTime *tai1, psTime *tai2)
+{
+    psTime *outTime = NULL;
+
+    if(tai1->type != PS_TIME_TAI) {
+        psError(__func__, " : Line %d - First argument is not PS_TIME_TAI type. Type: %d", __LINE__, tai1->type);
+        return NULL;
+    }
+
+    if(tai2->type != PS_TIME_TAI) {
+        psError(__func__, " : Line %d - Second argument is not PS_TIME_TAI type. Type: %d", __LINE__, tai2->type);
+        return NULL;
+    }
+
+    ALLOC_TIME(outTime);
+
+    outTime->sec = tai1->sec + tai2->sec;
+    outTime->usec = tai1->usec + tai2->usec;
+
+    // Increment seconds in case of microsecond overflow after addition
+    if(outTime->usec<tai1->usec || outTime->usec<tai2->usec) {
+        outTime->sec++;
+    }
+
+    return outTime;
+}
+
+psTime* psTAISub(psTime *tai1, psTime *tai2)
+{
+    psTime *outTime = NULL;
+
+    if(tai1->type != PS_TIME_TAI) {
+        psError(__func__, " : Line %d - First argument is not PS_TIME_TAI type. Type: %d", __LINE__, tai1->type);
+        return NULL;
+    }
+
+    if(tai2->type != PS_TIME_TAI) {
+        psError(__func__, " : Line %d - Second argument is not PS_TIME_TAI type. Type: %d", __LINE__, tai2->type);
+        return NULL;
+    }
+
+    ALLOC_TIME(outTime);
+
+    outTime->sec = tai1->sec - tai2->sec;
+    outTime->usec = tai1->usec - tai2->usec;
+
+    // Decrement seconds in case of microsecond underflow after subtraction
+    if(outTime->usec>tai1->usec || outTime->usec>tai2->usec) {
+        outTime->sec--;
+    }
+
+    return outTime;
+}
+
+psTime* psTAIDelta(psTime *tai1, psTime *tai2)
+{
+    psTime *outTime = NULL;
+
+    if(tai1->type != PS_TIME_TAI) {
+        psError(__func__, " : Line %d - First argument is not PS_TIME_TAI type. Type: %d", __LINE__, tai1->type);
+        return NULL;
+    }
+
+    if(tai2->type != PS_TIME_TAI) {
+        psError(__func__, " : Line %d - Second argument is not PS_TIME_TAI type. Type: %d", __LINE__, tai2->type);
+        return NULL;
+    }
+
+    ALLOC_TIME(outTime);
+
+    outTime->sec = tai1->sec - tai2->sec;
+    outTime->usec = tai1->usec - tai2->usec;
+
+    // Decrement seconds in case of microsecond underflow after subtraction
+    if(outTime->usec>tai1->usec || outTime->usec>tai2->usec) {
+        outTime->sec--;
+    }
+
+    outTime->sec = abs(outTime->sec);
+
+
+    return outTime;
+}
Index: /trunk/psLib/src/astronomy/psTime.h
===================================================================
--- /trunk/psLib/src/astronomy/psTime.h	(revision 1613)
+++ /trunk/psLib/src/astronomy/psTime.h	(revision 1614)
@@ -1,3 +1,2 @@
-
 /** @file  psTime.h
  *
@@ -7,12 +6,54 @@
  *  A collection of functions are required by psLib to manipulate time data. These functions primarily consist
  *  of conversions between specific time formats.  PSLib currently uses the UNIX timeval time system as the
- *  base upon which International Atomic Time (TAI) time is calculated. All time conversion functions within
- *  psLib, except those noted, are calculated in terms of TAI time, which is approxinmately 32 seconds faster
- *  than UTC/timeval.
+ *  base upon which International Atomic Time (TAI) and Universal Time Coordinated (UTC) are calculated. TAI
+ *  time varies over time due to the earth's rotation and the movement of the continental plates. It is
+ *  currentls 32 seconds faster than UTC/timeval time. The conversion between TAI and UTC time for other dates
+ *  is given in the table below, which comes from:
+ *
+ *  ftp://maia.usno.navy.mil/ser7/tai-utc.dat
+ *
+ *  This table is placed into a static array and used by the psTime functions for conversions.
+ *
+ *   1961 JAN  1 =JD 2437300.5  TAI-UTC=   1.4228180 S + (MJD - 37300.) X 0.001296 S
+ *   1961 AUG  1 =JD 2437512.5  TAI-UTC=   1.3728180 S + (MJD - 37300.) X 0.001296 S
+ *   1962 JAN  1 =JD 2437665.5  TAI-UTC=   1.8458580 S + (MJD - 37665.) X 0.0011232S
+ *   1963 NOV  1 =JD 2438334.5  TAI-UTC=   1.9458580 S + (MJD - 37665.) X 0.0011232S
+ *   1964 JAN  1 =JD 2438395.5  TAI-UTC=   3.2401300 S + (MJD - 38761.) X 0.001296 S
+ *   1964 APR  1 =JD 2438486.5  TAI-UTC=   3.3401300 S + (MJD - 38761.) X 0.001296 S
+ *   1964 SEP  1 =JD 2438639.5  TAI-UTC=   3.4401300 S + (MJD - 38761.) X 0.001296 S
+ *   1965 JAN  1 =JD 2438761.5  TAI-UTC=   3.5401300 S + (MJD - 38761.) X 0.001296 S
+ *   1965 MAR  1 =JD 2438820.5  TAI-UTC=   3.6401300 S + (MJD - 38761.) X 0.001296 S
+ *   1965 JUL  1 =JD 2438942.5  TAI-UTC=   3.7401300 S + (MJD - 38761.) X 0.001296 S
+ *   1965 SEP  1 =JD 2439004.5  TAI-UTC=   3.8401300 S + (MJD - 38761.) X 0.001296 S
+ *   1966 JAN  1 =JD 2439126.5  TAI-UTC=   4.3131700 S + (MJD - 39126.) X 0.002592 S
+ *   1968 FEB  1 =JD 2439887.5  TAI-UTC=   4.2131700 S + (MJD - 39126.) X 0.002592 S
+ *   1972 JAN  1 =JD 2441317.5  TAI-UTC=  10.0       S + (MJD - 41317.) X 0.0      S
+ *   1972 JUL  1 =JD 2441499.5  TAI-UTC=  11.0       S + (MJD - 41317.) X 0.0      S
+ *   1973 JAN  1 =JD 2441683.5  TAI-UTC=  12.0       S + (MJD - 41317.) X 0.0      S
+ *   1974 JAN  1 =JD 2442048.5  TAI-UTC=  13.0       S + (MJD - 41317.) X 0.0      S
+ *   1975 JAN  1 =JD 2442413.5  TAI-UTC=  14.0       S + (MJD - 41317.) X 0.0      S
+ *   1976 JAN  1 =JD 2442778.5  TAI-UTC=  15.0       S + (MJD - 41317.) X 0.0      S
+ *   1977 JAN  1 =JD 2443144.5  TAI-UTC=  16.0       S + (MJD - 41317.) X 0.0      S
+ *   1978 JAN  1 =JD 2443509.5  TAI-UTC=  17.0       S + (MJD - 41317.) X 0.0      S
+ *   1979 JAN  1 =JD 2443874.5  TAI-UTC=  18.0       S + (MJD - 41317.) X 0.0      S
+ *   1980 JAN  1 =JD 2444239.5  TAI-UTC=  19.0       S + (MJD - 41317.) X 0.0      S
+ *   1981 JUL  1 =JD 2444786.5  TAI-UTC=  20.0       S + (MJD - 41317.) X 0.0      S
+ *   1982 JUL  1 =JD 2445151.5  TAI-UTC=  21.0       S + (MJD - 41317.) X 0.0      S
+ *   1983 JUL  1 =JD 2445516.5  TAI-UTC=  22.0       S + (MJD - 41317.) X 0.0      S
+ *   1985 JUL  1 =JD 2446247.5  TAI-UTC=  23.0       S + (MJD - 41317.) X 0.0      S
+ *   1988 JAN  1 =JD 2447161.5  TAI-UTC=  24.0       S + (MJD - 41317.) X 0.0      S
+ *   1990 JAN  1 =JD 2447892.5  TAI-UTC=  25.0       S + (MJD - 41317.) X 0.0      S
+ *   1991 JAN  1 =JD 2448257.5  TAI-UTC=  26.0       S + (MJD - 41317.) X 0.0      S
+ *   1992 JUL  1 =JD 2448804.5  TAI-UTC=  27.0       S + (MJD - 41317.) X 0.0      S
+ *   1993 JUL  1 =JD 2449169.5  TAI-UTC=  28.0       S + (MJD - 41317.) X 0.0      S
+ *   1994 JUL  1 =JD 2449534.5  TAI-UTC=  29.0       S + (MJD - 41317.) X 0.0      S
+ *   1996 JAN  1 =JD 2450083.5  TAI-UTC=  30.0       S + (MJD - 41317.) X 0.0      S
+ *   1997 JUL  1 =JD 2450630.5  TAI-UTC=  31.0       S + (MJD - 41317.) X 0.0      S
+ *   1999 JAN  1 =JD 2451179.5  TAI-UTC=  32.0       S + (MJD - 41317.) X 0.0      S
  *
  *  @author Ross Harman, MHPCC
  *
- *  @version $Revision: 1.12 $ $Name: not supported by cvs2svn $
- *  @date $Date: 2004-08-13 22:08:51 $
+ *  @version $Revision: 1.13 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2004-08-25 01:37:45 $
  *
  *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
@@ -31,172 +72,238 @@
 /// @{
 
-/******************************************************************************/
-
-/*  TYPE DEFINITIONS                                                          */
-
-/******************************************************************************/
+
+/** Time type.
+ *
+ * Enumeration for psTime types, TAI or UTC time.
+ */
+typedef enum {
+    PS_TIME_TAI,        ///< Temps Atomique International (TAI) time (time with leapseconds).
+    PS_TIME_UTC,        ///< Universal Time Coordinated (UTC) time (time without leapseconds).
+} psTimeType;
 
 /** Definition of psTime.
  *
- *  The psTime struct is used by psLib to represent time values critical to 
- *  astronomical calculations.  This structure represents a time which is 
- *  equivalent to TAI (International Atomic Time) and is measured in both 
+ *  The psTime struct is used by psLib to represent time values critical to
+ *  astronomical calculations.  This structure represents a time which is
+ *  equivalent to TAI (International Atomic Time) and is measured in both
  *  seconds and microseconds.
  */
-typedef struct timeval psTime;
-
-/*****************************************************************************/
-
-/* FUNCTION PROTOTYPES                                                       */
-
-/*****************************************************************************/
-
-/** Get current TAI time.
- *
- * Gets current time from the system clock in correct TAI units.
- *
- *  @return  psTime: Struct with current time.
- */
-
-psTime psTimeGetTime(void);
-
-/** Convert psTime to ISO time in TAI units.
- *
- *  Converts psTime to a null terminated string in the form of: 
- *  YYYY/MM/DD,HH:MM:SS.SSS. This function assumes the input time already is 
- *  in TAI time and does not add or subtract leapseconds.
+typedef struct psTime
+{
+    psS64 sec;          ///< Seconds since epoch, Jan 1, 1970.
+    psU32 usec;         ///< Microseconds since last second.
+    psTimeType type;    ///< Type of time.
+}
+psTime;
+
+/** Get current time.
+ *
+ * Gets current time from the system clock. User must specify the psTimeType (PS_TIME_TAI or PS_TIME_UTC) in
+ * the argument.
+ *
+ *  @return  psTime*: Struct with current time.
+ */
+psTime* psTimeGetTime(
+    psTimeType type     ///< Type of time to get (UTC or TAI).
+);
+
+
+/** Convert psTime to UTC or TAI time.
+ *
+ *  Converts psTime to UTC or TAI time based on the psTimeType argument.
+ *
+ *  @return  psTime*: Pointer to psTime.
+ */
+psTime* psTimeConvert(
+    psTime *time,
+    psTimeType type
+);
+
+/** Convert psTime to Local Mean Sidereal Time (LST).
+ *
+ *  Converts psTime at the given longitude to LST time. If the input time is not in UTC format, then it is
+ *  converted.
+ *
+ *  @return  double: LST Time.
+ */
+double psTimeToLST(
+    psTime *time,       ///< psTime to be converted.
+    double longitude    ///< Longitude.
+);
+
+/** Convert Local Mean Sidereal Time (LST) to psTime.
+ *
+ *  Converts LST time to psTime.
+ *
+ *  @return  psTime*: Pointer to psTime.
+ */
+psTime* psLSTToTime(
+    double time,       ///< LST time to be converted.
+    double longitude   ///< Longitude.
+);
+
+/** Determine UT1 - UTC from table lookup.
+ *
+ *  This function is necessary to for various SLALIB functions.
+ *
+ *  @return  double: Time difference.
+ */
+double psGetUT1Delta(
+    psTime *time      ///< psTime to be looked up.
+);
+
+/** Determine TAI - UTC from table lookup.
+ *
+ *  This function is necessary to for various psTime functions.
+ *
+ *  @return  double: Time difference.
+ */
+double psGetTAIDelta(
+    psTime *time      ///< psTime to be looked up.
+);
+
+/** Determine polar coordinates at a given time.
+ *
+ *  Determines the orientation of the polar axis at the given time.
+ *
+ *  @return  psSphere*: Spherical coordinates of Earth's polar axias.
+ */
+/*psSphere* psGetPoleCoords(
+    psTime *time      ///< psTime determine polar orientation.
+);*/
+
+/** Convert psTime to Julian date time.
+ *
+ *  Converts psTime to Julian date (JD) time. This function does not add or subtract leapseconds.
+ *
+ *  @return  double: Julian Date (JD) time.
+ */
+double psTimeToJD(
+    psTime *time                        ///< Input time to be converted.
+);
+/** Convert psTime to modified Julian date time.
+ *
+ *  Converts psTime to modified Julian date (MJD) time. This function does not add or subtract leapseconds.
+ *
+ *  @return  double: Modified Julian Days (MJD) time.
+ */
+double psTimeToMJD(
+    psTime *time                        ///< Input time to be converted.
+);
+
+/** Convert psTime to ISO8601 formatted string.
+ *
+ *  Converts psTime to a null terminated string in the form of YYYY-MM-DDThh:mm:ss.sss. This function does not
+ *  add or subtract leapseconds.
  *
  *  @return  char*: Pointer null terminated array of chars in ISO time.
  */
-
-char *psTimeToISO(
-    psTime time                        ///< Input time to be converted.
-);
-
-/** Convert psTime to UTC time.
- *
- *  Converts psTime to UTC time in double precision floating point notation. 
- *  The input to this must already be int TAI time. The result from this 
- *  function is not in TAI units, but that of UTC, which does not contain
- *  leapseconds.
- *
- *  @return  psTime: UTC time psTime format.
- */
-
-psTime psTimeToUTC(
-    psTime time                        ///< Input time to be converted.
-);
-
-/** Convert psTime to modified Julian date time.
- *
- *  Converts psTime to modified Julian date (MJD) time. This function assumes 
- *  the input time already is in TAI time and does not add or subtract 
- *  leapseconds.
- *
- *  @return  double: Modified Julian Days (MJD) time.
- */
-double psTimeToMJD(
-    psTime time                        ///< Input time to be converted.
-);
-
-/** Convert psTime to Julian date time.
- *
- *  Converts psTime to Julian date (JD) time. This function assumes the input 
- *  time already is in TAI time and does not add or subtract leapseconds.
- *
- *  @return  double: Julian Date (JD) time.
- */
-double psTimeToJD(
-    psTime time                        ///< Input time to be converted.
+char* psTimeToISO(
+    psTime *time                        ///< Input time to be converted.
 );
 
 /** Convert psTime to timeval time.
  *
- *  Converts psTime to timeval time. This function assumes the input time 
- *  already is in TAI time and does not add or subtract leapseconds.
+ *  Converts psTime to timeval time. This function does not add or subtract leapseconds.
  *
  *  @return  timeval: timeval struct time.
  */
 struct timeval psTimeToTimeval(
-                psTime time                        ///< Input time to be converted.
+                psTime *time                        ///< Input time to be converted.
             );
 
 /** Convert psTime to tm time.
  *
- * Converts psTime to tm time. This function assumes the input time already is in TAI time and does not add or
- * subtract leapseconds.
+ * Converts psTime to tm time. This function does not add or subtract leapseconds.
  *
  *  @return  tm: tm struct time.
  */
-struct tm *psTimeToTM(
-                psTime time                        ///< Input time to be converted.
+struct tm* psTimeToTM(
+                psTime *time                        ///< Input time to be converted.
             );
 
+/** Convert JD to psTime.
+ *
+ *  Converts JD time to psTime. This function does not add or subtract leapseconds.
+ *
+ *  @return  psTime: time.
+ */
+psTime* psJDToTime(
+    double time                         ///< Input time to be converted.
+);
+
+/** Convert MJD to psTime.
+ *
+ *  Converts MJD time to psTime. This function does not add or subtract leapseconds.
+ *
+ *  @return  psTime: time.
+ */
+psTime* psMJDToTime(
+    double time                         ///< Input time to be converted.
+);
+
 /** Convert ISO to psTime.
  *
- *  Converts ISO time to psTime. This function assumes the input time already 
- *  is in TAI time and does not add or subtract leapseconds.
- *
- *  @return  psTime: time
- */
-psTime psISOToTime(
+ *  Converts ISO time to psTime. This function does not add or subtract leapseconds.
+ *
+ *  @return  psTime*: time
+ */
+psTime* psISOToTime(
     char *time                         ///< Input time to be converted.
 );
 
-/** Convert UTC to psTime.
- *
- *  Converts UTC time to psTime. This function assumes the input time already 
- *  is in TAI time and add or subtracts the necessary leapseconds.
- *
- *  @return  psTime: time in TAI units.
- */
-psTime psUTCToTime(
-    psTime time                        ///< Input time to be converted.
-);
-
-/** Convert MJD to psTime.
- *
- *  Converts MJD time to psTime. This function assumes the input time already 
- *  is in TAI time and does not add or subtract leapseconds.
- *
- *  @return  psTime: time.
- */
-psTime psMJDToTime(
-    double time                        ///< Input time to be converted.
-);
-
-/** Convert JD to psTime.
- *
- *  Converts JD time to psTime. This function assumes the input time already 
- *  is in TAI time and does not add or subtract leapseconds.
- *
- *  @return  psTime: time.
- */
-psTime psJDToTime(
-    double time                        ///< Input time to be converted.
-);
-
 /** Convert timeval to psTime.
  *
- *  Converts timeval time to psTime. This function assumes the input time 
- *  already is in TAI time and does not add or subtract leapseconds.
- *
- *  @return  psTime: time.
- */
-psTime psTimevalToTime(
-    struct timeval *time               ///< Input time to be converted.
+ *  Converts timeval time to psTime. This function does not add or subtract leapseconds.
+ *
+ *  @return  psTime*: time.
+ */
+psTime* psTimevalToTime(
+    struct timeval *time                ///< Input time to be converted.
 );
 
 /** Convert tm time to psTime.
  *
- *  Converts tm time to psTime. This function assumes the input time already 
- *  is in TAI time and does not add or subtract leapseconds.
- *
- *  @return  psTime: time.
- */
-psTime psTMToTime(
+ *  Converts tm time to psTime. This function does not add or subtract leapseconds.
+ *
+ *  @return  psTime*: time.
+ */
+psTime* psTMToTime(
     struct tm *time                    ///< Input time to be converted.
 );
 
+/** Add two TAI times.
+ *
+ *  Adds two TAI times. This function does not add or subtract leapseconds.
+ *
+ *  @return  psTime*: time.
+ */
+psTime* psTAIAdd(
+    psTime *tai1,                    ///< First TAI time.
+    psTime *tai2                     ///< Second TAI time.
+);
+
+/** Subtract two TAI times.
+ *
+ *  Subtracts two TAI times. This function does not add or subtract leapseconds.
+ *
+ *  @return  psTime*: time.
+ */
+psTime* psTAISub(
+    psTime *tai1,                    ///< First TAI time.
+    psTime *tai2                     ///< Second TAI time.
+);
+
+
+/** Find delta of two TAI times.
+ *
+ *  Finds the absolute difference of two TAI times. This function does not add or subtract leapseconds.
+ *
+ *  @return  psTime*: time.
+ */
+psTime* psTAIDelta(
+    psTime *tai1,                    ///< First TAI time.
+    psTime *tai2                     ///< Second TAI time.
+);
 /// @}
 
