GRASS Programmer's Manual  6.4.2(2012)
change.c
Go to the documentation of this file.
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 }
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines