GRASS 8 Programmer's Manual 8.6.0dev(2026)-5f4f7ad06c
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 */
53int datetime_change_from_to(DateTime *dt, int from, int to, int round)
54{
55 DateTime dummy, incr;
56 int pos;
57 int carry;
58 int ndays;
59 int dtfrom;
60
61 /* is 'dt' valid? */
63 return -1;
64
65 /* is new from/to valid for dt->mode? */
66 if (datetime_set_type(&dummy, dt->mode, from, to, 0) != 0)
67 return -2;
68
69 /* copy dt->from to local variable, then change it
70 in the structure so that increment works correctly for RELATIVE.
71 Otherwise, since increment "reduces" answers, performing carries,
72 we would carry to invalid units */
73
74 dtfrom = dt->from;
75
76 /* now set the from */
77 dt->from = from;
78
79 /* convert the "lost" lower elements to equiv value for the new 'from'
80 * NOTE: this only affects DATETIME_RELATIVE
81 * since absolute will have from==dt->from==YEAR
82 */
83 for (pos = dtfrom; pos < from; pos++) {
84 switch (pos) {
85 case DATETIME_YEAR:
86 dt->month += dt->year * 12;
87 dt->year = 0;
88 break;
89 case DATETIME_DAY:
90 dt->hour += dt->day * 24;
91 dt->day = 0;
92 break;
93 case DATETIME_HOUR:
94 dt->minute += dt->hour * 60;
95 dt->hour = 0;
96 break;
97 case DATETIME_MINUTE:
98 dt->second += dt->minute * 60.0;
99 dt->minute = 0;
100 break;
101 }
102 }
103
104 /* if losing precision, round
105 * round > 0 force up if any lost values not zero
106 * round ==0 increment by all lost values
107 */
108 if (to < dt->to) {
109 if (round > 0) {
110 int x;
111
112 x = datetime_is_absolute(dt) ? 1 : 0;
113
114 for (carry = 0, pos = dt->to; carry == 0 && pos > to; pos--) {
115 switch (pos) {
116 case DATETIME_MONTH:
117 if (dt->month != x)
118 carry = 1;
119 break;
120 case DATETIME_DAY:
121 if (dt->day != x)
122 carry = 1;
123 break;
124 case DATETIME_HOUR:
125 if (dt->hour != 0)
126 carry = 1;
127 break;
128 case DATETIME_MINUTE:
129 if (dt->minute != 0)
130 carry = 1;
131 break;
132 case DATETIME_SECOND:
133 if (dt->second != 0)
134 carry = 1;
135 break;
136 }
137 }
138
139 if (carry) {
140 make_incr(&incr, to, to, dt);
141
142 incr.year = 1;
143 incr.month = 1;
144 incr.day = 1;
145 incr.hour = 1;
146 incr.minute = 1;
147 incr.second = 1.0;
148
149 datetime_increment(dt, &incr);
150 }
151 }
152
153 if (round == 0) {
154 /*NEW*/ if (datetime_is_absolute(dt))
155 /*NEW*/ ndays = datetime_days_in_year(dt->year, dt->positive);
156 /*NEW*/
157 else
158 /*NEW*/ ndays = 0;
159
160 for (pos = dt->to; pos > to; pos--) {
161 make_incr(&incr, pos, pos, dt);
162
163 incr.year = dt->year;
164 incr.month = dt->month;
165 /*NEW*/ incr.day = dt->day + ndays / 2;
166 incr.hour = dt->hour;
167 incr.minute = dt->minute;
168 incr.second = dt->second;
169
170 datetime_increment(dt, &incr);
171 /*NEW*/ if (ndays > 0 && pos == DATETIME_DAY)
172 /*NEW*/ break;
173 }
174 }
175 }
176
177 /* set the new elements to zero */
178 for (pos = from; pos < dtfrom; pos++)
179 switch (pos) {
180 case DATETIME_YEAR:
181 dt->year = 0;
182 break;
183 case DATETIME_MONTH:
184 dt->month = 0;
185 break;
186 case DATETIME_DAY:
187 dt->day = 0;
188 break;
189 case DATETIME_HOUR:
190 dt->hour = 0;
191 break;
192 case DATETIME_MINUTE:
193 dt->minute = 0;
194 break;
195 case DATETIME_SECOND:
196 dt->second = 0;
197 break;
198 }
199
200 for (pos = to; pos > dt->to; pos--)
201 switch (pos) {
202 case DATETIME_YEAR:
203 dt->year = 0;
204 break;
205 case DATETIME_MONTH:
206 dt->month = 0;
207 break;
208 case DATETIME_DAY:
209 dt->day = 0;
210 break;
211 case DATETIME_HOUR:
212 dt->hour = 0;
213 break;
214 case DATETIME_MINUTE:
215 dt->minute = 0;
216 break;
217 case DATETIME_SECOND:
218 dt->second = 0;
219 break;
220 }
221
222 /* make sure that fracsec is zero if original didn't have seconds */
223 if (dt->to < DATETIME_SECOND)
224 dt->fracsec = 0;
225
226 /* now set the to */
227 dt->to = to;
228
229 return 0;
230}
231
232static void make_incr(DateTime *incr, int from, int to, DateTime *dt)
233{
234 datetime_set_type(incr, DATETIME_RELATIVE, from, to, 0);
237}
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
#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_is_negative(const DateTime *dt)
Returns: 1 if the DateTime is negative 0 otherwise.
Definition sign.c:34
void datetime_set_negative(DateTime *dt)
Makes the DateTime negative. (B.C. for ABSOLUTE DateTimes)
Definition sign.c:60
int datetime_is_valid_type(const DateTime *dt)
Returns: 1 if datetime_check_type() returns 0 0 if not.
int datetime_is_absolute(const DateTime *dt)
Returns: 1 if dt.mode is absolute 0 if not (even if dt.mode is not defined)
int datetime_set_type(DateTime *dt, int mode, int from, int to, int fracsec)
int datetime_is_relative(const DateTime *dt)
Returns: 1 if dt.mode is relative 0 if not (even if dt.mode is not defined)
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_days_in_year(int year, int ad)
returns the number of days in 'year'
int positive
Definition datetime.h:24
int month
Definition datetime.h:21
int year
Definition datetime.h:21
int mode
Definition datetime.h:18
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
#define x