1 /*
2  * geoTime.c --
3  *
4  *	This file defines functions for manipulate date and times
5  *
6  * Copyright (c) 2004 Gordon D. Carrie
7  *
8  * Licensed under the Open Software License version 2.1
9  *
10  * Please send feedback to user0@tkgeomap.org
11  *
12  * @(#) $Id: geoTime.c,v 1.6 2007/04/20 15:08:58 tkgeomap Exp $
13  *
14  **********************************************************************
15  */
16 
17 #include <stdlib.h>
18 #include <math.h>
19 #include <tcl.h>
20 
21 #include "geography.h"
22 
23 /*
24  *------------------------------------------------------------------------
25  *
26  * GeoTime_CalSet --
27  *
28  * 	This function assigns values to a GeoTime_Cal structure.
29  *
30  * Results:
31  * 	Assigns values to a calendar time structure.
32  *
33  * Side effects:
34  * 	None.
35  *------------------------------------------------------------------------
36  */
37 
38 struct GeoTime_Cal
GeoTime_CalSet(year,month,day,hour,minute,second)39 GeoTime_CalSet(year, month, day, hour, minute, second)
40     int year;
41     int month;
42     int day;
43     int hour;
44     int minute;
45     double second;
46 {
47     struct GeoTime_Cal cal;
48     int s;
49     double fsec;
50 
51     s = floor(second);
52     fsec = second - s;
53     minute += s / 60;
54     s %= 60;
55     hour += minute / 60;
56     minute %= 60;
57     day += hour / 24;
58     hour %= 24;
59 
60     cal.year = year;
61     cal.month = month;
62     cal.day = day;
63     cal.hour = hour;
64     cal.minute = minute;
65     cal.second = s + fsec;
66     return cal;
67 }
68 
69 /*
70  *------------------------------------------------------------------------
71  *
72  * GeoTime_JulSet --
73  *
74  * 	This function assigns values to a GeoTime_Jul structure.
75  *
76  * Results:
77  * 	Assigns values to a Julian time structure.
78  *
79  * Side effects:
80  * 	None.
81  *
82  *------------------------------------------------------------------------
83  */
84 
85 struct GeoTime_Jul
GeoTime_JulSet(day,second)86 GeoTime_JulSet(day, second)
87     int day;
88     double second;
89 {
90     struct GeoTime_Jul jul;
91     int s;
92     double fsec;
93 
94     s = floor(second);
95     fsec = second - s;
96     day += s / 86400;
97     s %= 86400;
98     jul.day = day;
99     jul.second = s + fsec;
100     return jul;
101 }
102 
103 /*
104  *------------------------------------------------------------------------
105  *
106  * GeoTime_CalToJul --
107  *
108  *	This function converts a calendar time representation to Julian date.
109  *
110  * Results:
111  * 	Return value gives the Julian representation of a calendar time.
112  * Side effects:
113  *------------------------------------------------------------------------
114  */
115 
116 struct GeoTime_Jul
GeoTime_CalToJul(cal)117 GeoTime_CalToJul(cal)
118     struct GeoTime_Cal cal;	/* Time instant in calendar format */
119 {
120     int year = cal.year;
121     int month = cal.month;
122     int day = cal.day;
123     int hour = cal.hour;
124     int minute = cal.minute;
125     double second = cal.second;
126     struct GeoTime_Jul jul;	/* Return value */
127     int d;			/* Number of days in second */
128 
129     /*
130      * Compute Julian day.
131      * Ref. Henry F. Fliegel and Thomas C. Van Flandern, from
132      * http://serendipity.magnet.ch/hermetic/cal_stud/jdn.htm or
133      * http://aa.usno.navy.mil/faq/docs/JD_Formula.html
134      */
135 
136     jul.day =   (1461 * (year + 4800 + (month - 14) / 12)) / 4
137 	+ (367 * (month - 2 - 12 * ((month - 14) / 12))) / 12
138 	- (3 * ((year + 4900 + (month - 14) / 12) / 100)) / 4
139 	+ day - 32075;
140 
141     /*
142      * Compute total seconds.  If greater than 1 day, increment days.
143      */
144 
145     second = 3600.0 * hour + 60.0 * minute + second;
146     d = floor(second / 86400.0);
147     jul.day += d;
148     jul.second = second - d * 86400.0;
149     return jul;
150 }
151 
152 /*
153  *------------------------------------------------------------------------
154  *
155  * GeoTime_GetCal --
156  *
157  *	This function retrieves a calendar date and time from a GeoTime.
158  *
159  * Results:
160  * 	Return value gives the calendar representation of a Julian time.
161  * Side effects:
162  * 	None.
163  *
164  *------------------------------------------------------------------------
165  */
166 
167 struct GeoTime_Cal
GeoTime_JulToCal(jul)168 GeoTime_JulToCal(jul)
169     struct GeoTime_Jul jul;	/* Time instant in calendar form */
170 {
171     struct GeoTime_Cal cal;	/* Return value, calendar equivalent of jul */
172     int l, n, i, j;		/* Intermediaries */
173     int h, m;			/* Hour, minute */
174     int s;			/* Second */
175     double fsec;
176 
177     /*
178      * Compute month, day, and year from Julian date
179      * Ref. Henry F. Fliegel and Thomas C. Van Flandern,
180      * http://serendipity.magnet.ch/hermetic/cal_stud/jdn.htm
181      */
182 
183     l = jul.day + 68569;
184     n = (4 * l) / 146097;
185     l = l - (146097 * n + 3) / 4;
186     i = (4000 * (l + 1)) / 1461001;
187     l = l - (1461 * i) / 4 + 31;
188     j = (80 * l) / 2447;
189     cal.day = l - (2447 * j) / 80;
190     l = j / 11;
191     cal.month = j + 2 - (12 * l);
192     cal.year = 100 * (n - 49) + i + l;
193 
194     /*
195      * Convert seconds to clock time
196      */
197 
198     s = floor(jul.second);
199     fsec = jul.second - s;
200     h = s / 3600;
201     s %= 3600;
202     m = s / 60;
203     s %= 60;
204     if (h > 23) {
205 	cal.day += h / 24;
206 	h %= 24;
207     }
208     cal.hour = h;
209     cal.minute = m;
210     cal.second = s + fsec;
211     return cal;
212 }
213 
214 /*
215  *------------------------------------------------------------------------
216  *
217  * GeoTime_Incr --
218  *
219  *	This function increments a time instant.
220  *
221  * Results:
222  * 	This given time is incremented.
223  *
224  * Side effects:
225  * 	None.
226  *
227  *------------------------------------------------------------------------
228  */
229 
230 void
GeoTime_Incr(jul,ds)231 GeoTime_Incr(jul, ds)
232     struct GeoTime_Jul *jul;	/* GeoTime to increment */
233     double ds;			/* Increment, in seconds */
234 {
235     int d;
236     double s;
237 
238     s = jul->second + ds;
239     d = floor(s / 86400.0);
240     jul->day += d;
241     jul->second = s - d * 86400.0;
242 }
243 
244 /*
245  *------------------------------------------------------------------------
246  *
247  * GeoTime_Cmp --
248  *
249  *	Compare two times.
250  *
251  * Results:
252  * 	Return value is a collating code.
253  *	    -1 if jul1 is before jul2
254  *	     0 if jul1 is same time as jul2
255  *	     1 if jul1 is after jul2
256  *
257  * Side effects:
258  * 	None.
259  *
260  *------------------------------------------------------------------------
261  */
262 
263 int
GeoTime_Cmp(jul1,jul2)264 GeoTime_Cmp(jul1, jul2)
265     struct GeoTime_Jul jul1, jul2;	/* GeoTimes to compare */
266 {
267 
268     jul1 = GeoTime_JulSet(jul1.day, jul1.second);
269     jul2 = GeoTime_JulSet(jul2.day, jul2.second);
270     if (jul1.day > jul2.day) {
271 	return 1;
272     }
273     if (jul1.day < jul2.day) {
274 	return -1;
275     }
276     if (jul1.second > jul2.second) {
277 	return 1;
278     }
279     if (jul1.second < jul2.second) {
280 	return -1;
281     }
282     return 0;
283 }
284 
285 /*
286  *------------------------------------------------------------------------
287  *
288  * GeoTime_Diff --
289  *
290  *	Subtract one time from another.
291  *
292  * Results:
293  * 	Return value is the difference in seconds between two times.
294  *
295  * Side effects:
296  * 	None.
297  *
298  *------------------------------------------------------------------------
299  */
300 
301 double
GeoTime_Diff(jul1,jul2)302 GeoTime_Diff(jul1, jul2)
303     struct GeoTime_Jul jul1, jul2;	/* GeoTimes to compare */
304 {
305 
306     jul1 = GeoTime_JulSet(jul1.day, jul1.second);
307     jul2 = GeoTime_JulSet(jul2.day, jul2.second);
308     return (jul1.day - jul2.day) * 86400.0 + jul1.second - jul2.second;
309 }
310