source: XIOS/dev/branch_yushan_merged/src/calendar.cpp @ 1205

Last change on this file since 1205 was 1134, checked in by yushan, 7 years ago

branch merged with trunk r1130

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