Ignore:
Timestamp:
02/10/15 14:23:02 (9 years ago)
Author:
rlacroix
Message:

Add a new user defined calendar type.

A new calendar type "user_defined" is now available. This allows the users to create a custom calendar that we can configured to be suitable for planets other than the Earth.

An user defined calendar is always defined by two mandatory attributes:

  • day_length: the duration of a day, in seconds
  • and either:
    • month_length: an array containing the duration of each month, in days (the number of elements in the array is the number of months in a year)
    • or year_length: the duration of a year, in seconds (in that case, the calendar does not have months).

If the calendar has months (i.e. month_length attribute is set) and only in that case, it is possible to define leap years in order to compensate for the duration of an astronomical year not being a multiple of the day length. The leap years are defined by two mandatory attributes:

  • leap_year_month: the month to which the extra day will be added in case of leap year, expressed as an integer number in the range [1, numberOfMonths]
  • and leap_year_drift: the fraction of a day representing the yearly drift between the calendar year and the astronomical year, expressed as a real number in the range [0, 1).

Optionally, one can define the leap_year_drift_offset attribute to set the original drift at the beginning of the time origin's year, again expressed as a real number in the range [0, 1). If leap_year_drift_offset + leap_year_drift is greater or equal to 1, then the first year will be a leap year.

For example, the following configuration creates a Gregorian-like calendar:

<calendar type="user_defined" start_date="2012-03-01 15:00:00" time_origin="2012-02-28 15:00:00 + 1d" day_length="86400" month_lengths="(1, 12) [31 28 31 30 31 30 31 31 30 31 30 31]" leap_year_month="2" leap_year_drift="0.25" leap_year_drift_offset="0.75" />

Note that dates attributes must be written differently in the configuration file when using an user defined calendar without months:

  • if the year length is greater than the day length, the input format is year-day hh:min:sec instead of year-month-day hh:min:sec
  • if the day length is greater or equal to the year length, the input format is year hh:min:sec.

In all cases, it is still possible to use the date + duration notation to build a date (with both the date and duration parts being optional).

