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