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/duration.cpp

    r539 r550  
    22#include "date.hpp" 
    33#include "calendar.hpp" 
     4#include "calendar_util.hpp" 
    45 
    56namespace xios 
    67{ 
    78      /// ////////////////////// Définitions ////////////////////// /// 
    8       const CDuration Year   = {1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0}, 
    9                       Month  = {0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0}, 
    10                       Week   = {0.0, 0.0, 7.0, 0.0, 0.0, 0.0, 0.0}, 
    11                       Day    = {0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0}, 
    12                       Hour   = {0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0}, 
    13                       Minute = {0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0}, 
    14                       Second = {0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0}, 
    15                       NoneDu = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0}, 
    16                       TimeStep = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0}; 
     9      const CDuration Year     = { 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 }, 
     10                      Month    = { 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0 }, 
     11                      Week     = { 0.0, 0.0, 7.0, 0.0, 0.0, 0.0, 0.0 }, 
     12                      Day      = { 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0 }, 
     13                      Hour     = { 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0 }, 
     14                      Minute   = { 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0 }, 
     15                      Second   = { 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0 }, 
     16                      TimeStep = { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0 }, 
     17                      NoneDu   = { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 }; 
    1718 
    1819      ///--------------------------------------------------------------- 
    1920 
    20       CDuration & CDuration::operator=(const CDuration & duration) 
     21      CDuration& CDuration::operator=(const CDuration& duration) 
    2122      { 
    22          year = duration.year;  month  = duration.month ; day    = duration.day; 
    23          hour = duration.hour;  minute = duration.minute; second = duration.second; timestep=duration.timestep ; 
    24          return (*this); 
     23        year = duration.year; month  = duration.month; day    = duration.day; 
     24        hour = duration.hour; minute = duration.minute; second = duration.second; timestep = duration.timestep; 
     25        return *this; 
    2526      } 
    2627 
    27       StdOStream & operator<<(StdOStream & out, const CDuration & duration) 
     28      StdOStream& operator<<(StdOStream& out, const CDuration& duration) 
    2829      { 
    29          StdOStringStream sout; 
    30          bool testValue = true; 
    31          if(duration.year   != 0.0) { testValue = false; sout << duration.year   << "y " ; } 
    32          if(duration.month  != 0.0) { testValue = false; sout << duration.month  << "mo "; } 
    33          if(duration.day    != 0.0) { testValue = false; sout << duration.day    << "d " ; } 
    34          if(duration.hour   != 0.0) { testValue = false; sout << duration.hour   << "h " ; } 
    35          if(duration.minute != 0.0) { testValue = false; sout << duration.minute << "mi "; } 
    36          if(duration.second != 0.0) { testValue = false; sout << duration.second << "s " ; } 
    37          if(duration.timestep != 0.0 || testValue)       { sout << duration.timestep << "ts " ; } 
     30        StdOStringStream sout; 
     31        bool forceOutput = true; 
    3832 
    39          // << suppression de l'espace en fin de chaîne. 
    40          out << (sout.str().substr(0, sout.str().size()-1)); 
    41          return (out); 
     33        if (duration.year   != 0.0) { forceOutput = false; sout << duration.year   << "y "; } 
     34        if (duration.month  != 0.0) { forceOutput = false; sout << duration.month  << "mo "; } 
     35        if (duration.day    != 0.0) { forceOutput = false; sout << duration.day    << "d "; } 
     36        if (duration.hour   != 0.0) { forceOutput = false; sout << duration.hour   << "h "; } 
     37        if (duration.minute != 0.0) { forceOutput = false; sout << duration.minute << "mi "; } 
     38        if (duration.second != 0.0) { forceOutput = false; sout << duration.second << "s "; } 
     39        if (duration.timestep != 0.0 || forceOutput)     { sout << duration.timestep << "ts "; } 
     40 
     41        // suppression de l'espace en fin de chaîne. 
     42        StdString strOut = sout.str(); 
     43        out << strOut.erase(strOut.size() - 1); 
     44        return out; 
    4245      } 
    4346 
     
    7881            } 
    7982            default: 
    80               invalidUnit = true;  
     83              invalidUnit = true; 
    8184              break; 
    8285          } 
     
    8588            ERROR("StdIStream& operator>>(StdIStream& in , CDuration& duration)", 
    8689                  << "Bad duration format: invalid unit, unexpected '" << c << "' character."); 
    87         } while (in.peek() != EOF); // check whether there is a next character to read  
     90        } while (in.peek() != EOF); // check whether there is a next character to read 
    8891 
    8992        return in; 
     
    9497      bool CDuration::isNone(void) const 
    9598      { 
    96          if ((year == 0) && (month  == 0) && (day    == 0) && 
    97              (hour == 0) && (minute == 0) && (second == 0) && (timestep == 0)) 
    98             return (true); 
    99          return (false); 
     99        return (*this == NoneDu); 
    100100      } 
    101101 
    102102      //----------------------------------------------------------------- 
    103       CDuration & CDuration::solveTimeStep(const CCalendar & c) 
     103 
     104      CDuration& CDuration::solveTimeStep(const CCalendar& c) 
    104105      { 
    105         CDuration timeStep=c.getTimeStep() ; 
    106         second +=timestep*timeStep.second ;  
    107         minute +=timestep*timeStep.minute ;  
    108         hour +=timestep*timeStep.hour ;  
    109         day +=timestep*timeStep.day ;  
    110         month +=timestep*timeStep.month ;  
    111         year +=timestep*timeStep.year ;  
    112         timestep = 0 ; 
     106        CDuration timeStep = c.getTimeStep(); 
     107        second += timestep * timeStep.second; 
     108        minute += timestep * timeStep.minute; 
     109        hour   += timestep * timeStep.hour; 
     110        day    += timestep * timeStep.day; 
     111        month  += timestep * timeStep.month; 
     112        year   += timestep * timeStep.year; 
     113        timestep = 0.0; 
     114      } 
    113115 
    114       } 
    115                 
    116          
    117       CDuration & CDuration::resolve(const CCalendar & c) 
     116      CDuration& CDuration::resolve(const CCalendar& c, bool noNegativeTime /*= false*/) 
    118117      { 
    119          // Simplification de l'écriture des minutes. 
    120          second += modf(minute, &minute) * (float)c.getMinuteLength(); 
    121          minute += int(second)/c.getMinuteLength(); second = int(second)%c.getMinuteLength(); 
    122  
    123          // Simplification de l'écriture des heures. 
    124          minute += modf(hour , &hour) * (float)c.getHourLength(); 
    125          hour   += int(minute)/c.getHourLength(); minute = int(minute)%c.getHourLength(); 
    126  
    127          // Simplification de l'écriture des jours. 
    128          hour   += modf(day, &day) * (float)c.getDayLength(); 
    129          day    += int(hour)  /c.getDayLength(); hour   = int(hour)%c.getDayLength(); 
    130  
    131          // > Aucune équivalence jour - mois fixée par avance. // 
    132  
    133          // Simplification de l'écriture des années. 
    134          month  += modf(year, &year) * (float)c.getYearLength(); 
    135          year   += int(month) /c.getYearLength(); month  = int(month)%c.getYearLength(); 
    136          return (*this); 
     118        return c.resolve(*this, noNegativeTime); 
    137119      } 
    138120 
     
    141123      StdString CDuration::toString(void) const 
    142124      { 
    143          const  CDuration & own = *this; 
    144          StdOStringStream oss; oss << own; 
    145          return (oss.str()); 
     125        StdOStringStream oss; oss << *this; 
     126        return oss.str(); 
    146127      } 
    147128 
    148       CDuration CDuration::FromString(const StdString & str) 
     129      CDuration CDuration::FromString(const StdString& str) 
    149130      { 
    150          CDuration dr = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0}; 
    151          StdIStringStream iss(str); iss >> dr; 
    152          return (dr); 
     131        CDuration dr = NoneDu; 
     132        StdIStringStream iss(str); iss >> dr; 
     133        return dr; 
    153134      } 
    154  
    155       ///--------------------------------------------------------------- 
    156  
    157  
    158135} // namespace xios 
    159136 
Note: See TracChangeset for help on using the changeset viewer.