DD_time.cc 9.5 KB
/* ===================================================================
 * Name          : DD_time.c
 * Version:     : 3.2
 * Author        : Andrey Fedorov 
 * Institution   : IKI RAN, Moscow , CESR, Toulouse
 * Written on    : Tue Feb 21 14:27:10 EET 1995
 * Modified on   :  Oct 5, 2002
 * List of modifications:
 *           Oct 5, 2002: V.3.0, New functions   DD_Time2Double   and  Double2DD_Time
 *                                          were added.
 *           March 26, 2010: V.3.1 YEARS up to 2025
 * 	     Sept 05, 2011: V.3.2  SetIntNew =>  arg TimeKind => to work with 1970-1973 : BR
 *==================================================================*/

#include "DD_time.hh"
#include <stdio.h>
#include <string.h>
#include <stdarg.h>

#define YEARS 70

/*---- Static array of days shift from Jun-1-1970 -------*/
/*                    1970    1971    1972    1973    1974    1975    1976  
 *                    1977    1978    1979    1980    1981    1982    1983
 *                    1984    1985    1986    1987    1988    1989    1990 
 *                    1991    1992    1993    1994    1995    1996    1997
 *                    1998    1999    2000    2001    2002    2003    2004
 *                    2005    2006    2007    2008    2009    2010    2011
 *                    2012    2013    2014    2015    2016    2017    2018
 *                    2019    2020    2021    2022    2023    2024    2025
 *                    2026    2027    2028    2029    2030    2031    2032
 *                    2033    2034    2035    2036    2037    2038    2039
 */
static double
      YearDays[YEARS] = {   0.0,   365.0,   730.0,  1096.0,  1461.0,  1826.0,  2191.0,
                         2557.0,  2922.0,  3287.0,  3652.0,  4018.0,  4383.0,  4748.0,
                         5113.0,  5479.0,  5844.0,  6209.0,  6574.0,  6940.0,  7305.0,
                         7670.0,  8035.0,  8401.0,  8766.0,  9131.0,  9496.0,  9862.0,
                        10227.0, 10592.0, 10957.0, 11323.0, 11688.0, 12053.0, 12418.0,
                        12784.0, 13149.0, 13514.0, 13879.0, 14245.0, 14610.0, 14975.0,
                        15340.0, 15706.0, 16071.0, 16436.0, 16801.0, 17167.0, 17532.0,
                        17897.0, 18262.0, 18628.0, 18993.0, 19358.0, 19723.0, 20089.0,
                        20454.0, 20819.0, 21184.0, 21550.0, 21915.0, 22280.0, 22645.0,
                        23011.0, 23376.0, 23741.0, 24106.0, 24472.0, 24837.0, 25202};

static int monthday[2][12] = 
{
{0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334},
{0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335}
};
/* so, DAY = monthday[*][month-1]+day -1 */

/*================== INTERNAL FUNCTION ====================*/
/*-------------------- SetInt ----------------------------*/
void SetInt(dd_tmstr_t *UT)
{
  SetIntNew(UT,DD_TM_UNKNOWN);
}

void SetIntNew(dd_tmstr_t *UT,t_DDTimeKind timeKind) /* Fill int values of dd_tmstr_t */
/* If the double times field of UT structure is defined,
 * this function fills remains fields of Year, day .... separately
 */
{
   static const double msofday = 24.0*60.0*60.0;
   static const double msofhour = 60.0*60.0;
   static const double msofmin = 60.0;
   long daynumber;
   double msrest;
   int i;

   daynumber = (long)(UT->times / msofday);
   for(i=0;i<YEARS;i++) if(daynumber < (long)YearDays[i]) break;
   i--;

   switch(timeKind)
   {
     case DD_TM_DATE :
     {
       //it's a date
       UT->year = i+1970;
       UT->day = (int)(daynumber - (long)YearDays[i]);
       break;
     }
     case DD_TM_TIME_INTERVAL :
     {
       //it's a time interval
       UT->year = 0;
       UT->day =  (int)(daynumber);
       break;
     }
     default :
       //compatibility mode
       if(i > 3)
       {
         UT->year = i+1970;
         UT->day = (int)(daynumber - (long)YearDays[i]);
       }
       else
       {
         UT->year = 0;
         UT->day =  (int)(daynumber);
       }
       break;
   }

   msrest = UT->times - (double)daynumber * msofday;
   UT->hour = (int)(msrest / msofhour);
   msrest -= (double)(UT->hour)*msofhour;
   UT->min = (int)(msrest / msofmin);
   msrest -= (double)(UT->min)*msofmin;
   UT->sec = (int)(msrest);
   UT->msec = (int)((msrest - (double)(UT->sec))*1000.0);
   return;
}

/*---------------- end of SetInt -----------------------*/

/*-----------------SetDouble ---------------------------*/
void SetDouble(dd_tmstr_t *UT) /* Fill double value of dd_tmstr_t */
/* If indeger fields of UT is defined, You can calculate double
 * field - amount of sec after Jun-1-1970
 */
{
 if(UT->year >= 1970)
 UT->times =          (double)UT->msec/1000.0  +
                      (double)UT->sec +
                      (double)UT->min*60 +
                      (double)UT->hour*60.0*60.0 +
                      (double)UT->day*60.0*60.0*24.0 +
                      YearDays[(UT->year - 1970)]*60.0*60.0*24.0;
 else if(UT->year < YEARS)
 UT->times =            (double)UT->msec/1000.0  +
                        (double)UT->sec +
                        (double)UT->min*60 +
                        (double)UT->hour*60.0*60.0 +
                        (double)UT->day*60.0*60.0*24.0 +
                        YearDays[UT->year]*60.0*60.0*24.0;
 else
 UT->times =            0.0;
 return;
}
/*----------------- end of SetDouble ---------------------*/

