/************************************************************************/
/*									*/
/*	time_funct.c							*/
/*									*/
/*	Copyright (c) 1997 by Chris Albertson.  			*/
/*	This program is licensed under terms of the GNU GPL.  See the	*/
/*	file "COPYING".							*/
/*									*/
/*	The algorithm used here was supplied by George wm Turner	*/
/*	turner@bigbang.astro.indiana.edu  USA+ 812 855 6911		*/
/*									*/
/************************************************************************/

char time_funct_rcsid[] = 
	"$Id: time_funct.c,v 1.2 1998/08/04 05:08:47 chris Exp $";

#include <sys/time.h> 
#include <time.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <math.h>

#include "MLog.h"


/* Define this here.  Seems to be missing from my RH5.0 system */
#define DST_NONE 0


/************************************************************************/
/*									*/
/*  getJD								*/
/*									*/
/*  Purpose:								*/
/*	Get currnt JD as a double precision floating point number.	*/
/*									*/
/*	The algorithm used here was supplied by George wm Turner	*/
/*	turner@bigbang.astro.indiana.edu  USA+ 812 855 6911		*/
/*									*/
/************************************************************************/
double getJD(void)
{
    struct timeval	curtime;
    struct timezone	gmtz;
    double		sec;
    double		secs_in_day = 60.0*60.0*24.0;
    int                 res;
    

    /* Set up tz struct with GMT offset, zero  and no daylight savings 	*/
    /* time to be applied.						*/
    gmtz.tz_minuteswest = 0;
    gmtz.tz_dsttime	= DST_NONE;

    /* Get seconds from epoch in the GMT timezone.  Compute floating 	*/
    /* point seconds.							*/
    res = gettimeofday(&curtime,&gmtz);
    if (res < 0)
    {
        /* ERROR gettimeofday failed */
        ml_printf(ML_MANDATORY, ML_ERROR,
            "ERROR gettimeofday failed %s:%d %s\n",
            __FILE__, __LINE__, strerror(errno));
        return 0.0;
    }
    
    sec = curtime.tv_sec+curtime.tv_usec/1000000.;
    
    /* convert seconds to days and add offset between JD=0 and epoch	*/
    return ((double)(sec/secs_in_day)+2440587.5);
}


/************************************************************************/
/*									*/
/*  ut_seconds								*/
/*									*/
/*  Purpose:								*/
/*	Return the time of day UT in seconds past midnight in a		*/
/*	double precision floating point number.				*/
/*									*/
/************************************************************************/
double ut_seconds(void)
{
    struct timeval      curtime;
    struct timezone     gmtz;
    
    struct tm          *tp;
    time_t              time;
    
    int		        today_sec_I;
    double	        today_sec_D;
    int                 res;
    
    
    /* Set up tz struct with GMT offset, zero  and no daylight savings  */
    /* time to be applied.                                              */
    gmtz.tz_minuteswest = 0;
    gmtz.tz_dsttime     = DST_NONE;

    res = gettimeofday(&curtime,&gmtz);
    if (res < 0)
    {
        /* ERROR gettimeofday failed */
        ml_printf(ML_MANDATORY, ML_ERROR,
            "ERROR gettimeofday failed %s:%d %s\n",
            __FILE__, __LINE__, strerror(errno));
        return 0.0;
    }
    
    
    time = (time_t)curtime.tv_sec;
    tp   = gmtime( &time );
    
    today_sec_I = (tp->tm_sec) + 
                  (tp->tm_min  *   60) +
                  (tp->tm_hour * 3600);
                  
    today_sec_D = (double)today_sec_I + 
                  (double)curtime.tv_usec / 1000000.0;
                
    return today_sec_D;
}

/************************************************************************/
/*                                                                      */
/*  get_epoc                                                            */
/*                                                                      */
/*  Purpose:                                                            */
/*      Returns "seconds from epoc" as a double.  Fractional seconds    */
/*      are only as good as the system clock.                           */
/*      This is the basic measure of time within this server.  The      */
/*      reference point is purposfully meaningless.  Use getJD or       */
/*      ut_seconds if you need to know the absolute time.               */
/*                                                                      */
/************************************************************************/
double get_epoc(void)
{ 
    struct timeval  current_time;
    int             res;
    double          Now;
    
   
    res = gettimeofday(&current_time, NULL);
    if (res < 0)
    {
        /* ERROR gettimeofday failed */
        ml_printf(ML_MANDATORY, ML_ERROR,
            "ERROR gettimeofday failed %s:%d %s\n",
            __FILE__, __LINE__, strerror(errno));
        return 0.0;
    }
    
    Now = (double)current_time.tv_sec + 
          (double)current_time.tv_usec / 1000000.0;
    return Now;
}

void dbl2tv(struct timeval *tv_ptr, double secs)
{
    double  full_secs;
    double  fract_secs;
    
    full_secs  = floor(secs);
    fract_secs = secs - full_secs;
    
    tv_ptr->tv_sec  = (int)full_secs;       
    tv_ptr->tv_usec = (int)(0.5 + (fract_secs * 1000000.0));
}

void tv2dbl(double *secs, struct timeval *tv_ptr)
{
    *secs = (double)(tv_ptr->tv_sec) + 
            (double)(tv_ptr->tv_usec) / 1000000.0;
}