The Fortran interface has been updated accordingly so that xios_define_calendar can accept the new attributes necessary to define custom calendars.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • XIOS/trunk/src/calendar_util.cpp

    r549 r550  
    33namespace xios 
    44{ 
    5       /// ////////////////////// Définitions ////////////////////// /// 
    6  
    7       CDuration operator*(const double& scal, const CDuration& ddr) 
    8       { return (ddr * scal); } 
    9  
    10       CDuration operator-(const CDuration& ddr , const CDuration& dr) 
    11       { 
    12          CDuration dur(ddr); 
    13          dur.year -= dr.year;  dur.month  -= dr.month; dur.day    -= dr.day; 
    14          dur.hour -= dr.hour;  dur.minute -= dr.minute; dur.second -= dr.second; dur.timestep -= dr.timestep; 
    15          return (dur); 
    16       } 
    17  
    18       CDuration operator+(const CDuration& ddr , const CDuration& dr) 
    19       { 
    20          CDuration dur(ddr); 
    21          dur.year += dr.year;  dur.month  += dr.month; dur.day    += dr.day; 
    22          dur.hour += dr.hour;  dur.minute += dr.minute; dur.second += dr.second; dur.timestep += dr.timestep; 
    23          return (dur); 
    24       } 
    25  
    26       CDuration operator*(const CDuration& ddr , const double& scal) 
    27       { 
    28          CDuration dur(ddr); 
    29          dur.year *= scal;  dur.month  *= scal; dur.day    *= scal; 
    30          dur.hour *= scal;  dur.minute *= scal; dur.second *= scal; dur.timestep *= scal; 
    31          return (dur); 
    32       } 
    33  
    34       CDuration operator-(const CDuration& ddr) 
    35       { 
    36          CDuration dur(ddr); 
    37          dur.year   = -dur.year; 
    38          dur.month  = -dur.month; 
    39          dur.day    = -dur.day; 
    40          dur.hour   = -dur.hour; 
    41          dur.minute = -dur.minute; 
    42          dur.second = -dur.second; 
    43          dur.timestep = -dur.timestep; 
    44          return (dur); 
    45       } 
    46  
    47       //----------------------------------------------------------------- 
    48  
    49       CDate operator+(const CDate& dt, const CDuration& dr) 
    50       { 
    51          CDuration drr(dr); 
    52          int year = 0, month = 0, day = 0, hour = 0, minute = 0, second = 0; 
    53          const CCalendar& c = dt.getRelCalendar(); 
    54  
    55          drr.timestep = 0; 
    56          if (dr.timestep) 
    57          { 
    58             if (c.getTimeStep() == NoneDu) 
    59                ERROR("operator+(const CDate& dt, const CDuration& dr)", 
    60                      << "Impossible to use the timestep before it is set."); 
    61             drr = drr + dr.timestep * c.getTimeStep(); 
    62          } 
    63  
    64          drr.resolve(c); 
    65  
    66          // Ajustement des minutes par rapport aux secondes. 
    67          second += dt.getSecond() + drr.second; 
    68          if (second < 0) { minute--; second += c.getMinuteLength(); } 
    69          if (second >= c.getMinuteLength()) { minute++; second -= c.getMinuteLength(); } 
    70  
    71          // Ajustement des heures en fonction des minutes. 
    72          minute += dt.getMinute() + drr.minute; 
    73          if (minute < 0) { hour--; minute += c.getHourLength(); } 
    74          if (minute >= c.getHourLength()) { hour++; minute -= c.getHourLength(); } 
    75  
    76          // Ajustement des jours en fonction des heures. 
    77          hour += dt.getHour() + drr.hour; 
    78          if (hour < 0) { drr.day--; hour += c.getDayLength(); } 
    79          if (hour >= c.getDayLength()) { drr.day++; hour -= c.getDayLength(); } 
    80  
    81          // Ajustement des mois en fonction des jours. 
    82          CDate dtt(dt); 
    83          drr.day += dtt.getDay() - 1; 
    84          dtt.setDay(1); 
    85  
    86          if (drr.day >= 0) 
    87          { 
    88            for(; c.getMonthLength(dtt) <= drr.day; dtt.addMonth(1)) 
    89            { drr.day -= c.getMonthLength(dtt); drr.month += 1; } 
    90  
    91            day = drr.day + 1; 
    92          } 
    93          else 
    94          { 
    95            dtt.addMonth(-1); 
    96            drr.month -= 1; 
    97            for(; c.getMonthLength(dtt) < -drr.day; dtt.addMonth(-1)) 
    98            { drr.day += c.getMonthLength(dtt); drr.month -= 1; } 
    99            day = c.getMonthLength(dtt) + drr.day + 1; 
    100          } 
    101  
    102 /* 
    103          if (day <  0) { drr.month --; day += c.getMonthLength(dtt); } 
    104          if (day > c.getMonthLength(dtt)) { drr.month ++; day -= c.getMonthLength(dtt); } // << ProblÚme ici 
    105          if (day == 0){ day = c.getMonthLength(dtt); drr.month --; } 
    106 */ 
    107          drr.resolve(c); 
    108  
    109          // Ajustement des années en fonction des mois. 
    110          month += dt.getMonth() + drr.month; 
    111          if (month < 0) { drr.year--; month += c.getYearLength(); } 
    112          if (month > c.getYearLength()) { drr.year++; month -= c.getYearLength(); } 
    113          if (month == 0){ month = c.getYearLength(); drr.year--; } 
    114  
    115          year += dt.getYear() + drr.year; 
    116  
    117          return (CDate(c, year, month, day, hour, minute, second)); 
    118       } 
    119  
    120       CDate operator-(const CDate& dt, const CDuration& dr) { return (dt + (-dr)); } 
    121  
    122       //----------------------------------------------------------------- 
    123  
    124       CDuration operator-(const CDate& dt0, const CDate& dt1) 
    125       { 
    126          // TODO :: Vérifier que les deux dates (dt0 et dt1) ont une référence vers le même calendrier. 
    127          CDuration dur = 
    128          { dt0.getYear() - dt1.getYear(), dt0.getMonth()  - dt1.getMonth() , dt0.getDay()    - dt1.getDay(), 
    129            dt0.getHour() - dt1.getHour(), dt0.getMinute() - dt1.getMinute(), dt0.getSecond() - dt1.getSecond() }; 
    130          return (dur.resolve(dt0.getRelCalendar())); 
    131       } 
    132  
    133       //----------------------------------------------------------------- 
    134  
    135       /// Les opérateurs de comparaison. (Non testés pour le moment) 
    136  
    137       bool operator==(const CDuration& ddr, const CDuration& dr) 
    138       { 
    139          return ((ddr.year == dr.year)&& (ddr.month  == dr.month) && (dr.day    == ddr.day)&& 
    140                  (ddr.hour == dr.hour)&& (ddr.minute == dr.minute)&& (dr.second == ddr.second)&& 
    141                  (ddr.timestep == dr.timestep)); 
    142       } 
    143  
    144       bool operator!=(const CDuration& ddr, const CDuration& dr) 
    145       { 
    146          return !(ddr == dr); 
    147       } 
    148  
    149       bool operator==(const CDate& dt0, const CDate& dt1) 
    150       { 
    151          // TODO :: Vérifier que les deux dates (dt0 et dt1) ont une référence vers le même calendrier. 
    152          return ((dt0.getYear() == dt1.getYear())&& (dt0.getMonth()  == dt1.getMonth()) && (dt1.getDay()    == dt0.getDay())&& 
    153                  (dt0.getHour() == dt1.getHour())&& (dt0.getMinute() == dt1.getMinute())&& (dt1.getSecond() == dt0.getSecond())); 
    154       } 
    155  
    156       bool operator< (const CDate& dt0, const CDate& dt1) 
    157       { 
    158          // TODO :: Vérifier que les deux dates (dt0 et dt1) ont une référence vers le même calendrier. 
    159          if   (dt0.getYear()  < dt1.getYear()) 
    160          { 
    161             return true; 
    162          } 
    163          else if (dt0.getYear() == dt1.getYear()) 
    164          { 
    165             if   (dt0.getMonth()  < dt1.getMonth()) 
     5    /// ////////////////////// Définitions ////////////////////// /// 
     6 
     7    CDuration operator*(const double& scal, const CDuration& ddr) 
     8    { return (ddr * scal); } 
     9 
     10    CDuration operator-(const CDuration& ddr, const CDuration& dr) 
     11    { 
     12      CDuration dur(ddr); 
     13      dur.year -= dr.year; dur.month  -= dr.month;  dur.day    -= dr.day; 
     14      dur.hour -= dr.hour; dur.minute -= dr.minute; dur.second -= dr.second; dur.timestep -= dr.timestep; 
     15      return dur; 
     16    } 
     17 
     18    CDuration operator+(const CDuration& ddr, const CDuration& dr) 
     19    { 
     20      CDuration dur(ddr); 
     21      dur.year += dr.year; dur.month  += dr.month;  dur.day    += dr.day; 
     22      dur.hour += dr.hour; dur.minute += dr.minute; dur.second += dr.second; dur.timestep += dr.timestep; 
     23      return dur; 
     24    } 
     25 
     26    CDuration operator*(const CDuration& ddr, const double& scal) 
     27    { 
     28      CDuration dur(ddr); 
     29      dur.year *= scal; dur.month  *= scal; dur.day    *= scal; 
     30      dur.hour *= scal; dur.minute *= scal; dur.second *= scal; dur.timestep *= scal; 
     31      return dur; 
     32    } 
     33 
     34    CDuration operator-(const CDuration& ddr) 
     35    { 
     36      CDuration dur(ddr); 
     37      dur.year     = -dur.year; 
     38      dur.month    = -dur.month; 
     39      dur.day      = -dur.day; 
     40      dur.hour     = -dur.hour; 
     41      dur.minute   = -dur.minute; 
     42      dur.second   = -dur.second; 
     43      dur.timestep = -dur.timestep; 
     44      return dur; 
     45    } 
     46 
     47    //----------------------------------------------------------------- 
     48 
     49    CDate operator+(const CDate& dt, const CDuration& dr) 
     50    { 
     51      CDuration drr(dr); 
     52      int year = 0, month = 0, day = 0, hour = 0, minute = 0, second = 0; 
     53      const CCalendar& c = dt.getRelCalendar(); 
     54      const bool calendarHasMonths = (c.getYearLength() > 0); 
     55 
     56      drr.timestep = 0; 
     57      if (dr.timestep) 
     58      { 
     59        if (c.getTimeStep() == NoneDu) 
     60          ERROR("operator+(const CDate& dt, const CDuration& dr)", 
     61                << "Impossible to use the timestep before it is set."); 
     62        drr = drr + dr.timestep * c.getTimeStep(); 
     63      } 
     64 
     65      // Handle the time part of the date 
     66      drr.second += dt.getSecond(); 
     67      drr.minute += dt.getMinute(); 
     68      drr.hour   += dt.getHour(); 
     69 
     70      if (!calendarHasMonths) // Handle the day and year immediately if there is no months 
     71      { 
     72        drr.day  += dt.getDay() - 1; 
     73        drr.year += dt.getYear(); 
     74      } 
     75 
     76      drr.resolve(c, true); // Force the time to be positive 
     77 
     78      second = drr.second; 
     79      minute = drr.minute; 
     80      hour   = drr.hour; 
     81 
     82      if (calendarHasMonths) 
     83      { 
     84        // Ajustement des mois en fonction des jours. 
     85        CDate dtt(dt); 
     86        drr.day += dtt.getDay() - 1; 
     87        dtt.setDay(1); 
     88 
     89        if (drr.day >= 0) 
     90        { 
     91          for(; c.getMonthLength(dtt) <= drr.day; dtt.addMonth(1)) 
     92          { drr.day -= c.getMonthLength(dtt); drr.month += 1; } 
     93 
     94          day = drr.day + 1; 
     95        } 
     96        else 
     97        { 
     98          dtt.addMonth(-1); 
     99          drr.month -= 1; 
     100          for(; c.getMonthLength(dtt) < -drr.day; dtt.addMonth(-1)) 
     101          { drr.day += c.getMonthLength(dtt); drr.month -= 1; } 
     102          day = c.getMonthLength(dtt) + drr.day + 1; 
     103        } 
     104 
     105        drr.resolve(c); 
     106 
     107        // Ajustement des années en fonction des mois. 
     108        month += dt.getMonth() + drr.month; 
     109        if (month < 0) { drr.year--; month += c.getYearLength(); } 
     110        if (month > c.getYearLength()) { drr.year++; month -= c.getYearLength(); } 
     111        if (month == 0){ month = c.getYearLength(); drr.year--; } 
     112 
     113        year += dt.getYear() + drr.year; 
     114      } 
     115      else // if (!calendarHasMonths) 
     116      { 
     117        day   = drr.day + 1; 
     118        month = 1; 
     119        year  = drr.year; 
     120      } 
     121 
     122      return (CDate(c, year, month, day, hour, minute, second)); 
     123    } 
     124 
     125    CDate operator-(const CDate& dt, const CDuration& dr) { return (dt + (-dr)); } 
     126 
     127    //----------------------------------------------------------------- 
     128 
     129    CDuration operator-(const CDate& dt0, const CDate& dt1) 
     130    { 
     131      // TODO :: Vérifier que les deux dates (dt0 et dt1) ont une référence vers le même calendrier. 
     132      CDuration dur = 
     133      { dt0.getYear() - dt1.getYear(), dt0.getMonth()  - dt1.getMonth() , dt0.getDay()   - dt1.getDay(), 
     134        dt0.getHour() - dt1.getHour(), dt0.getMinute() - dt1.getMinute(), dt0.getSecond() - dt1.getSecond() }; 
     135      return (dur.resolve(dt0.getRelCalendar())); 
     136    } 
     137 
     138    //----------------------------------------------------------------- 
     139 
     140    /// Les opérateurs de comparaison. (Non testés pour le moment) 
     141 
     142    bool operator==(const CDuration& ddr, const CDuration& dr) 
     143    { 
     144      return ((ddr.year == dr.year) && (ddr.month  == dr.month)  && (dr.day    == ddr.day) && 
     145              (ddr.hour == dr.hour) && (ddr.minute == dr.minute) && (dr.second == ddr.second) && 
     146              (ddr.timestep == dr.timestep)); 
     147    } 
     148 
     149    bool operator!=(const CDuration& ddr, const CDuration& dr) 
     150    { 
     151      return !(ddr == dr); 
     152    } 
     153 
     154    bool operator==(const CDate& dt0, const CDate& dt1) 
     155    { 
     156      // TODO :: Vérifier que les deux dates (dt0 et dt1) ont une référence vers le même calendrier. 
     157      return ((dt0.getYear() == dt1.getYear()) && (dt0.getMonth()  == dt1.getMonth())  && (dt1.getDay()    == dt0.getDay()) && 
     158              (dt0.getHour() == dt1.getHour()) && (dt0.getMinute() == dt1.getMinute()) && (dt1.getSecond() == dt0.getSecond())); 
     159    } 
     160 
     161    bool operator<(const CDate& dt0, const CDate& dt1) 
     162    { 
     163      // TODO :: Vérifier que les deux dates (dt0 et dt1) ont une référence vers le même calendrier. 
     164      if (dt0.getYear() < dt1.getYear()) 
     165      { 
     166        return true; 
     167      } 
     168      else if (dt0.getYear() == dt1.getYear()) 
     169      { 
     170        if (dt0.getMonth() < dt1.getMonth()) 
     171        { 
     172          return true; 
     173        } 
     174        else if (dt0.getMonth() == dt1.getMonth()) 
     175        { 
     176          if (dt0.getDay() < dt1.getDay()) 
     177          { 
     178             return true; 
     179          } 
     180          else if (dt0.getDay() == dt1.getDay()) 
     181          { 
     182            if (dt0.getHour() < dt1.getHour()) 
    166183            { 
    167                return true; 
     184              return true; 
    168185            } 
    169             else if (dt0.getMonth() == dt1.getMonth()) 
     186            else if (dt0.getHour() == dt1.getHour()) 
    170187            { 
    171                if   (dt0.getDay()  < dt1.getDay()) 
    172                { 
    173                    return true; 
    174                } 
    175                else if (dt0.getDay() == dt1.getDay()) 
    176                { 
    177                   if    (dt0.getHour()  < dt1.getHour()) 
    178                   { 
    179                      return true; 
    180                   } 
    181                   else if (dt0.getHour() == dt1.getHour()) 
    182                   { 
    183                      if   (dt0.getMinute()  < dt1.getMinute()) 
    184                      { 
    185                         return true; 
    186                      } 
    187                      else if (dt0.getMinute() == dt1.getMinute()) 
    188                      { 
    189                         if (dt0.getSecond() < dt1.getSecond()) 
    190                            return true; 
    191                      } 
    192                   } 
    193                } 
     188              if (dt0.getMinute() < dt1.getMinute()) 
     189              { 
     190                return true; 
     191              } 
     192              else if (dt0.getMinute() == dt1.getMinute()) 
     193              { 
     194                if (dt0.getSecond() < dt1.getSecond()) 
     195                  return true; 
     196              } 
    194197            } 
    195          } 
    196          return false; 
    197       } 
    198  
    199       //----------------------------------------------------------------- 
    200  
    201       bool operator!=(const CDate& dt0, const CDate& dt1){ return !(dt1 == dt0); } 
    202       bool operator> (const CDate& dt0, const CDate& dt1){ return (dt1 < dt0); } 
    203       bool operator>=(const CDate& dt0, const CDate& dt1){ return ((dt0 > dt1) || (dt1 == dt0)); } 
    204       bool operator<=(const CDate& dt0, const CDate& dt1){ return ((dt0 < dt1) || (dt1 == dt0)); } 
    205  
    206       ///---------------------------------------------------------------- 
     198          } 
     199        } 
     200      } 
     201      return false; 
     202    } 
     203 
     204    //----------------------------------------------------------------- 
     205 
     206    bool operator!=(const CDate& dt0, const CDate& dt1) { return !(dt1 == dt0); } 
     207    bool operator> (const CDate& dt0, const CDate& dt1) { return (dt1 < dt0); } 
     208    bool operator>=(const CDate& dt0, const CDate& dt1) { return (dt0 > dt1 || dt1 == dt0); } 
     209    bool operator<=(const CDate& dt0, const CDate& dt1) { return (dt0 < dt1 || dt1 == dt0); } 
     210 
     211    ///---------------------------------------------------------------- 
    207212 
    208213} // namespace xios 
Note: See TracChangeset for help on using the changeset viewer.