GRASS 8 Programmer's Manual 8.6.0dev(2026)-56a9afeb9f
Loading...
Searching...
No Matches
diff.c
Go to the documentation of this file.
1/*
2 * Copyright (C) 1995. Bill Brown <brown@gis.uiuc.edu> & Michael Shapiro
3 *
4 * This program is free software under the GPL (>=v2)
5 * Read the file GPL.TXT coming with GRASS for details.
6 */
7#include <stdlib.h>
8#include <grass/datetime.h>
9#include "math.h"
10
11/*************************************************************/
12/*
13 This performs the formula: result = a - b;
14
15 both a and b must be absolute.
16 result will be relative
17 If a is "earlier" than b, then result should be set negative.
18
19 b must be no more "precise" than a.
20 (a copy of b is "extended" to the precision of a)
21
22 datetime_copy (tb, b)
23 datetime_reset_from_to (tb, b.from, a.to, a.fracsec))
24
25
26 If result.to == SECOND, then result.fracsec is a.fracsec
27
28 result will have the following from/to based on a.to:
29
30 result
31 a.to from to
32 YEAR YEAR YEAR
33 MONTH YEAR MONTH
34 DAY DAY DAY
35 HOUR DAY HOUR
36 MINUTE DAY MINUTE
37 SECOND DAY SECOND
38
39 If either 'a' or 'b' has a timezone, both must have a timezone.
40 The difference will account for the differences in the time zones.
41 */
42
43static int _datetime_ymd_to_ddays(const DateTime *, double *);
44static int _datetime_compare(const DateTime *, const DateTime *);
45
46/*!
47 * \brief
48 *
49 *
50 * This performs the formula: result = a - b;
51 * <ul>
52 <li> both a and b must be absolute.
53 * </li>
54 <li> result will be relative
55 * </li>
56 <li> If a is "earlier" than b, then result will be set negative.
57 * </li>
58 <li> b must be no more "precise" than a.
59 * (a copy of b is "extended" to the precision of a)
60 * </li>
61 <li> If result.to == SECOND, then result.fracsec is a.fracsec
62 * </li>
63 <li> result will have the following from/to based
64 * on a.to: result a.to from to YEAR YEAR YEAR MONTH YEAR
65 * MONTH DAY DAY DAY HOUR DAY HOUR MINUTE DAY
66 * MINUTE SECOND DAY SECOND [LAYOUT ??? - see HTML]
67 * </li>
68 <li> If either 'a' or 'b' has a timezone, both must have a timezone. The
69 * difference will account for the differences in the time zones.
70 </li></ul>
71
72 *
73 * \param a
74 * \param b
75 * \param result
76 * \return int
77 */
78int datetime_difference(const DateTime *a, const DateTime *b, DateTime *result)
79{
80 DateTime tb, ta, *early, *late;
81 int compare, tzmin;
82
83 /* if not both absolute, return error */
84
87
88 datetime_copy(&ta, a);
89 if (datetime_get_timezone(&ta, &tzmin) == 0 ||
91 if (datetime_get_timezone(&ta, &tzmin) == 0 &&
95 }
96 else
97 return datetime_error(-1,
98 "only one opperand contains valid timezone");
99 }
100
101 /* initialize result */
104 ta.to, ta.fracsec);
105 compare = _datetime_compare(&ta, &tb);
106 if (compare > 0) {
107 early = &tb;
108 late = &ta;
109 result->positive = 1;
110 }
111 else if (compare < 0) {
112 early = &ta;
113 late = &tb;
114 result->positive = 0;
115 }
116 else { /* equal */
117 return (0);
118 }
119
120 /* now the work */
122 int dm;
123
124 if (ta.positive == tb.positive) {
125 /* change if we use doubles! */
126 result->year = abs(late->year - early->year);
127 }
128 else {
129 result->year = late->year + early->year - 2;
130 }
131 dm = late->month - early->month;
132 if (dm >= 0)
133 result->month = dm;
134 else {
135 result->year -= 1;
136 result->month = dm + 12;
137 }
138 }
139 else {
141 double latedays, earlydays;
142
144 _datetime_ymd_to_ddays(early, &earlydays);
145 /* copy day -> down */
146 erel.day = earlydays;
147 erel.hour = early->hour;
148 erel.minute = early->minute;
149 erel.second = early->second;
150
152 _datetime_ymd_to_ddays(late, &latedays);
153 /* copy day -> down */
154 lrel.day = latedays;
155 lrel.hour = late->hour;
156 lrel.minute = late->minute;
157 lrel.second = late->second;
158
161
162 /* copy erel back to result */
163 result->day = erel.day;
164 result->hour = erel.hour;
165 result->minute = erel.minute;
166 result->second = erel.second;
167
168 /* need carry? */
169 }
170
171 return (0);
172}
173
174/*************************************************************/
175/* returns 1 if a is later than b,
176 -1 if a is earlier than a,
177 0 otherwise
178 */
179/* only looks at from-to fields defined by a */
180
181static int _datetime_compare(const DateTime *a, const DateTime *b)
182{
183 int i;
184
185 if (a->positive && !b->positive)
186 return (1);
187 else if (b->positive && !a->positive)
188 return (-1);
189
190 /* same signs */
191 for (i = a->from; i <= a->to; i++) {
192 switch (i) {
193
194 case DATETIME_SECOND:
195 if (a->second > b->second)
196 return (1);
197 else if (a->second < b->second)
198 return (-1);
199 break;
200
201 case DATETIME_MINUTE:
202 if (a->minute > b->minute)
203 return (1);
204 else if (a->minute < b->minute)
205 return (-1);
206 break;
207
208 case DATETIME_HOUR:
209 if (a->hour > b->hour)
210 return (1);
211 else if (a->hour < b->hour)
212 return (-1);
213 break;
214
215 case DATETIME_DAY:
216 if (a->day > b->day)
217 return (1);
218 else if (a->day < b->day)
219 return (-1);
220 break;
221
222 case DATETIME_MONTH:
223 if (a->month > b->month)
224 return (1);
225 else if (a->month < b->month)
226 return (-1);
227 break;
228
229 case DATETIME_YEAR: /* only place sign matters */
230 if (a->positive) {
231 if (a->year > b->year)
232 return (1);
233 else if (a->year < b->year)
234 return (-1);
235 }
236 else {
237 if (a->year < b->year)
238 return (1);
239 else if (a->year > b->year)
240 return (-1);
241 }
242 break;
243 }
244 }
245 return (0);
246}
247
248/*************************************************************/
249
250static int _datetime_ymd_to_ddays(const DateTime *dtymd, double *days)
251{ /* note extra precision! */
252 int yr, mo;
253
254 *days = 0.0;
255
256 if (dtymd->positive) {
257 *days = dtymd->day - 1; /* start w/ days - 1 */
258 for (mo = dtymd->month - 1; mo > 0; mo--) { /* add earlier months */
259 *days += datetime_days_in_month(dtymd->year, mo, dtymd->positive);
260 }
261 for (yr = dtymd->year - 1; yr > 0; yr--) { /* add earlier years */
262 *days += datetime_days_in_year(yr, dtymd->positive);
263 }
264 }
265 else {
266 for (yr = dtymd->year - 1; yr > 0; yr--) { /* add later years */
267 *days += datetime_days_in_year(yr, dtymd->positive);
268 }
269 for (mo = 12; mo >= dtymd->month;
270 mo--) { /*add current & later months */
271 *days += datetime_days_in_month(dtymd->year, mo, dtymd->positive);
272 }
273 *days -= dtymd->day; /* subtract current days */
274 }
275
276 return 0;
277}
278
279/*************************************************************/
280
281/*************************************************************/
#define DATETIME_MONTH
Definition datetime.h:11
#define DATETIME_DAY
Definition datetime.h:12
#define DATETIME_HOUR
Definition datetime.h:13
#define DATETIME_SECOND
Definition datetime.h:15
#define DATETIME_MINUTE
Definition datetime.h:14
#define DATETIME_RELATIVE
Definition datetime.h:5
#define DATETIME_YEAR
Definition datetime.h:10
int datetime_change_to_utc(DateTime *dt)
Return datetime_change_timezone (dt, 0);.
Definition tz2.c:57
int datetime_error(int code, char *msg)
record 'code' and 'msg' as error code/msg (in static variables) code==0 will clear the error (ie set ...
int datetime_get_timezone(const DateTime *dt, int *minutes)
returns 0 on success
Definition tz1.c:44
int datetime_days_in_month(int year, int month, int ad)
returns number of days in 'month' of a particular 'year'
int datetime_set_type(DateTime *dt, int mode, int from, int to, int fracsec)
void datetime_invert_sign(DateTime *dt)
Definition sign.c:71
int datetime_increment(DateTime *src, DateTime *incr)
This function changes the 'src' date/time data based on the 'incr' The type (mode/from/to) of the 'sr...
Definition incr1.c:67
int datetime_change_from_to(DateTime *dt, int from, int to, int round)
Changes the from/to of the type for dt. The 'from/to' must be legal values for the mode of dt; (if th...
Definition change.c:53
int datetime_set_increment_type(const DateTime *src, DateTime *incr)
src must be legal This is a convenience routine which is implemented as follows:
Definition incr3.c:82
int datetime_days_in_year(int year, int ad)
returns the number of days in 'year'
int datetime_in_interval_year_month(int x)
void datetime_copy(DateTime *src, const DateTime *dst)
Copies the DateTime [into/from ???] src.
int compare(const void *a, const void *b)
Definition dgraph.c:168
int datetime_difference(const DateTime *a, const DateTime *b, DateTime *result)
This performs the formula: result = a - b;.
Definition diff.c:78
double b
Definition r_raster.c:39
int positive
Definition datetime.h:24
int month
Definition datetime.h:21
int year
Definition datetime.h:21
int to
Definition datetime.h:19
double second
Definition datetime.h:23
int fracsec
Definition datetime.h:20
int from
Definition datetime.h:19
int hour
Definition datetime.h:22
int minute
Definition datetime.h:22
int day
Definition datetime.h:21