Satellite Observers Workbench. NOT yet complete, just published for forum posters to \"cherry pick\" pieces of code as requiered as an example.
sgp4sdp4/sgp_time.c@0:0a841b89d614, 2010-10-11 (annotated)
- Committer:
- AjK
- Date:
- Mon Oct 11 10:34:55 2010 +0000
- Revision:
- 0:0a841b89d614
Totally Alpha quality as this project isn\t completed. Just publishing it as it answers many questions asked in the forums
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
AjK | 0:0a841b89d614 | 1 | /* |
AjK | 0:0a841b89d614 | 2 | * Unit SGP_Time |
AjK | 0:0a841b89d614 | 3 | * Author: Dr TS Kelso |
AjK | 0:0a841b89d614 | 4 | * Original Version: 1992 Jun 02 |
AjK | 0:0a841b89d614 | 5 | * Current Revision: 2000 Jan 22 |
AjK | 0:0a841b89d614 | 6 | * Modified for Y2K: 1999 Mar 07 |
AjK | 0:0a841b89d614 | 7 | * Version: 2.05 |
AjK | 0:0a841b89d614 | 8 | * Copyright: 1992-1999, All Rights Reserved |
AjK | 0:0a841b89d614 | 9 | * Version 1.50 added Y2K support. Due to limitations in the current |
AjK | 0:0a841b89d614 | 10 | * format of the NORAD two-line element sets, however, only dates |
AjK | 0:0a841b89d614 | 11 | * through 2056 December 31/2359 UTC are valid. |
AjK | 0:0a841b89d614 | 12 | * Version 1.60 modifies Calendar_Date to ensure date matches time |
AjK | 0:0a841b89d614 | 13 | * resolution and modifies Time_of_Day to make it more robust. |
AjK | 0:0a841b89d614 | 14 | * Version 2.00 adds Julian_Date, Date_Time, and Check_Date to support |
AjK | 0:0a841b89d614 | 15 | * checking for valid date/times, permitting the use of Time_to_UTC and |
AjK | 0:0a841b89d614 | 16 | * Time_from_UTC for UTC/local time conversions. |
AjK | 0:0a841b89d614 | 17 | * Version 2.05 modifies UTC_offset to allow non-integer offsets. |
AjK | 0:0a841b89d614 | 18 | * |
AjK | 0:0a841b89d614 | 19 | * Ported to C by: Neoklis Kyriazis April 9 2001 |
AjK | 0:0a841b89d614 | 20 | */ |
AjK | 0:0a841b89d614 | 21 | |
AjK | 0:0a841b89d614 | 22 | #include "sgp4sdp4.h" |
AjK | 0:0a841b89d614 | 23 | |
AjK | 0:0a841b89d614 | 24 | /* The function Julian_Date_of_Epoch returns the Julian Date of */ |
AjK | 0:0a841b89d614 | 25 | /* an epoch specified in the format used in the NORAD two-line */ |
AjK | 0:0a841b89d614 | 26 | /* element sets. It has been modified to support dates beyond */ |
AjK | 0:0a841b89d614 | 27 | /* the year 1999 assuming that two-digit years in the range 00-56 */ |
AjK | 0:0a841b89d614 | 28 | /* correspond to 2000-2056. Until the two-line element set format */ |
AjK | 0:0a841b89d614 | 29 | /* is changed, it is only valid for dates through 2056 December 31. */ |
AjK | 0:0a841b89d614 | 30 | |
AjK | 0:0a841b89d614 | 31 | double |
AjK | 0:0a841b89d614 | 32 | Julian_Date_of_Epoch(double epoch) |
AjK | 0:0a841b89d614 | 33 | { |
AjK | 0:0a841b89d614 | 34 | double year,day; |
AjK | 0:0a841b89d614 | 35 | |
AjK | 0:0a841b89d614 | 36 | /* Modification to support Y2K */ |
AjK | 0:0a841b89d614 | 37 | /* Valid 1957 through 2056 */ |
AjK | 0:0a841b89d614 | 38 | day = modf(epoch*1E-3, &year)*1E3; |
AjK | 0:0a841b89d614 | 39 | if( year < 57 ) |
AjK | 0:0a841b89d614 | 40 | year = year + 2000; |
AjK | 0:0a841b89d614 | 41 | else |
AjK | 0:0a841b89d614 | 42 | year = year + 1900; |
AjK | 0:0a841b89d614 | 43 | /* End modification */ |
AjK | 0:0a841b89d614 | 44 | |
AjK | 0:0a841b89d614 | 45 | return( Julian_Date_of_Year(year) + day ); |
AjK | 0:0a841b89d614 | 46 | } /*Function Julian_Date_of_Epoch*/ |
AjK | 0:0a841b89d614 | 47 | |
AjK | 0:0a841b89d614 | 48 | /*------------------------------------------------------------------*/ |
AjK | 0:0a841b89d614 | 49 | |
AjK | 0:0a841b89d614 | 50 | /* Converts a Julian epoch to NORAD TLE epoch format */ |
AjK | 0:0a841b89d614 | 51 | double |
AjK | 0:0a841b89d614 | 52 | Epoch_Time(double jd) |
AjK | 0:0a841b89d614 | 53 | { |
AjK | 0:0a841b89d614 | 54 | double yr,_time,epoch_time; |
AjK | 0:0a841b89d614 | 55 | struct tm edate; |
AjK | 0:0a841b89d614 | 56 | |
AjK | 0:0a841b89d614 | 57 | Calendar_Date(jd, &edate); |
AjK | 0:0a841b89d614 | 58 | yr = edate.tm_year - 100*(edate.tm_year/100) ; |
AjK | 0:0a841b89d614 | 59 | _time = Frac(jd + 0.5); |
AjK | 0:0a841b89d614 | 60 | epoch_time = yr*1000 |
AjK | 0:0a841b89d614 | 61 | + DOY(edate.tm_year, edate.tm_mon, edate.tm_mday) |
AjK | 0:0a841b89d614 | 62 | + _time; |
AjK | 0:0a841b89d614 | 63 | |
AjK | 0:0a841b89d614 | 64 | return( epoch_time ); |
AjK | 0:0a841b89d614 | 65 | } /*Function Epoch_Time*/ |
AjK | 0:0a841b89d614 | 66 | |
AjK | 0:0a841b89d614 | 67 | /*------------------------------------------------------------------*/ |
AjK | 0:0a841b89d614 | 68 | |
AjK | 0:0a841b89d614 | 69 | /* The function DOY calculates the day of the year for the specified */ |
AjK | 0:0a841b89d614 | 70 | /* date. The calculation uses the rules for the Gregorian calendar */ |
AjK | 0:0a841b89d614 | 71 | /* and is valid from the inception of that calendar system. */ |
AjK | 0:0a841b89d614 | 72 | int |
AjK | 0:0a841b89d614 | 73 | DOY(int yr, int mo, int dy) |
AjK | 0:0a841b89d614 | 74 | { |
AjK | 0:0a841b89d614 | 75 | const int days[] = {31,28,31,30,31,30,31,31,30,31,30,31}; |
AjK | 0:0a841b89d614 | 76 | int i,day; |
AjK | 0:0a841b89d614 | 77 | |
AjK | 0:0a841b89d614 | 78 | day = 0; |
AjK | 0:0a841b89d614 | 79 | for( i = 0; i < mo-1; i++ ) |
AjK | 0:0a841b89d614 | 80 | day += days[i]; |
AjK | 0:0a841b89d614 | 81 | day = day + dy; |
AjK | 0:0a841b89d614 | 82 | |
AjK | 0:0a841b89d614 | 83 | /* Leap year correction */ |
AjK | 0:0a841b89d614 | 84 | if( |
AjK | 0:0a841b89d614 | 85 | (yr%4 == 0) && ((yr%100 != 0) || (yr%400 == 0)) && (mo>2) |
AjK | 0:0a841b89d614 | 86 | ) |
AjK | 0:0a841b89d614 | 87 | day++; |
AjK | 0:0a841b89d614 | 88 | |
AjK | 0:0a841b89d614 | 89 | return( day ); |
AjK | 0:0a841b89d614 | 90 | } /*Function DOY*/ |
AjK | 0:0a841b89d614 | 91 | |
AjK | 0:0a841b89d614 | 92 | /*------------------------------------------------------------------*/ |
AjK | 0:0a841b89d614 | 93 | |
AjK | 0:0a841b89d614 | 94 | /* Fraction_of_Day calculates the fraction of */ |
AjK | 0:0a841b89d614 | 95 | /* a day passed at the specified input time. */ |
AjK | 0:0a841b89d614 | 96 | double |
AjK | 0:0a841b89d614 | 97 | Fraction_of_Day(int hr,int mi,int se) |
AjK | 0:0a841b89d614 | 98 | { |
AjK | 0:0a841b89d614 | 99 | return( (hr + (mi + se/60.0)/60.0)/24.0 ); |
AjK | 0:0a841b89d614 | 100 | } /*Function Fraction_of_Day*/ |
AjK | 0:0a841b89d614 | 101 | |
AjK | 0:0a841b89d614 | 102 | /*------------------------------------------------------------------*/ |
AjK | 0:0a841b89d614 | 103 | |
AjK | 0:0a841b89d614 | 104 | /* The function Calendar_Date converts a Julian Date to a struct tm. */ |
AjK | 0:0a841b89d614 | 105 | /* Only the members tm_year, tm_mon and tm_mday are calculated and set */ |
AjK | 0:0a841b89d614 | 106 | void |
AjK | 0:0a841b89d614 | 107 | Calendar_Date(double jd, struct tm *cdate) |
AjK | 0:0a841b89d614 | 108 | { |
AjK | 0:0a841b89d614 | 109 | /* Astronomical Formulae for Calculators, Jean Meeus, pages 26-27 */ |
AjK | 0:0a841b89d614 | 110 | int Z,month; |
AjK | 0:0a841b89d614 | 111 | double A,B,C,D,E,F,alpha,day,year,factor; |
AjK | 0:0a841b89d614 | 112 | |
AjK | 0:0a841b89d614 | 113 | factor = 0.5/secday/1000; |
AjK | 0:0a841b89d614 | 114 | F = Frac(jd + 0.5); |
AjK | 0:0a841b89d614 | 115 | if (F + factor >= 1.0) |
AjK | 0:0a841b89d614 | 116 | { |
AjK | 0:0a841b89d614 | 117 | jd = jd + factor; |
AjK | 0:0a841b89d614 | 118 | F = 0.0; |
AjK | 0:0a841b89d614 | 119 | } /*if*/ |
AjK | 0:0a841b89d614 | 120 | Z = Round(jd); |
AjK | 0:0a841b89d614 | 121 | if( Z < 2299161 ) |
AjK | 0:0a841b89d614 | 122 | A = Z; |
AjK | 0:0a841b89d614 | 123 | else |
AjK | 0:0a841b89d614 | 124 | { |
AjK | 0:0a841b89d614 | 125 | alpha = Int((Z - 1867216.25)/36524.25); |
AjK | 0:0a841b89d614 | 126 | A = Z + 1 + alpha - Int(alpha/4); |
AjK | 0:0a841b89d614 | 127 | } /*else*/ |
AjK | 0:0a841b89d614 | 128 | B = A + 1524; |
AjK | 0:0a841b89d614 | 129 | C = Int((B - 122.1)/365.25); |
AjK | 0:0a841b89d614 | 130 | D = Int(365.25 * C); |
AjK | 0:0a841b89d614 | 131 | E = Int((B - D)/30.6001); |
AjK | 0:0a841b89d614 | 132 | day = B - D - Int(30.6001 * E) + F; |
AjK | 0:0a841b89d614 | 133 | |
AjK | 0:0a841b89d614 | 134 | if( E < 13.5 ) |
AjK | 0:0a841b89d614 | 135 | month = Round(E - 1); |
AjK | 0:0a841b89d614 | 136 | else |
AjK | 0:0a841b89d614 | 137 | month = Round(E - 13); |
AjK | 0:0a841b89d614 | 138 | if( month > 2.5 ) |
AjK | 0:0a841b89d614 | 139 | year = C - 4716; |
AjK | 0:0a841b89d614 | 140 | else |
AjK | 0:0a841b89d614 | 141 | year = C - 4715; |
AjK | 0:0a841b89d614 | 142 | |
AjK | 0:0a841b89d614 | 143 | cdate->tm_year = (int) year; |
AjK | 0:0a841b89d614 | 144 | cdate->tm_mon = month; |
AjK | 0:0a841b89d614 | 145 | cdate->tm_mday = (int) floor(day); |
AjK | 0:0a841b89d614 | 146 | |
AjK | 0:0a841b89d614 | 147 | } /*Function Calendar_Date*/ |
AjK | 0:0a841b89d614 | 148 | |
AjK | 0:0a841b89d614 | 149 | /*------------------------------------------------------------------*/ |
AjK | 0:0a841b89d614 | 150 | |
AjK | 0:0a841b89d614 | 151 | /* Time_of_Day takes a Julian Date and calculates the clock time */ |
AjK | 0:0a841b89d614 | 152 | /* portion of that date. Only tm_hour, tm_min and tm_sec are set */ |
AjK | 0:0a841b89d614 | 153 | void |
AjK | 0:0a841b89d614 | 154 | Time_of_Day(double jd, struct tm *cdate) |
AjK | 0:0a841b89d614 | 155 | { |
AjK | 0:0a841b89d614 | 156 | int hr,mn,sc; |
AjK | 0:0a841b89d614 | 157 | double _time; |
AjK | 0:0a841b89d614 | 158 | |
AjK | 0:0a841b89d614 | 159 | _time = Frac(jd - 0.5)*secday; |
AjK | 0:0a841b89d614 | 160 | _time = Round(_time); |
AjK | 0:0a841b89d614 | 161 | hr = floor(_time/3600.0); |
AjK | 0:0a841b89d614 | 162 | _time = _time - 3600.0*hr; |
AjK | 0:0a841b89d614 | 163 | if( hr == 24 ) hr = 0; |
AjK | 0:0a841b89d614 | 164 | mn = floor(_time/60.0); |
AjK | 0:0a841b89d614 | 165 | sc = _time - 60.0*mn; |
AjK | 0:0a841b89d614 | 166 | cdate->tm_hour = hr; |
AjK | 0:0a841b89d614 | 167 | cdate->tm_min = mn; |
AjK | 0:0a841b89d614 | 168 | cdate->tm_sec = sc; |
AjK | 0:0a841b89d614 | 169 | |
AjK | 0:0a841b89d614 | 170 | } /*Function Time_of_Day*/ |
AjK | 0:0a841b89d614 | 171 | |
AjK | 0:0a841b89d614 | 172 | /*------------------------------------------------------------------*/ |
AjK | 0:0a841b89d614 | 173 | |
AjK | 0:0a841b89d614 | 174 | /* The function Julian_Date converts a standard calendar */ |
AjK | 0:0a841b89d614 | 175 | /* date and time to a Julian Date. The procedure Date_Time */ |
AjK | 0:0a841b89d614 | 176 | /* performs the inverse of this function. */ |
AjK | 0:0a841b89d614 | 177 | double |
AjK | 0:0a841b89d614 | 178 | Julian_Date(struct tm *cdate) |
AjK | 0:0a841b89d614 | 179 | { |
AjK | 0:0a841b89d614 | 180 | double julian_date; |
AjK | 0:0a841b89d614 | 181 | |
AjK | 0:0a841b89d614 | 182 | julian_date = Julian_Date_of_Year(cdate->tm_year) + |
AjK | 0:0a841b89d614 | 183 | DOY(cdate->tm_year,cdate->tm_mon,cdate->tm_mday) + |
AjK | 0:0a841b89d614 | 184 | Fraction_of_Day(cdate->tm_hour,cdate->tm_min,cdate->tm_sec); |
AjK | 0:0a841b89d614 | 185 | |
AjK | 0:0a841b89d614 | 186 | return( julian_date ); |
AjK | 0:0a841b89d614 | 187 | } /*Function Julian_Date */ |
AjK | 0:0a841b89d614 | 188 | |
AjK | 0:0a841b89d614 | 189 | /*------------------------------------------------------------------*/ |
AjK | 0:0a841b89d614 | 190 | |
AjK | 0:0a841b89d614 | 191 | |
AjK | 0:0a841b89d614 | 192 | /* Date_Time() |
AjK | 0:0a841b89d614 | 193 | * |
AjK | 0:0a841b89d614 | 194 | * The function Date_Time() converts a Julian Date to |
AjK | 0:0a841b89d614 | 195 | * standard calendar date and time. The function |
AjK | 0:0a841b89d614 | 196 | * Julian_Date() performs the inverse of this function. |
AjK | 0:0a841b89d614 | 197 | */ |
AjK | 0:0a841b89d614 | 198 | |
AjK | 0:0a841b89d614 | 199 | void |
AjK | 0:0a841b89d614 | 200 | Date_Time(double julian_date, struct tm *cdate) |
AjK | 0:0a841b89d614 | 201 | { |
AjK | 0:0a841b89d614 | 202 | time_t jtime; |
AjK | 0:0a841b89d614 | 203 | |
AjK | 0:0a841b89d614 | 204 | jtime = (julian_date - 2440587.5)*86400.; |
AjK | 0:0a841b89d614 | 205 | *cdate = *gmtime( &jtime ); |
AjK | 0:0a841b89d614 | 206 | |
AjK | 0:0a841b89d614 | 207 | } /* End of Date_Time() */ |
AjK | 0:0a841b89d614 | 208 | |
AjK | 0:0a841b89d614 | 209 | |
AjK | 0:0a841b89d614 | 210 | /*------------------------------------------------------------------*/ |
AjK | 0:0a841b89d614 | 211 | |
AjK | 0:0a841b89d614 | 212 | /* The procedure Check_Date can be used as a check to see if a calendar */ |
AjK | 0:0a841b89d614 | 213 | /* date and time are valid. It works by first converting the calendar */ |
AjK | 0:0a841b89d614 | 214 | /* date and time to a Julian Date (which allows for irregularities, such */ |
AjK | 0:0a841b89d614 | 215 | /* as a time greater than 24 hours) and then converting back and comparing.*/ |
AjK | 0:0a841b89d614 | 216 | int |
AjK | 0:0a841b89d614 | 217 | Check_Date(struct tm *cdate) |
AjK | 0:0a841b89d614 | 218 | { |
AjK | 0:0a841b89d614 | 219 | double jt; |
AjK | 0:0a841b89d614 | 220 | struct tm chkdate; |
AjK | 0:0a841b89d614 | 221 | |
AjK | 0:0a841b89d614 | 222 | jt = Julian_Date(cdate); |
AjK | 0:0a841b89d614 | 223 | Date_Time(jt, &chkdate); |
AjK | 0:0a841b89d614 | 224 | |
AjK | 0:0a841b89d614 | 225 | if( (cdate->tm_year == chkdate.tm_year) && |
AjK | 0:0a841b89d614 | 226 | (cdate->tm_mon == chkdate.tm_mon ) && |
AjK | 0:0a841b89d614 | 227 | (cdate->tm_mday == chkdate.tm_mday) && |
AjK | 0:0a841b89d614 | 228 | (cdate->tm_hour == chkdate.tm_hour) && |
AjK | 0:0a841b89d614 | 229 | (cdate->tm_min == chkdate.tm_min ) && |
AjK | 0:0a841b89d614 | 230 | (cdate->tm_sec == chkdate.tm_sec ) ) |
AjK | 0:0a841b89d614 | 231 | return ( 1 ); |
AjK | 0:0a841b89d614 | 232 | else |
AjK | 0:0a841b89d614 | 233 | return( 0 ); |
AjK | 0:0a841b89d614 | 234 | |
AjK | 0:0a841b89d614 | 235 | } /*Procedure Check_Date*/ |
AjK | 0:0a841b89d614 | 236 | |
AjK | 0:0a841b89d614 | 237 | /*------------------------------------------------------------------*/ |
AjK | 0:0a841b89d614 | 238 | |
AjK | 0:0a841b89d614 | 239 | /* Procedures Time_to_UTC and Time_from_UTC are used to */ |
AjK | 0:0a841b89d614 | 240 | /* convert 'struct tm' dates between UTC and local time. */ |
AjK | 0:0a841b89d614 | 241 | /* The procedures JD_to_UTC and JD_from_UTC are used to */ |
AjK | 0:0a841b89d614 | 242 | /* do the same thing working directly with Julian dates. */ |
AjK | 0:0a841b89d614 | 243 | |
AjK | 0:0a841b89d614 | 244 | struct tm |
AjK | 0:0a841b89d614 | 245 | Time_to_UTC(struct tm *cdate) |
AjK | 0:0a841b89d614 | 246 | { |
AjK | 0:0a841b89d614 | 247 | time_t tdate; |
AjK | 0:0a841b89d614 | 248 | |
AjK | 0:0a841b89d614 | 249 | tdate = mktime(cdate); |
AjK | 0:0a841b89d614 | 250 | return( *gmtime(&tdate) ); |
AjK | 0:0a841b89d614 | 251 | } /*Procedure Time_to_UTC*/ |
AjK | 0:0a841b89d614 | 252 | |
AjK | 0:0a841b89d614 | 253 | /*------------------------------------------------------------------*/ |
AjK | 0:0a841b89d614 | 254 | |
AjK | 0:0a841b89d614 | 255 | struct tm |
AjK | 0:0a841b89d614 | 256 | Time_from_UTC(struct tm *cdate) |
AjK | 0:0a841b89d614 | 257 | { |
AjK | 0:0a841b89d614 | 258 | time_t tdate; |
AjK | 0:0a841b89d614 | 259 | |
AjK | 0:0a841b89d614 | 260 | tdate = mktime(cdate); |
AjK | 0:0a841b89d614 | 261 | return( *localtime(&tdate) ); |
AjK | 0:0a841b89d614 | 262 | } /*Procedure Time_from_UTC*/ |
AjK | 0:0a841b89d614 | 263 | |
AjK | 0:0a841b89d614 | 264 | /*------------------------------------------------------------------*/ |
AjK | 0:0a841b89d614 | 265 | |
AjK | 0:0a841b89d614 | 266 | /* |
AjK | 0:0a841b89d614 | 267 | BSD systems don't define the timezone variable, so the following two |
AjK | 0:0a841b89d614 | 268 | routines won't work. They're not used anyway in the example main(), |
AjK | 0:0a841b89d614 | 269 | so we might as well comment them out. |
AjK | 0:0a841b89d614 | 270 | */ |
AjK | 0:0a841b89d614 | 271 | |
AjK | 0:0a841b89d614 | 272 | #if 0 |
AjK | 0:0a841b89d614 | 273 | |
AjK | 0:0a841b89d614 | 274 | double |
AjK | 0:0a841b89d614 | 275 | JD_to_UTC(double jt) |
AjK | 0:0a841b89d614 | 276 | { |
AjK | 0:0a841b89d614 | 277 | extern long timezone; |
AjK | 0:0a841b89d614 | 278 | struct tm cdate; |
AjK | 0:0a841b89d614 | 279 | |
AjK | 0:0a841b89d614 | 280 | time_t t = 0; |
AjK | 0:0a841b89d614 | 281 | |
AjK | 0:0a841b89d614 | 282 | cdate = *localtime( &t ); |
AjK | 0:0a841b89d614 | 283 | jt = jt - timezone/secday; |
AjK | 0:0a841b89d614 | 284 | if( cdate.tm_isdst ) |
AjK | 0:0a841b89d614 | 285 | jt= jt - 1.0/24.0; |
AjK | 0:0a841b89d614 | 286 | |
AjK | 0:0a841b89d614 | 287 | return( jt ); |
AjK | 0:0a841b89d614 | 288 | } /*Procedure JD_to_UTC*/ |
AjK | 0:0a841b89d614 | 289 | |
AjK | 0:0a841b89d614 | 290 | /*------------------------------------------------------------------*/ |
AjK | 0:0a841b89d614 | 291 | |
AjK | 0:0a841b89d614 | 292 | double |
AjK | 0:0a841b89d614 | 293 | JD_from_UTC(double jt) |
AjK | 0:0a841b89d614 | 294 | { |
AjK | 0:0a841b89d614 | 295 | extern long timezone; |
AjK | 0:0a841b89d614 | 296 | struct tm cdate; |
AjK | 0:0a841b89d614 | 297 | time_t t = 0; |
AjK | 0:0a841b89d614 | 298 | |
AjK | 0:0a841b89d614 | 299 | cdate = *localtime( &t ); |
AjK | 0:0a841b89d614 | 300 | jt = jt + timezone/secday; |
AjK | 0:0a841b89d614 | 301 | if( cdate.tm_isdst ) |
AjK | 0:0a841b89d614 | 302 | jt= jt + 1.0/24.0; |
AjK | 0:0a841b89d614 | 303 | |
AjK | 0:0a841b89d614 | 304 | return( jt ); |
AjK | 0:0a841b89d614 | 305 | } /*Procedure JD_from_UTC*/ |
AjK | 0:0a841b89d614 | 306 | |
AjK | 0:0a841b89d614 | 307 | #endif |
AjK | 0:0a841b89d614 | 308 | |
AjK | 0:0a841b89d614 | 309 | /*------------------------------------------------------------------*/ |
AjK | 0:0a841b89d614 | 310 | |
AjK | 0:0a841b89d614 | 311 | /* The function Delta_ET has been added to allow calculations on */ |
AjK | 0:0a841b89d614 | 312 | /* the position of the sun. It provides the difference between UT */ |
AjK | 0:0a841b89d614 | 313 | /* (approximately the same as UTC) and ET (now referred to as TDT).*/ |
AjK | 0:0a841b89d614 | 314 | /* This function is based on a least squares fit of data from 1950 */ |
AjK | 0:0a841b89d614 | 315 | /* to 1991 and will need to be updated periodically. */ |
AjK | 0:0a841b89d614 | 316 | |
AjK | 0:0a841b89d614 | 317 | double |
AjK | 0:0a841b89d614 | 318 | Delta_ET(double year) |
AjK | 0:0a841b89d614 | 319 | { |
AjK | 0:0a841b89d614 | 320 | /* Values determined using data from 1950-1991 in the 1990 |
AjK | 0:0a841b89d614 | 321 | Astronomical Almanac. See DELTA_ET.WQ1 for details. */ |
AjK | 0:0a841b89d614 | 322 | |
AjK | 0:0a841b89d614 | 323 | double delta_et; |
AjK | 0:0a841b89d614 | 324 | |
AjK | 0:0a841b89d614 | 325 | delta_et = 26.465 + 0.747622*(year - 1950) + |
AjK | 0:0a841b89d614 | 326 | 1.886913*sin(twopi*(year - 1975)/33); |
AjK | 0:0a841b89d614 | 327 | |
AjK | 0:0a841b89d614 | 328 | return( delta_et ); |
AjK | 0:0a841b89d614 | 329 | } /*Function Delta_ET*/ |
AjK | 0:0a841b89d614 | 330 | |
AjK | 0:0a841b89d614 | 331 | /*------------------------------------------------------------------*/ |
AjK | 0:0a841b89d614 | 332 | |
AjK | 0:0a841b89d614 | 333 | /* The function Julian_Date_of_Year calculates the Julian Date */ |
AjK | 0:0a841b89d614 | 334 | /* of Day 0.0 of {year}. This function is used to calculate the */ |
AjK | 0:0a841b89d614 | 335 | /* Julian Date of any date by using Julian_Date_of_Year, DOY, */ |
AjK | 0:0a841b89d614 | 336 | /* and Fraction_of_Day. */ |
AjK | 0:0a841b89d614 | 337 | |
AjK | 0:0a841b89d614 | 338 | double |
AjK | 0:0a841b89d614 | 339 | Julian_Date_of_Year(double year) |
AjK | 0:0a841b89d614 | 340 | { |
AjK | 0:0a841b89d614 | 341 | /* Astronomical Formulae for Calculators, Jean Meeus, */ |
AjK | 0:0a841b89d614 | 342 | /* pages 23-25. Calculate Julian Date of 0.0 Jan year */ |
AjK | 0:0a841b89d614 | 343 | |
AjK | 0:0a841b89d614 | 344 | long A,B,i; |
AjK | 0:0a841b89d614 | 345 | double jdoy; |
AjK | 0:0a841b89d614 | 346 | |
AjK | 0:0a841b89d614 | 347 | year = year-1; |
AjK | 0:0a841b89d614 | 348 | i = year/100; |
AjK | 0:0a841b89d614 | 349 | A = i; |
AjK | 0:0a841b89d614 | 350 | i = A/4; |
AjK | 0:0a841b89d614 | 351 | B = 2-A+i; |
AjK | 0:0a841b89d614 | 352 | i = 365.25*year; |
AjK | 0:0a841b89d614 | 353 | i += 30.6001*14; |
AjK | 0:0a841b89d614 | 354 | jdoy = i+1720994.5+B; |
AjK | 0:0a841b89d614 | 355 | |
AjK | 0:0a841b89d614 | 356 | return (jdoy); |
AjK | 0:0a841b89d614 | 357 | } /*Function Julian_Date_of_Year*/ |
AjK | 0:0a841b89d614 | 358 | |
AjK | 0:0a841b89d614 | 359 | /*------------------------------------------------------------------*/ |
AjK | 0:0a841b89d614 | 360 | |
AjK | 0:0a841b89d614 | 361 | /* The function ThetaG calculates the Greenwich Mean Sidereal Time */ |
AjK | 0:0a841b89d614 | 362 | /* for an epoch specified in the format used in the NORAD two-line */ |
AjK | 0:0a841b89d614 | 363 | /* element sets. It has now been adapted for dates beyond the year */ |
AjK | 0:0a841b89d614 | 364 | /* 1999, as described above. The function ThetaG_JD provides the */ |
AjK | 0:0a841b89d614 | 365 | /* same calculation except that it is based on an input in the */ |
AjK | 0:0a841b89d614 | 366 | /* form of a Julian Date. */ |
AjK | 0:0a841b89d614 | 367 | |
AjK | 0:0a841b89d614 | 368 | double |
AjK | 0:0a841b89d614 | 369 | ThetaG(double epoch, deep_arg_t *deep_arg) |
AjK | 0:0a841b89d614 | 370 | { |
AjK | 0:0a841b89d614 | 371 | /* Reference: The 1992 Astronomical Almanac, page B6. */ |
AjK | 0:0a841b89d614 | 372 | |
AjK | 0:0a841b89d614 | 373 | double year,day,UT,jd,TU,GMST,_ThetaG; |
AjK | 0:0a841b89d614 | 374 | |
AjK | 0:0a841b89d614 | 375 | /* Modification to support Y2K */ |
AjK | 0:0a841b89d614 | 376 | /* Valid 1957 through 2056 */ |
AjK | 0:0a841b89d614 | 377 | day = modf(epoch*1E-3,&year)*1E3; |
AjK | 0:0a841b89d614 | 378 | if(year < 57) |
AjK | 0:0a841b89d614 | 379 | year += 2000; |
AjK | 0:0a841b89d614 | 380 | else |
AjK | 0:0a841b89d614 | 381 | year += 1900; |
AjK | 0:0a841b89d614 | 382 | /* End modification */ |
AjK | 0:0a841b89d614 | 383 | |
AjK | 0:0a841b89d614 | 384 | UT = modf(day,&day); |
AjK | 0:0a841b89d614 | 385 | jd = Julian_Date_of_Year(year)+day; |
AjK | 0:0a841b89d614 | 386 | TU = (jd-2451545.0)/36525; |
AjK | 0:0a841b89d614 | 387 | GMST = 24110.54841+TU*(8640184.812866+TU*(0.093104-TU* 6.2E-6)); |
AjK | 0:0a841b89d614 | 388 | GMST = Modulus(GMST+secday*omega_E*UT,secday); |
AjK | 0:0a841b89d614 | 389 | _ThetaG = twopi*GMST/secday; |
AjK | 0:0a841b89d614 | 390 | deep_arg->ds50 = jd-2433281.5+UT; |
AjK | 0:0a841b89d614 | 391 | _ThetaG = FMod2p(6.3003880987*deep_arg->ds50+1.72944494); |
AjK | 0:0a841b89d614 | 392 | |
AjK | 0:0a841b89d614 | 393 | return (_ThetaG); |
AjK | 0:0a841b89d614 | 394 | } /* Function ThetaG */ |
AjK | 0:0a841b89d614 | 395 | |
AjK | 0:0a841b89d614 | 396 | /*------------------------------------------------------------------*/ |
AjK | 0:0a841b89d614 | 397 | |
AjK | 0:0a841b89d614 | 398 | double |
AjK | 0:0a841b89d614 | 399 | ThetaG_JD(double jd) |
AjK | 0:0a841b89d614 | 400 | { |
AjK | 0:0a841b89d614 | 401 | /* Reference: The 1992 Astronomical Almanac, page B6. */ |
AjK | 0:0a841b89d614 | 402 | |
AjK | 0:0a841b89d614 | 403 | double UT,TU,GMST; |
AjK | 0:0a841b89d614 | 404 | |
AjK | 0:0a841b89d614 | 405 | UT = Frac(jd + 0.5); |
AjK | 0:0a841b89d614 | 406 | jd = jd - UT; |
AjK | 0:0a841b89d614 | 407 | TU = (jd - 2451545.0)/36525; |
AjK | 0:0a841b89d614 | 408 | GMST = 24110.54841 + TU * (8640184.812866 + TU * (0.093104 - TU * 6.2E-6)); |
AjK | 0:0a841b89d614 | 409 | GMST = Modulus(GMST + secday*omega_E*UT,secday); |
AjK | 0:0a841b89d614 | 410 | |
AjK | 0:0a841b89d614 | 411 | return( twopi * GMST/secday ); |
AjK | 0:0a841b89d614 | 412 | } /*Function ThetaG_JD*/ |
AjK | 0:0a841b89d614 | 413 | |
AjK | 0:0a841b89d614 | 414 | /*------------------------------------------------------------------*/ |
AjK | 0:0a841b89d614 | 415 | |
AjK | 0:0a841b89d614 | 416 | /* Gets calendar time from time() and produces a UTC calendar date */ |
AjK | 0:0a841b89d614 | 417 | void |
AjK | 0:0a841b89d614 | 418 | UTC_Calendar_Now( struct tm *cdate ) |
AjK | 0:0a841b89d614 | 419 | { |
AjK | 0:0a841b89d614 | 420 | time_t t; |
AjK | 0:0a841b89d614 | 421 | |
AjK | 0:0a841b89d614 | 422 | t = time(0); |
AjK | 0:0a841b89d614 | 423 | *cdate = *gmtime(&t); |
AjK | 0:0a841b89d614 | 424 | cdate->tm_year += 1900; |
AjK | 0:0a841b89d614 | 425 | cdate->tm_mon += 1; |
AjK | 0:0a841b89d614 | 426 | |
AjK | 0:0a841b89d614 | 427 | } /* End UTC_Calendar_Now */ |
AjK | 0:0a841b89d614 | 428 | /*------------------------------------------------------------------*/ |