GRASS GIS 8 Programmer's Manual 8.3.2(2024)-exported
Loading...
Searching...
No Matches
change.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 <grass/datetime.h>
8
9static void make_incr(DateTime *, int, int, DateTime *);
10
11/*!
12 * \brief
13 *
14 * Changes the from/to of the type for dt.
15 * The 'from/to' must be legal
16 * values for the mode of dt; (if they are not legal, then the original values
17 * are preserved, dt is not changed).
18 * Returns:
19 * 0 OK
20 * -1 invalid 'dt'
21 * -2 invalid 'from/to' <br>
22 <ul>
23 <li> round =
24 * negative implies floor() [decrease magnitude]
25 * 0 implies normal rounding, [incr/decr magnitude]
26 * positive implies ceil() [increase magnitude]
27 </li>
28 <li> If dt.from < 'from' (losing "lower" elements), convert the "lost"
29 * values to the equivalent value for the new 'from' Lost elements are then set
30 * to zero. (This case can only occur for dt.mode relative):
31 * months += lost years * 12 ; years = 0
32 * hours += lost days * 24 ; days = 0
33 * minutes += lost hours * 60 ; hours = 0
34 * seconds += lost minutes * 60.0 ; minutes = 0
35 </li>
36 <li> If dt.from > 'from' (adding "lower" elements), the new elements are set
37 * to zero.
38 </li>
39 <li> If dt.to < 'to' (adding "higher" elements), the new elements are set to
40 * zero.
41 </li>
42 <li> If dt.to > 'to' (losing "higher" elements), the the new 'to' is
43 * adjusted according to the value for 'round' After rounding the "lost"
44 * elements are set to zero.
45 </li></ul>
46 *
47 * \param dt
48 * \param from
49 * \param to
50 * \param round
51 * \return int
52 */
53
54int datetime_change_from_to(DateTime *dt, int from, int to, int round)
55{
56 DateTime dummy, incr;
57 int pos;
58 int carry;
59 int ndays;
60 int dtfrom;
61
62 /* is 'dt' valid? */
64 return -1;
65
66 /* is new from/to valid for dt->mode? */
67 if (datetime_set_type(&dummy, dt->mode, from, to, 0) != 0)
68 return -2;
69
70 /* copy dt->from to local variable, then change it
71 in the structure so that increment works correctly for RELATIVE.
72 Otherwise, since increment "reduces" answers, performing carries,
73 we would carry to invalid units */
74
75 dtfrom = dt->from;
76
77 /* now set the from */
78 dt->from = from;
79
80 /* convert the "lost" lower elements to equiv value for the new 'from'
81 * NOTE: this only affects DATETIME_RELATIVE
82 * since absolute will have from==dt->from==YEAR
83 */
84 for (pos = dtfrom; pos < from; pos++) {
85 switch (pos) {
86 case DATETIME_YEAR:
87 dt->month += dt->year * 12;
88 dt->year = 0;
89 break;
90 case DATETIME_DAY:
91 dt->hour += dt->day * 24;
92 dt->day = 0;
93 break;
94 case DATETIME_HOUR:
95 dt->minute += dt->hour * 60;
96 dt->hour = 0;
97 break;
98 case DATETIME_MINUTE:
99 dt->second += dt->minute * 60.0;
100 dt->minute = 0;
101 break;
102 }
103 }
104
105 /* if losing precision, round
106 * round > 0 force up if any lost values not zero
107 * round ==0 increment by all lost values
108 */
109 if (to < dt->to) {
110 if (round > 0) {
111 int x;
112
113 x = datetime_is_absolute(dt) ? 1 : 0;
114
115 for (carry = 0, pos = dt->to; carry == 0 && pos > to; pos--) {
116 switch (pos) {
117 case DATETIME_MONTH:
118 if (dt->month != x)
119 carry = 1;
120 break;
121 case DATETIME_DAY:
122 if (dt->day != x)
123 carry = 1;
124 break;
125 case DATETIME_HOUR:
126 if (dt->hour != 0)
127 carry = 1;
128 break;
129 case DATETIME_MINUTE:
130 if (dt->minute != 0)
131 carry = 1;
132 break;
133 case DATETIME_SECOND:
134 if (dt->second != 0)
135 carry = 1;
136 break;
137 }
138 }
139
140 if (carry) {
141 make_incr(&incr, to, to, dt);
142
143 incr.year = 1;
144 incr.month = 1;
145 incr.day = 1;
146 incr.hour = 1;
147 incr.minute = 1;
148 incr.second = 1.0;
149
150 datetime_increment(dt, &incr);
151 }
152 }
153
154 if (round == 0) {
155 /*NEW*/ if (datetime_is_absolute(dt))
156 /*NEW*/ ndays = datetime_days_in_year(dt->year, dt->positive);
157 /*NEW*/
158 else
159 /*NEW*/ ndays = 0;
160
161 for (pos = dt->to; pos > to; pos--) {
162 make_incr(&incr, pos, pos, dt);
163
164 incr.year = dt->year;
165 incr.month = dt->month;
166 /*NEW*/ incr.day = dt->day + ndays / 2;
167 incr.hour = dt->hour;
168 incr.minute = dt->minute;
169 incr.second = dt->second;
170
171 datetime_increment(dt, &incr);
172 /*NEW*/ if (ndays > 0 && pos == DATETIME_DAY)
173 /*NEW*/ break;
174 }
175 }
176 }
177
178 /* set the new elements to zero */
179 for (pos = from; pos < dtfrom; pos++)
180 switch (pos) {
181 case DATETIME_YEAR:
182 dt->year = 0;
183 break;
184 case DATETIME_MONTH:
185 dt->month = 0;
186 break;
187 case DATETIME_DAY:
188 dt->day = 0;
189 break;
190 case DATETIME_HOUR:
191 dt->hour = 0;
192 break;
193 case DATETIME_MINUTE:
194 dt->minute = 0;
195 break;
196 case DATETIME_SECOND:
197 dt->second = 0;
198 break;
199 }
200
201 for (pos = to; pos > dt->to; pos--)
202 switch (pos) {
203 case DATETIME_YEAR:
204 dt->year = 0;
205 break;
206 case DATETIME_MONTH:
207 dt->month = 0;
208 break;
209 case DATETIME_DAY:
210 dt->day = 0;
211 break;
212 case DATETIME_HOUR:
213 dt->hour = 0;
214 break;
215 case DATETIME_MINUTE:
216 dt->minute = 0;
217 break;
218 case DATETIME_SECOND:
219 dt->second = 0;
220 break;
221 }
222
223 /* make sure that fracsec is zero if original didn't have seconds */
224 if (dt->to < DATETIME_SECOND)
225 dt->fracsec = 0;
226
227 /* now set the to */
228 dt->to = to;
229
230 return 0;
231}
232
233static void make_incr(DateTime *incr, int from, int to, DateTime *dt)
234{
235 datetime_set_type(incr, DATETIME_RELATIVE, from, to, 0);
238}
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:54
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:68
int datetime_days_in_year(int year, int ad)
returns the number of days in 'year'
Definition misc.c:39
int datetime_is_negative(const DateTime *dt)
Returns: 1 if the DateTime is negative 0 otherwise.
Definition sign.c:36
void datetime_set_negative(DateTime *dt)
Makes the DateTime negative. (B.C. for ABSOLUTE DateTimes)
Definition sign.c:64
int datetime_is_valid_type(const DateTime *dt)
Returns: 1 if datetime_check_type() returns 0 0 if not.
Definition type.c:77
int datetime_is_absolute(const DateTime *dt)
Returns: 1 if dt.mode is absolute 0 if not (even if dt.mode is not defined)
Definition type.c:168
int datetime_set_type(DateTime *dt, int mode, int from, int to, int fracsec)
Definition type.c:36
int datetime_is_relative(const DateTime *dt)
Returns: 1 if dt.mode is relative 0 if not (even if dt.mode is not defined)
Definition type.c:184
#define x