GRASS Programmer's Manual
6.4.2(2012)
|
00001 /* 00002 * Copyright (C) 1995. Bill Brown <brown@gis.uiuc.edu> & Michael Shapiro 00003 * 00004 * This program is free software under the GPL (>=v2) 00005 * Read the file GPL.TXT coming with GRASS for details. 00006 */ 00007 #include <grass/datetime.h> 00008 00009 static void make_incr(); 00010 00011 00054 int datetime_change_from_to(DateTime * dt, int from, int to, int round) 00055 { 00056 DateTime dummy, incr; 00057 int pos; 00058 int carry; 00059 int ndays; 00060 int dtfrom; 00061 00062 /* is 'dt' valid? */ 00063 if (!datetime_is_valid_type(dt)) 00064 return -1; 00065 00066 /* is new from/to valid for dt->mode? */ 00067 if (datetime_set_type(&dummy, dt->mode, from, to, 0) != 0) 00068 return -2; 00069 00070 /* copy dt->from to local variable, then change it 00071 in the structure so that increment works correctly for RELATIVE. 00072 Otherwise, since increment "reduces" answers, performing carries, 00073 we would carry to invalid units */ 00074 00075 dtfrom = dt->from; 00076 00077 /* now set the from */ 00078 dt->from = from; 00079 00080 /* convert the "lost" lower elements to equiv value for the new 'from' 00081 * NOTE: this only affects DATETIME_RELATIVE 00082 * since absolute will have from==dt->from==YEAR 00083 */ 00084 for (pos = dtfrom; pos < from; pos++) { 00085 switch (pos) { 00086 case DATETIME_YEAR: 00087 dt->month += dt->year * 12; 00088 dt->year = 0; 00089 break; 00090 case DATETIME_DAY: 00091 dt->hour += dt->day * 24; 00092 dt->day = 0; 00093 break; 00094 case DATETIME_HOUR: 00095 dt->minute += dt->hour * 60; 00096 dt->hour = 0; 00097 break; 00098 case DATETIME_MINUTE: 00099 dt->second += dt->minute * 60.0; 00100 dt->minute = 0; 00101 break; 00102 } 00103 } 00104 00105 /* if losing precision, round 00106 * round > 0 force up if any lost values not zero 00107 * round ==0 increment by all lost values 00108 */ 00109 if (to < dt->to) { 00110 if (round > 0) { 00111 int x; 00112 00113 x = datetime_is_absolute(dt) ? 1 : 0; 00114 00115 for (carry = 0, pos = dt->to; carry == 0 && pos > to; pos--) { 00116 switch (pos) { 00117 case DATETIME_MONTH: 00118 if (dt->month != x) 00119 carry = 1; 00120 break; 00121 case DATETIME_DAY: 00122 if (dt->day != x) 00123 carry = 1; 00124 break; 00125 case DATETIME_HOUR: 00126 if (dt->hour != 0) 00127 carry = 1; 00128 break; 00129 case DATETIME_MINUTE: 00130 if (dt->minute != 0) 00131 carry = 1; 00132 break; 00133 case DATETIME_SECOND: 00134 if (dt->second != 0) 00135 carry = 1; 00136 break; 00137 } 00138 } 00139 00140 if (carry) { 00141 make_incr(&incr, to, to, dt); 00142 00143 incr.year = 1; 00144 incr.month = 1; 00145 incr.day = 1; 00146 incr.hour = 1; 00147 incr.minute = 1; 00148 incr.second = 1.0; 00149 00150 datetime_increment(dt, &incr); 00151 } 00152 } 00153 00154 if (round == 0) { 00155 /*NEW*/ if (datetime_is_absolute(dt)) 00156 /*NEW*/ ndays = datetime_days_in_year(dt->year, dt->positive); 00157 /*NEW*/ 00158 else 00159 /*NEW*/ ndays = 0; 00160 00161 for (pos = dt->to; pos > to; pos--) { 00162 make_incr(&incr, pos, pos, dt); 00163 00164 incr.year = dt->year; 00165 incr.month = dt->month; 00166 /*NEW*/ incr.day = dt->day + ndays / 2; 00167 incr.hour = dt->hour; 00168 incr.minute = dt->minute; 00169 incr.second = dt->second; 00170 00171 datetime_increment(dt, &incr); 00172 /*NEW*/ if (ndays > 0 && pos == DATETIME_DAY) 00173 /*NEW*/ break; 00174 } 00175 } 00176 } 00177 00178 /* set the new elements to zero */ 00179 for (pos = from; pos < dtfrom; pos++) 00180 switch (pos) { 00181 case DATETIME_YEAR: 00182 dt->year = 0; 00183 break; 00184 case DATETIME_MONTH: 00185 dt->month = 0; 00186 break; 00187 case DATETIME_DAY: 00188 dt->day = 0; 00189 break; 00190 case DATETIME_HOUR: 00191 dt->hour = 0; 00192 break; 00193 case DATETIME_MINUTE: 00194 dt->minute = 0; 00195 break; 00196 case DATETIME_SECOND: 00197 dt->second = 0; 00198 break; 00199 } 00200 00201 for (pos = to; pos > dt->to; pos--) 00202 switch (pos) { 00203 case DATETIME_YEAR: 00204 dt->year = 0; 00205 break; 00206 case DATETIME_MONTH: 00207 dt->month = 0; 00208 break; 00209 case DATETIME_DAY: 00210 dt->day = 0; 00211 break; 00212 case DATETIME_HOUR: 00213 dt->hour = 0; 00214 break; 00215 case DATETIME_MINUTE: 00216 dt->minute = 0; 00217 break; 00218 case DATETIME_SECOND: 00219 dt->second = 0; 00220 break; 00221 } 00222 00223 /* make sure that fracsec is zero if original didn't have seconds */ 00224 if (dt->to < DATETIME_SECOND) 00225 dt->fracsec = 0; 00226 00227 /* now set the to */ 00228 dt->to = to; 00229 00230 return 0; 00231 } 00232 00233 static void make_incr(DateTime * incr, int from, int to, DateTime * dt) 00234 { 00235 datetime_set_type(incr, DATETIME_RELATIVE, from, to, 0); 00236 if (datetime_is_relative(dt) && datetime_is_negative(dt)) 00237 datetime_set_negative(incr); 00238 }