3 /* Copyright (C) 2002 Brad Jorsch <anomie@users.sourceforge.net>
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22 # if TIME_WITH_SYS_TIME
23 # include <sys/time.h>
27 # include <sys/time.h>
41 * To indicate unavailable data
42 * 999 is used for temperature
43 * x<0 is used for rh, pressure, and windspeed
49 int rh_C(int temp_C
, int dewpt_C
){
52 if(temp_C
==999 || dewpt_C
==999) return 999;
54 f
=1782.75*(dewpt_C
-temp_C
)/((237.7+dewpt_C
)*(237.7+temp_C
));
55 return round(pow(10, f
+2));
58 int rh_F(int temp_F
, int dewpt_F
){
61 if(temp_F
==999 || dewpt_F
==999) return 999;
63 f
=3208.95*(dewpt_F
-temp_F
)/((395.86+dewpt_F
)*(395.86+temp_F
));
64 return round(pow(10, f
+2));
67 int heatindex_C(int temp_C
, int rh
){
69 if(temp_C
==999 || temp_C
<21 || rh
<0) return 999;
70 return heatindex_F(temp_C2F(temp_C
), rh
);
74 if(temp_C
==999 || temp_C
<38 || rh
<0) return 999;
78 return round(16.18754948 + 2.900509394*temp_C
- 0.0221545692*temp2
+ 4.20938791*rh
- 0.26300889*temp_C
*rh
+ 0.0039811176*temp2
*rh
- 0.02956469*rh2
+ 0.001305828*temp_C
*rh2
- 6.4476e-06*temp2
*rh2
);
82 int heatindex_F(int temp_F
, int rh
){
83 int temp2
, temp3
, rh2
, rh3
;
85 if(temp_F
==999 || temp_F
<70 || rh
<0) return 999;
91 return round(16.923 + .185212*temp_F
+ 5.37941*rh
- .100254*temp_F
*rh
+ (9.41695e-3)*temp2
+ (7.28898e-3)*rh2
+ (3.45372e-4)*temp2
*rh
- (8.14971e-4)*temp_F
*rh2
+ (1.02102e-5)*temp2
*rh2
- (3.8646e-5)*temp3
+ (2.91583e-5)*rh3
+ (1.42721e-6)*temp3
*rh
+ (1.97483e-7)*temp_F
*rh3
- (2.18429e-8)*temp3
*rh2
+ (8.43296e-10)*temp2
*rh3
- (4.81975e-11)*temp3
*rh3
);
93 return round(-42.379 + 2.04901523*temp_F
+ 10.14333127*rh
- 0.22475541*temp_F
*rh
- .00683783*temp2
- .05481717*rh2
+ .00122874*temp2
*rh
+ .00085282*temp_F
*rh2
- .00000199*temp2
*rh2
);
97 int windchill_C(int temp_C
, int windspeed
){
98 if(temp_C
==999 || windspeed
<0) return 999;
100 return windchill_F(temp_C2F(temp_C
), windspeed
);
103 int windchill_F(int temp_F
, int windspeed
){
105 if(temp_F
==999 || windspeed
<0) return 999;
107 ret
=35.74 + 0.6215*temp_F
+ (-35.75 + 0.4275*temp_F
)*pow(windspeed
*50292/57875.0, 0.16);
108 if(ret
>temp_F
) return temp_F
;
112 /* Length Conversions */
116 return round(in
*2.54);
119 float m2mi(int meters
){
120 if(meters
<0) return meters
;
121 return meters
*125/201168;
124 /* Windspeed Conversions */
126 int knots2mph(int knots
){
127 if(knots
<0) return knots
;
128 return round(knots
*57875/50292.0);
131 int knots2kph(int knots
){
132 if(knots
<0) return knots
;
133 return round(knots
*463/250.0);
136 int kph2knots(int kph
){
137 if(kph
<0) return kph
;
138 return round(kph
*250/463.0);
141 int knots2mps(int knots
){
142 if(knots
<0) return knots
;
143 return round(knots
*463/900.0);
146 int mps2knots(int mps
){
147 if(mps
<0) return mps
;
148 return round(mps
*900/463.0);
151 int knots2beaufort(int knots
){
152 if(knots
<0) return knots
;
153 if(knots
<1) return 0;
154 if(knots
<=3) return 1;
155 if(knots
<=6) return 2;
156 if(knots
<=10) return 3;
157 if(knots
<=16) return 4;
158 if(knots
<=21) return 5;
159 if(knots
<=27) return 6;
160 if(knots
<=33) return 7;
161 if(knots
<=40) return 8;
162 if(knots
<=47) return 9;
163 if(knots
<=55) return 10;
164 if(knots
<=63) return 11;
169 /* Temperature Conversions */
171 int temp_C2F(int temp_C
){
172 if(temp_C
==999) return 999;
173 return round(temp_C
*9/5.0+32);
176 int temp_F2C(int temp_F
){
177 if(temp_F
==999) return 999;
178 return round((temp_F
-32)*5/9.0);
182 /* Pressure Conversions */
184 float inHg2mmHg(float inHg
){
185 if(inHg
<0) return inHg
;
189 float inHg2hPa(float inHg
){
190 if(inHg
<0) return inHg
;
194 float inHg2atm(float inHg
){
195 if(inHg
<0) return inHg
;
196 return inHg
*.033421052632;
199 float hPa2inHg(float hPa
){
200 if(hPa
<0) return hPa
;
205 /* Time Conversions */
207 /* NOTE: y%400==100 because y=year-1900 */
208 #define is_leap(y) (y%4==0 && (y%100!=0 || y%400==100))
210 /* mktime for UTC, more or less.
212 * - no range checking
213 * - never recalculates tm_wday or tm_yday
215 time_t mkgmtime(struct tm
*tm
){
216 static long msec
[]={0, 2678400, 5097600, 7776000, 10368000, 13046400, 15638400, 18316800, 20995200, 23587200, 26265600, 28857600};
222 for(i
=70; i
<tm
->tm_year
; i
++){
224 if(is_leap(i
)) t
+=86400;
226 } else if(tm
->tm_year
<70){
227 for(i
=69; i
>=tm
->tm_year
; i
--){
229 if(is_leap(i
)) t
-=86400;
233 if(tm
->tm_mon
>1 && is_leap(tm
->tm_year
)) t
+=86400;
234 t
+=(((tm
->tm_mday
-1)*24+tm
->tm_hour
)*60+tm
->tm_min
)*60+tm
->tm_sec
;
239 int utc2local(int hm
, int *month
, int *day
, int *year
, int *wday
){
246 if(month
!=NULL
&& *month
!=-1) tm
->tm_mon
=*month
-1;
247 if(day
!=NULL
&& *day
!=-1) tm
->tm_mday
=*day
;
248 if(year
!=NULL
&& *year
!=-1) tm
->tm_year
=*year
;
253 if(month
!=NULL
) *month
=tm
->tm_mon
+1;
254 if(day
!=NULL
) *day
=tm
->tm_mday
;
255 if(year
!=NULL
) *year
=tm
->tm_year
;
256 if(wday
!=NULL
) *wday
=tm
->tm_wday
;
257 return tm
->tm_hour
*100+tm
->tm_min
;
260 int local2utc(int hm
, int *month
, int *day
, int *year
, int *wday
){
267 if(month
!=NULL
&& *month
!=-1) tm
->tm_mon
=*month
-1;
268 if(day
!=NULL
&& *day
!=-1) tm
->tm_mday
=*day
;
269 if(year
!=NULL
&& *year
!=-1) tm
->tm_year
=*year
;
274 if(month
!=NULL
) *month
=tm
->tm_mon
+1;
275 if(day
!=NULL
) *day
=tm
->tm_mday
;
276 if(year
!=NULL
) *year
=tm
->tm_year
;
277 if(wday
!=NULL
) *wday
=tm
->tm_wday
;
278 return tm
->tm_hour
*100+tm
->tm_min
;
281 void fix_date(int *month
, int *day
, int *year
, int *wday
){
286 if(month
!=NULL
&& *month
!=-1) tm
->tm_mon
=*month
-1;
287 if(day
!=NULL
&& *day
!=-1) tm
->tm_mday
=*day
;
288 if(year
!=NULL
&& *year
!=-1) tm
->tm_year
=*year
;
293 if(month
!=NULL
) *month
=tm
->tm_mon
+1;
294 if(day
!=NULL
) *day
=tm
->tm_mday
;
295 if(year
!=NULL
) *year
=tm
->tm_year
;
296 if(wday
!=NULL
) *wday
=tm
->tm_wday
;
300 return hm
/100*60+hm
%100;
303 /* Letter Case (destructive!) */
305 char *str_upper(char *str
){
308 for(c
=str
; *c
!='\0'; c
++){
314 char *str_lower(char *str
){
317 for(c
=str
; *c
!='\0'; c
++){
324 /* Angle conversions */
326 /* Convert radian angle to degrees */
327 double rad2deg(double angle
) {
328 return 180.0*angle
/PI
;
331 /* Convert degree angle to radians */
332 double deg2rad(double angle
) {
333 return PI
*angle
/180.0;
337 /* Date conversions */
339 /* Numerical day-of-year from month, day and year */
340 int mdy2doy(int mn
, int dy
, int y
) {
341 return 275*mn
/9 - ((y
%4==0 && (y
%100!=0 || y
%400==100))?1:2)*(mn
+ 9)/12 + dy
-30;
344 /* Julian day from month/day/year */
345 double mdy2jd(int year
, int month
, int day
) {
356 return (int)(365.25*(year
+ 4716)) + (int)(30.6001*(month
+1)) + day
+ B
- 1524.5;
359 /* convert Julian Day to centuries since J2000.0. */
360 double jd2jcent(double jd
) {
361 return (jd
- 2451545.0)/36525.0;
364 /* convert centuries since J2000.0 to Julian Day. */
365 double jcent2jd(double t
) {
366 return t
* 36525.0 + 2451545.0;
370 /* Lat/Long conversions */
372 static double parse_dd_or_dms(char *s
, char **e
){
376 if(strchr(s
, 'x') || strchr(s
, 'X')) return NAN
;
377 if(!strchr(s
, '\'')){
378 if(!isdigit(*s
) && *s
!='.') return NAN
;
382 if(!isdigit(*s
)) return NAN
;
383 deg
=strtol(s
, e
, 10);
384 if(*e
==s
|| *e
==NULL
|| **e
!='\'') return deg
;
386 if(!isdigit(*s
)) return deg
;
387 deg
+=strtol(s
, e
, 10)/60.0;
388 if(*e
==s
|| *e
==NULL
|| **e
!='\'') return deg
;
390 if(!isdigit(*s
) && *s
!='.') return NAN
;
391 deg
+=strtod(s
, e
)/3600.0;
392 if(*e
!=s
&& *e
!=NULL
&& **e
=='\'') (*e
)++;
396 int str2dd(char *s
, double *lat
, double *lon
){
402 if(c
=='+' || c
=='N'){
405 if(c
=='-' || c
=='S'){
409 *lat
=parse_dd_or_dms(s
, &e
);
410 if(isnan(*lat
) || e
==NULL
|| e
==s
|| *e
=='\0') return 0;
417 if(dir
<0) *lat
=-*lat
;
419 while(isspace(*e
)) e
++;
420 if(*e
=='\0') return 0;
424 if(c
=='+' || c
=='W'){
427 if(c
=='-' || c
=='E'){
431 *lon
=parse_dd_or_dms(s
, &e
);
432 if(isnan(*lon
) || e
==s
) return 0;
433 if(e
==NULL
|| *e
=='\0') return 1;
440 if(dir
<0) *lon
=-*lon
;