/*=================== PUBLIC FUNCTIONS ==================*/
/*-------------------   DD_Time2Double  --------------------*/
double DD_Time2Double(const dd_time_t  UTstring)
{
    dd_tmstr_t UT;
    char year[5] = "0000";
    char  day[4] = "000";
    char   hour[3]= "00";
    char min[3] = "00";
    char  sec[3]= "00";
    char  msec[4] = "000";

   strncpy(year,UTstring,4);
   strncpy(day,UTstring+4,3);
   strncpy(hour,UTstring+7,2);
   strncpy(min,UTstring+9,2);
   strncpy(sec,UTstring+11,2);
   strncpy(msec,UTstring+13,3);

   sscanf(year,"%4d",&(UT.year));
   sscanf(day,"%3d",&(UT.day));
   sscanf(min,"%2d",&(UT.min));
   sscanf(hour,"%2d",&(UT.hour));
   sscanf(sec,"%2d",&(UT.sec));
   sscanf(msec,"%3d",&(UT.msec));

   SetDouble(&UT);
   return UT.times;
}
/*------------------------------------------------------*/
/*-------------------   Double2DD_Time  ---------------------*/
void Double2DD_Time(char * buffer, double Time)
 {
    dd_time_t UTstring;
    dd_tmstr_t  UT;

    UT.times =   Time;
   SetIntNew(&UT,DD_TM_DATE); //
   sprintf(UTstring,"%04d%03d%02d%02d%02d%03d",(UT.year),(UT.day),(UT.hour), (UT.min), (UT.sec),(UT.msec));
   strncpy(buffer, &(UTstring[0]), TIMELENGTH);
 }
/*------------------------------------------------------------*/

/*================== BACKUP COMPABILITY FUNCTIONS =================*/
/*---------------------ReadTime --------------------------*/
/* The fiunction ReadTime read standard for DD time string
 * and convert it into dd_tmstr_t structure.
 * see DD-time.h
 * Return pointer to static internal structure or NULL in case
 * of error.
 */
void ReadTime(dd_tmstr_t &UT,char *UTstring)
{
   char year[5] = "0000";
   char  day[4] = "000";
   char   hour[3]= "00";
   char min[3] = "00";
   char  sec[3]= "00";
   char  msec[4] = "000";

   strncpy(year,UTstring,4);
   strncpy(day,UTstring+4,3);
   strncpy(hour,UTstring+7,2);
   strncpy(min,UTstring+9,2);
   strncpy(sec,UTstring+11,2);
   strncpy(msec,UTstring+13,3);

   sscanf(year,"%4d",&(UT.year));
   sscanf(day,"%2d",&(UT.day));
   sscanf(min,"%2d",&(UT.min));
   sscanf(hour,"%2d",&(UT.hour));
   sscanf(sec,"%2d",&(UT.sec));
   sscanf(msec,"%3d",&(UT.msec));

   SetDouble(&UT);
}
/*-------------------- end of ReadTime ------------------------*/

/*---------------------- Write Time ---------------------------*/
/* Function Write time convert use only double times field
 * of dd_tmstr_t structure to print time in DD style 
 * in internal static string. The integer fields redefined.
 * Function return string pointer.
 */

char *WriteTime(dd_tmstr_t *UT)
{
   static dd_time_t UTstring;

   SetIntNew(UT,DD_TM_DATE);
   sprintf(UTstring,"%04d%03d%02d%02d%02d%03d",(UT->year),(UT->day),(UT->hour),
                                         (UT->min), (UT->sec),(UT->msec));
   return(UTstring);
}
/*------------------- end of WriteTime -------------------*/

void WriteFmtTime(dd_tmstr_t *UT,char *UTstring)
  {
   SetIntNew(UT,DD_TM_DATE);
   sprintf(UTstring,"%04d:%03d:%02d:%02d:%02d",(UT->year),(UT->day),(UT->hour),
                                               (UT->min), (UT->sec));
  }

/*=================== Functions for INTERBALL DECODERS ==============*/
/*---------------------- UT 2 DOUBLE ---------------------*/
dd_tmstr_t *UT2double(unsigned *ut)
/* Fill the standard structure with double too using as
 * argument 7 int length array in Gavrilova Passport Standard
 */
{
static dd_tmstr_t UT;
int visocos;

if(ut[0]%4 == 0) visocos = 1; else visocos = 0;
UT.year = ut[0];
UT.day = monthday[visocos][ut[1] - 1]+ut[2] - 1;
UT.hour = ut[3];
UT.min = ut[4];
UT.sec = ut[5];
UT.msec = ut[6];

SetDouble(&UT);
return(&UT);
}
/*-------------------------------------------------------*/
/*---------------- DOUBLE 2 UT --------------------------*/
/*
 * Converts Standard DD double time to Gavrilova UT array
 */
unsigned *Double2UT(double t)
{
   static unsigned UT[7];
   dd_tmstr_t tm;
   int i,visocos;

   tm.times = t;
   SetIntNew(&tm,DD_TM_DATE);
   if(tm.year % 4 == 0) visocos = 1; else visocos = 0;
   i = 0;
   while((i < 12) && (tm.day >= monthday[visocos][i])) i++;
   UT[0] = tm.year;
   UT[1] = i;
   UT[2] = tm.day +1 - monthday[visocos][i-1];
   UT[3] = tm.hour;
   UT[4] = tm.min;
   UT[5] = tm.sec;
   UT[6] = tm.msec;

   return( (unsigned *)UT);
}
/*=======================================================================*/