source: XIOS/trunk/src/duration.cpp @ 550

Last change on this file since 550 was 550, checked in by rlacroix, 9 years ago

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.

  • Property copyright set to
    Software name : XIOS (Xml I/O Server)
    http://forge.ipsl.jussieu.fr/ioserver
    Creation date : January 2009
    Licence : CeCCIL version2
    see license file in root directory : Licence_CeCILL_V2-en.txt
    or http://www.cecill.info/licences/Licence_CeCILL_V2-en.html
    Holder : CEA/LSCE (Laboratoire des Sciences du CLimat et de l'Environnement)
    CNRS/IPSL (Institut Pierre Simon Laplace)
    Project Manager : Yann Meurdesoif
    yann.meurdesoif@cea.fr
File size: 4.8 KB
RevLine 
[219]1#include "duration.hpp"
2#include "date.hpp"
3#include "calendar.hpp"
[550]4#include "calendar_util.hpp"
[219]5
[335]6namespace xios
[219]7{
8      /// ////////////////////// Définitions ////////////////////// ///
[550]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 };
[219]18
19      ///---------------------------------------------------------------
20
[550]21      CDuration& CDuration::operator=(const CDuration& duration)
[219]22      {
[550]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;
[219]26      }
27
[550]28      StdOStream& operator<<(StdOStream& out, const CDuration& duration)
[219]29      {
[550]30        StdOStringStream sout;
31        bool forceOutput = true;
[219]32
[550]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;
[219]45      }
46
[539]47      StdIStream& operator>>(StdIStream& in , CDuration& duration)
[219]48      {
[539]49        duration = NoneDu;
50        double v = 1.0;
51        char   c = '/';
52        bool   invalidUnit = false;
53
54        do
55        {
56          in >> v >> c;
57          if (in.fail())
58            ERROR("StdIStream& operator>>(StdIStream& in , CDuration& duration)",
59                  << "Bad duration format: impossible to read a pair (value, unit).");
60
61          switch (c)
62          {
63            case 'y': duration.year   = v; break;
64            case 'd': duration.day    = v; break;
65            case 'h': duration.hour   = v; break;
66            case 's': duration.second = v; break;
67            case 'm':
68            {
69              in >> c;
70              if      (c == 'i') duration.minute = v;
71              else if (c == 'o') duration.month  = v;
72              else invalidUnit = true;
73              break;
[219]74            }
[539]75            case 't':
76            {
77              in >> c;
78              if (c == 's') duration.timestep = v;
79              else invalidUnit = true;
80              break;
81            }
82            default:
[550]83              invalidUnit = true;
[539]84              break;
85          }
86
87          if (invalidUnit)
88            ERROR("StdIStream& operator>>(StdIStream& in , CDuration& duration)",
89                  << "Bad duration format: invalid unit, unexpected '" << c << "' character.");
[550]90        } while (in.peek() != EOF); // check whether there is a next character to read
[539]91
92        return in;
[219]93      }
94
95      //-----------------------------------------------------------------
96
97      bool CDuration::isNone(void) const
98      {
[550]99        return (*this == NoneDu);
[219]100      }
101
102      //-----------------------------------------------------------------
[550]103
104      CDuration& CDuration::solveTimeStep(const CCalendar& c)
[436]105      {
[550]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      }
[448]115
[550]116      CDuration& CDuration::resolve(const CCalendar& c, bool noNegativeTime /*= false*/)
[219]117      {
[550]118        return c.resolve(*this, noNegativeTime);
[219]119      }
120
121      //-----------------------------------------------------------------
122
123      StdString CDuration::toString(void) const
124      {
[550]125        StdOStringStream oss; oss << *this;
126        return oss.str();
[219]127      }
128
[550]129      CDuration CDuration::FromString(const StdString& str)
[219]130      {
[550]131        CDuration dr = NoneDu;
132        StdIStringStream iss(str); iss >> dr;
133        return dr;
[219]134      }
[335]135} // namespace xios
[219]136
Note: See TracBrowser for help on using the repository browser.