source: XIOS/dev/branch_openmp/src/calendar.cpp @ 1460

Last change on this file since 1460 was 1460, checked in by yushan, 3 years ago

branch_openmp merged with XIOS_DEV_CMIP6@1459

  • 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: 11.4 KB
Line 
1#include "calendar.hpp"
2#include "duration.hpp"
3#include "date.hpp"
4#include "calendar_util.hpp"
5
6namespace xios
7{
8      /// ////////////////////// Définitions ////////////////////// ///
9      CCalendar::CCalendar(void)
10         : CObject()
11         , step(0)
12         , initDate(*this)
13         , timeOrigin(*this)
14         , currentDate(*this)
15      {}
16
17      CCalendar::CCalendar(const StdString& id)
18               : CObject(id)
19               , step(0)
20               , initDate(*this)
21               , timeOrigin(*this)
22               , currentDate(*this)
23      {}
24
25      CCalendar::CCalendar(const StdString& id,
26                           int yr, int mth, int d,
27                           int hr /*= 0*/, int min /*= 0*/, int sec /*= 0*/)
28               : CObject(id)
29               , step(0)
30               , initDate(*this)
31               , timeOrigin(*this)
32               , currentDate(*this)
33      {
34        initializeDate(yr, mth, d, hr, min, sec);
35      }
36
37      CCalendar::CCalendar(const StdString& id, const CDate& startDate)
38               : CObject(id)
39               , step(0)
40               , initDate(startDate)
41               , timeOrigin(startDate)
42               , currentDate(startDate)
43      {
44        // Initialize the dates only in the derivated classes
45        // since we want to use the overloaded virtual functions
46      }
47
48      CCalendar::CCalendar(const StdString& id, const CDate& startDate, const CDate& timeOrigin)
49               : CObject(id)
50               , step(0)
51               , initDate(startDate)
52               , timeOrigin(timeOrigin)
53               , currentDate(startDate)
54      {
55        // Initialize the dates only in the derivated classes
56        // since we want to use the overloaded virtual functions
57      }
58
59      void CCalendar::initializeDate()
60      {
61        if (!initDate.setRelCalendar(*this))
62          ERROR("CCalendar::initializeDate()",
63                "initDate: Bad format or date not conform to the calendar");
64        if (!timeOrigin.setRelCalendar(*this))
65          ERROR("CCalendar::initializeDate()",
66                "timeOrigin: Bad format or date not conform to the calendar");
67        if (!currentDate.setRelCalendar(*this))
68          ERROR("CCalendar::initializeDate()",
69                "currentDate: Bad format or date not conform to the calendar");
70      }
71
72      void CCalendar::initializeDate(int yr, int mth, int d,
73                                     int hr /*= 0*/, int min /*= 0*/, int sec /*= 0*/)
74      {
75        initDate = CDate(*this, yr, mth, d, hr, min, sec);
76        timeOrigin = initDate;
77        currentDate = initDate;
78      }
79
80      void CCalendar::initializeDate(const StdString& dateStr)
81      {
82        initDate = CDate::FromString(dateStr, *this);
83        timeOrigin = initDate;
84        currentDate = initDate;
85      }
86
87      void CCalendar::initializeDate(const StdString& dateStr, const StdString& timeOriginStr)
88      {
89        initDate = CDate::FromString(dateStr, *this);
90        timeOrigin = CDate::FromString(timeOriginStr, *this);
91        currentDate = initDate;
92      }
93
94      CCalendar::~CCalendar(void)
95      { /* Ne rien faire de plus */ }
96
97      ///---------------------------------------------------------------
98
99      StdString CCalendar::toString(void) const
100      {
101         StdOStringStream oss;
102         oss <<   "[type: "   << this->getId()
103             << ", start: "   << this->initDate
104             << ", current: " << this->currentDate << "]";
105         return (oss.str());
106      }
107
108      void CCalendar::fromString(const StdString& str)
109      { ERROR("CCalendar::fromString(str)",
110               << "[ str = " << str << "] Not implemented yet !"); }
111
112      //-----------------------------------------------------------------
113
114      void CCalendar::setTimeStep(const CDuration& timestep)
115      {
116        if (timestep.timestep)
117          ERROR("CCalendar::setTimeStep(const CDuration& timestep)",
118                << "Circular definition of the timestep: the timestep cannot refer to itself.");
119        this->timestep = timestep;
120      }
121
122      int CCalendar::getStep(void) const
123      {
124        return step;
125      }
126
127      const CDate& CCalendar::update(int step)
128      {
129        #pragma omp critical (_output)
130        info(20) << "update step : " << step << " timestep " << this->timestep << std::endl;
131        this->step = step;
132        return (this->currentDate = this->getInitDate() + step * this->timestep);
133      }
134
135      //-----------------------------------------------------------------
136
137      void CCalendar::setInitDate(const CDate& initDate)
138      {
139        if (&initDate.getRelCalendar() != this)
140          ERROR("CCalendar::setInitDate(const CDate& initDate)",
141                << "The init date cannot be attached to another calendar.");
142        this->initDate = initDate;
143      }
144
145      void CCalendar::setTimeOrigin(const CDate& timeOrigin)
146      {
147        if (&timeOrigin.getRelCalendar() != this)
148          ERROR("CCalendar::setInitDate(const CDate& timeOrigin)",
149                << "The time origin cannot be attached to another calendar.");
150        this->timeOrigin = timeOrigin;
151      }
152
153      //-----------------------------------------------------------------
154
155      const CDuration& CCalendar::getTimeStep(void) const { return this->timestep; }
156      const CDate& CCalendar::getInitDate(void) const     { return this->initDate; }
157      const CDate& CCalendar::getTimeOrigin(void) const   { return this->timeOrigin; }
158      const CDate& CCalendar::getCurrentDate(void) const  { return this->currentDate; }
159
160      //-----------------------------------------------------------------
161
162      int CCalendar::getMonthLength(const CDate& date) const
163      { // Retourne la durée du mois en jour.
164        static const int NoLeapMonthLength[] =
165          { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
166        return NoLeapMonthLength[date.getMonth() - 1];
167      }
168
169      StdString CCalendar::getType(void) const { return StdString(this->getId()); }
170
171      int CCalendar::getYearTotalLength(const CDate& date) const { return (365 * 86400); }
172
173      int CCalendar::getYearLength  (void) const { return 12; }
174      int CCalendar::getDayLength   (void) const { return 24; }
175      int CCalendar::getHourLength  (void) const { return 60; }
176      int CCalendar::getMinuteLength(void) const { return 60; }
177      int CCalendar::getDayLengthInSeconds(void) const { return getDayLength() * getHourLength() * getMinuteLength(); }
178
179      bool CCalendar::hasLeapYear() const { return false; }
180
181      StdString CCalendar::getMonthName(int monthId) const
182      {
183        static const StdString MonthNames[] =
184          { "january", "february", "march",     "april" ,  "may",      "june",
185            "july",    "august",   "september", "october", "november", "december" };
186        return MonthNames[monthId - 1];
187      }
188
189      const StdString CCalendar::getMonthShortName(int monthId) const
190      { StdString value = this->getMonthName(monthId); value.resize(3); return value; }
191
192      CDuration& CCalendar::resolve(CDuration& dur, bool noNegativeTime /*= false*/) const
193      {
194        const int hourLengthInSeconds = getHourLength() * getMinuteLength();
195
196        // Simplify the days, hours, minutes and seconds.
197        // First convert them to seconds
198        Time t = Time(modf(dur.day, &dur.day) * getDayLengthInSeconds()
199                        + (dur.hour * getHourLength() + dur.minute) * getMinuteLength() + dur.second);
200        // Then convert back to days
201        dur.day += int(t / getDayLengthInSeconds());
202        t %= getDayLengthInSeconds();
203
204        // Do we allow hour, minute, second to be negative?
205        if (noNegativeTime)
206        {
207          // If we don't, we remove some days until the time is positive
208          while (t < 0)
209          {
210            t += getDayLengthInSeconds();
211            dur.day -= 1.0;
212          }
213        }
214
215        // hours
216        dur.hour = int(t / hourLengthInSeconds);
217        t %= hourLengthInSeconds;
218        // minutes
219        dur.minute = int(t / getMinuteLength());
220        // secondes
221        dur.second = int(t % getMinuteLength());
222
223        // Nothing to do for the months yet since this depends on an actual date
224
225        // Simplify the years
226        dur.month  += modf(dur.year, &dur.year) * getYearLength();
227        dur.year   += int(dur.month) / getYearLength(); dur.month = int(dur.month) % getYearLength();
228
229        return dur;
230      }
231
232      /*! Parse a date using a generic parser. */
233      void CCalendar::parseDateDefault(StdIStream& in, CDate& date)
234      {
235        char sep = '-'; // Le caractÚre c est utilisé pour "recueillir" les séparateurs "/" et ":".
236        char c;
237
238        // Default initialize the date
239        int year = 00, month  = 01, day    = 01;
240        int hour = 00, minute = 00, second = 00;
241
242        in >> year >> c;
243        if (c == sep)
244        {
245          in >> month >> c;
246          if (c == sep)
247          {
248            in >> day;
249            c = in.get();
250            sep = ' ';
251            if (c == sep)
252            {
253              in >> hour >> c;
254              sep = ':';
255              if (c == sep)
256              {
257                in >> minute >> c;
258                if (c == sep)
259                {
260                  in >> second;
261                  in >> c;
262                }
263              }
264            }
265          }
266        }
267
268        date.setDate(year, month, day, hour, minute, second);
269
270        // Delay the verification until we get a calendar we can compare the date to
271        if (date.hasRelCalendar() && !date.checkDate())
272          ERROR("void parseDateDefault(StdIStream& in, CDate& date)",
273                << "Bad date format or not conform to calendar");
274
275        if (c == '+') // We will be adding a duration to the date
276        {
277          CDuration dur;
278          in >> dur;
279          date = date + dur;
280        }
281        else if (!in.eof())
282          ERROR("void parseDateDefault(StdIStream& in, CDate& date)",
283                << "Invalid date format: unexpected trailing character(s)");
284      }
285
286      /*! Parse a date using the calendar's parser. */
287      void CCalendar::parseDate(StdIStream& in, CDate& date) const
288      {
289        parseDateDefault(in, date);
290      }
291
292      /*! Test if a date is valid with regard to the current calendar. */
293      bool CCalendar::checkDate(CDate& date) const
294      {
295        bool isValid = true;
296
297        // Vérification de la valeur du mois.
298        if (date.getMonth() < 1)
299        { isValid = false; date.setMonth(1); }
300        else if (date.getMonth() > getYearLength())
301        { isValid = false; date.setMonth(getYearLength()); }
302
303        // Vérification de la valeur du jour.
304        if (date.getDay() < 1)
305        { isValid = false; date.setDay(1); }
306        else if (date.getDay() > getMonthLength(*this))
307        { isValid = false; date.setDay(getMonthLength(*this)); }
308
309        // Vérification de la valeur de l'heure.
310        if (date.getHour() < 0)
311        { isValid = false; date.setHour(0); }
312        else if (date.getHour() >= getDayLength())
313        { isValid = false; date.setHour(getDayLength() - 1); }
314
315        // Vérification de la valeur des minutes.
316        if (date.getMinute() < 0)
317        { isValid = false; date.setMinute(0); }
318        else if (date.getMinute() >= getHourLength())
319        { isValid = false; date.setMinute(getHourLength() - 1); }
320
321        // Vérification de la valeur des secondes.
322        if (date.getSecond() < 0)
323        { isValid = false; date.setSecond(0); }
324        else if (date.getSecond() >= getMinuteLength())
325        { isValid = false; date.setSecond(getMinuteLength() - 1); }
326
327        return isValid;
328      }
329} // namespace xios
Note: See TracBrowser for help on using the repository browser.