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