/* =================================================================== * Name : DD_time.c * Version: : 4.1 * Author : Andrey Fedorov * Institution : IRAP/UPS/CNRS Toulouse * Modifications list: * 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 * May 17, 2011: V.4.0 Fedorov, completely revised version. * There is no more confuse between Time and Time Interval * Sept 05, 2011: V.4.1 SetIntNew => arg TimeKind => to work with 1970-1973 : BR *==================================================================*/ #include "DD_time.h" #include #include #include #define YEARS 70 #define STARTYEAR 1970 /*---- Static array of days shift from Jan-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}; /*------------------------------------------------------------- * DAY_OF_YEAR = monthday[*][month-1]+day_of_month -1 *------------------------------------------------------------*/ 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} }; /*------------------------------------------------------------ * Global static Flag to show the current state of the time * processor. Is it Time interval (0), or DD Time (1) *----------------------------------------------------------*/ static int TimeFlag = 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 double msofday = 24.0*60.0*60.0; static double msofhour = 60.0*60.0; static double msofmin = 60.0; long daynumber; double msrest; int i; daynumber = (long)(UT->times / msofday); for(i=0;iyear = 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() * Returns the double value of seconds since 1 Jan 1970 * The calculations are made from already filled dd_tmstr_t. * If UT->year *------------------------------------------------------*/ void SetDouble(dd_tmstr_t *UT) { static double SecInMls = 1.0/1000.0; static double SecImMin = 60.0; static double SecInHour = 60.0*60.0; static double SecInDay = 60.0*60.0*24.0; if(UT->year >= STARTYEAR) // This is DD Time ! UT->times = (double)UT->msec*SecInMls + (double)UT->sec + (double)UT->min*SecImMin + (double)UT->hour*SecInHour + (double)UT->day*SecInDay + YearDays[(UT->year - 1970)]*SecInDay; else if(UT->year < STARTYEAR) // This is Time Interval UT->times = (double)UT->msec*SecInMls + (double)UT->sec + (double)UT->min*SecImMin + (double)UT->hour*SecInHour + (double)UT->day*SecInDay + YearDays[UT->year]*SecInDay; else UT->times = 0.0; return; } /*----------------- end of SetDouble ---------------------*/ /*=================== PUBLIC FUNCTIONS ==================*/ /*------------------- DD_Time2Double --------------------*/ double DD_Time2Double(dd_time_t UTstring) { static dd_tmstr_t UT; static char year[5] = "0000\0"; static char day[4] = "000\0"; static char hour[3]= "00\0"; static char min[3] = "00\0"; static char sec[3]= "00\0"; static char msec[4] = "000\0"; 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,"%d",&(UT.year)); sscanf(day,"%d",&(UT.day)); sscanf(min,"%d",&(UT.min)); sscanf(hour,"%d",&(UT.hour)); sscanf(sec,"%d",&(UT.sec)); sscanf(msec,"%d",&(UT.msec)); if(UT.year < STARTYEAR) TimeFlag = 0; // Time Inetrval SetDouble(&UT); return UT.times; } /*------------------------------------------------------*/ /*------------------- Double2DD_Time ---------------------*/ char *Double2DD_Time(double Time) { static dd_time_t UTstring; dd_tmstr_t UT; UT.times = Time; SetInt(&UT); sprintf(UTstring,"%04d%03d%02d%02d%02d%03d",(UT.year),(UT.day),(UT.hour), (UT.min), (UT.sec),(UT.msec)); return &(UTstring[0]); } /*------------------------------------------------------------*/ /*================== BACKUP COMPABILITY FUNCTIONS =================*/ /*----------------------------------------------------------------- * ReadTime() * Reads a standard DD time string as an argument * and converts it into dd_tmstr_t structure. * Function returns the pointer to the internal startic structure dd_tmstr_t. * Function redefines TimeFlag. *----------------------------------------------------------------*/ dd_tmstr_t *ReadTime(char *UTstring) { static dd_tmstr_t UT; static char year[5] = "0000\0"; static char day[4] = "000\0"; static char hour[3]= "00\0"; static char min[3] = "00\0"; static char sec[3]= "00\0"; static char msec[4] = "000\0"; 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,"%d",&(UT.year)); sscanf(day,"%d",&(UT.day)); sscanf(min,"%d",&(UT.min)); sscanf(hour,"%d",&(UT.hour)); sscanf(sec,"%d",&(UT.sec)); sscanf(msec,"%d",&(UT.msec)); if(UT.year < STARTYEAR) TimeFlag = 0; // Time Inetrval SetDouble(&UT); return(&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; SetInt(UT); 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) { SetInt(UT); sprintf(UTstring,"%04d:%03d:%02d:%02d:%02d",(UT->year),(UT->day),(UT->hour), (UT->min), (UT->sec)); } /*------------------- end of WriteFmtTime -------------------*/ /*========================================================= * Functions for DECODERs * These functions make conversion from/to DD double/DD_time_structure and * a integer array as follows: * {Year, Month, Day_Of_Month, Hour, Min, Sec, Mls} *========================================================*/ /*-------------------------------------------------------- * UT2double() * Fille the DD_time_structure with double fild from the * integer array (see the section header) *-------------------------------------------------------*/ 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); } /*-------------------------------------------------------*/ /*------------------------------------------------------- * Double2UT() * Converts Standard DD double time to interger array (see * the section header) *--------------------------------------------------------*/ unsigned *Double2UT(double t) { static unsigned UT[7]; dd_tmstr_t tm; int i,visocos; tm.times = t; SetInt(&tm); 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); } /*=======================================================================*/