source: XIOS/trunk/src/date.cpp @ 544

Last change on this file since 544 was 544, checked in by rlacroix, 6 years ago

Fix: The conversion of a date to a number of seconds since the time origin was wrong.

Remove the work around in nc4_data_output.cpp which hid this bug.

Also backport this fix in XIOS 1.0.

  • 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.0 KB
Line 
1#include "date.hpp"
2#include "calendar.hpp"
3#include "calendar_type.hpp"
4#include <boost/date_time/gregorian/gregorian.hpp>
5#include <boost/date_time/posix_time/posix_time.hpp>
6
7using namespace boost::posix_time ;
8using namespace boost::gregorian ;
9
10namespace xios
11{
12      /// ////////////////////// Définitions ////////////////////// ///
13      CDate::CDate(void)
14         : relCalendar(NULL)
15         , year(0), month(1) , day(1)
16         , hour(0), minute(0), second(0)
17      {}
18
19      CDate::CDate(const CCalendar& calendar)
20         : relCalendar(&calendar)
21         , year(0), month(1) , day(1)
22         , hour(0), minute(0), second(0)
23      {}
24     
25      CDate::CDate(const CCalendar& calendar,
26                   int yr, int mth, int d,
27                   int hr, int min, int sec)
28         : relCalendar(&calendar)
29         , year(yr), month(mth) , day(d)
30         , hour(hr), minute(min), second(sec)
31      {
32         if(!this->checkDate())
33         {
34            DEBUG(<< "La date initialisée a été modifiée "
35                  << "car elle était incorrecte par rapport au calendrier souhaité.");
36         }
37      }
38
39      CDate::CDate(const CDate& date)
40            : relCalendar(date.relCalendar),
41              year(date.year), month(date.month)  , day(date.day),
42              hour(date.hour), minute(date.minute), second(date.second)
43      {
44        // Delay the verification until we get a calendar we can compare the date to
45        if (relCalendar && !checkDate())
46        {
47          DEBUG(<< "La date initialisée a été modifiée "
48                << "car elle était incorrecte par rapport au calendrier souhaité.");
49        }
50      }
51
52      CDate::~CDate(void)
53      { /* Ne rien faire de plus */ }
54
55      ///---------------------------------------------------------------
56
57      CDate & CDate::operator=(const CDate & date)
58      {
59         relCalendar = date.relCalendar;
60         year = date.year; month  = date.month ; day    = date.day;
61         hour = date.hour; minute = date.minute; second = date.second;
62         return (*this);
63      }
64
65      StdOStream & operator<<(StdOStream & out, const CDate & date)
66      {
67         std::streamsize s ; 
68         char c ;
69
70
71         int width=4 ;
72         double maxSize=10000 ;
73         while(date.year>=maxSize)
74         {
75           maxSize*=10 ;
76           width++ ;
77         }
78         s = out.width (width);  c = out.fill ('0') ; out << date.year << '-';
79
80         s = out.width (2);  c = out.fill ('0') ; out << date.month << '-';
81         s = out.width (2);  c = out.fill ('0') ; out << date.day << ' ';
82         s = out.width (2);  c = out.fill ('0') ; out << date.hour << ':';
83         s = out.width (2);  c = out.fill ('0') ; out << date.minute << ':';
84         s = out.width (2);  c = out.fill ('0') ; out << date.second ;
85
86         return (out);
87      }
88
89      StdIStream & operator>>(StdIStream & in, CDate & date) // Non testée.
90      {
91        char sep = '-'; // Le caractÚre c est utilisé pour "recueillir" les séparateurs "/" et ":".
92        char c ;
93         
94        in >> date.year >> c ;
95        if (c==sep)
96        {
97          in >> date.month >> c ;
98          if (c==sep)
99          {
100            in >> date.day  ;
101            c=in.get();
102            sep=' ' ;
103            if (c==sep)
104            {
105              in >> date.hour >> c ;
106              sep=':' ;
107              if (c==sep) 
108              {
109                in>>date.minute >> c;
110                if (c==sep)
111                {
112                  in >> date.second;
113                  // Delay the verification until we get a calendar we can compare the date to
114                  if (date.relCalendar && !date.checkDate())
115                    ERROR("StdIStream & operator >> (StdIStream & in, CDate & date)",
116                          << "Bad date format or not conform to calendar");
117                  return (in);
118                }
119              }
120            }
121          }
122        }
123        ERROR("StdIStream & operator >> (StdIStream & in, CDate & date)",<<"Bad date format or not conform to calendar" );
124        return (in);
125      }
126
127      CDate::operator Time(void) const // Non vérifiée, pas optimisée ...
128      {
129         // This will check that a calendar was correctly associated to the date
130         const CCalendar& c = getRelCalendar();
131
132         // Todo : Tester si la date courante est supérieure à la date initiale.
133         Time retvalue = - c.getNbSecond(c.getTimeOrigin())
134                         + c.getNbSecond(*this);
135
136         if ((c.getId().compare("D360")    == 0) ||
137             (c.getId().compare("AllLeap") == 0) ||
138             (c.getId().compare("NoLeap")  == 0))
139         return (retvalue + (getYear() - c.getTimeOrigin().getYear())
140                                       * c.getYearTotalLength(*this));
141
142         for(CDate _d(c.getTimeOrigin());
143            _d.getYear() < getYear(); _d.setYear(_d.getYear()+1))
144            retvalue += c.getYearTotalLength(_d);
145         return (retvalue);
146      }
147
148      //----------------------------------------------------------------
149
150      bool CDate::checkDate(void)
151      {
152         bool retValue = true;
153
154         // This will check that a calendar was correctly associated to the date
155         const CCalendar& c = getRelCalendar();
156
157         // Vérification de la valeur du mois.
158         if (month  < 1) { retValue = false; month  = 1; }
159         if (month  > c.getYearLength())
160         { retValue = false; month = c.getYearLength(); }
161
162         // Vérification de la valeur du jour.
163         if (day    < 1) { retValue = false; day  = 1; }
164         if (day    > c.getMonthLength(*this))
165         { retValue = false; day = c.getMonthLength(*this); }
166
167         // Vérification de la valeur de l'heure.
168         if (hour   < 0) { retValue = false; hour  = 0; }
169         if (hour   >= c.getDayLength())
170         { retValue = false; hour = c.getDayLength() - 1; }
171
172         // Vérification de la valeur des minutes.
173         if (minute < 0) { retValue = false; minute = 0; }
174         if (minute >= c.getHourLength())
175         { retValue = false; minute = c.getHourLength() - 1; }
176
177         // Vérification de la valeur des secondes.
178         if (second < 0) { retValue = false; second = 0; }
179         if (second >= c.getMinuteLength())
180         { retValue = false; second = c.getMinuteLength() - 1; }
181
182         return retValue;
183      }
184
185      //----------------------------------------------------------------
186
187      int CDate::getYear  (void) const { return (this->year  ); }
188      int CDate::getMonth (void) const { return (this->month ); }
189      int CDate::getDay   (void) const { return (this->day   ); }
190      int CDate::getHour  (void) const { return (this->hour  ); }
191      int CDate::getMinute(void) const { return (this->minute); }
192      int CDate::getSecond(void) const { return (this->second); }
193
194      //----------------------------------------------------------------
195
196      const CCalendar& CDate::getRelCalendar(void) const
197      {
198        if (!this->relCalendar)
199          ERROR("const CCalendar& CDate::getRelCalendar(void) const",
200                "Invalid state: The date is not associated with any calendar.");
201        return (*this->relCalendar);
202      }
203
204      bool CDate::hasRelCalendar(void) const
205      { return (this->relCalendar != NULL); }
206
207      //----------------------------------------------------------------
208
209      void CDate::setYear  (int newyear)   { this->year   = newyear; }
210      void CDate::setMonth (int newmonth)  { this->month  = newmonth; }
211      void CDate::setDay   (int newday)    { this->day    = newday; }
212      void CDate::setHour  (int newhour)   { this->hour   = newhour; }
213      void CDate::setMinute(int newminute) { this->minute = newminute; }
214      void CDate::setSecond(int newsecond) { this->second = newsecond; }
215
216      void CDate::setDate(int yr, int mth, int d, int hr, int min, int sec)
217      {
218        this->year   = yr;
219        this->month  = mth;
220        this->day    = d;
221        this->hour   = hr;
222        this->minute = min;
223        this->second = sec;
224      }
225
226      //----------------------------------------------------------------
227
228      void CDate::addMonth (int value)
229      {// Value doit être égale à 1 ou -1.
230         this->month += value;
231         if (this->month == 13) { year++; this->month = 1 ; }
232         if (this->month == 0 ) { year--; this->month = 12; }
233      }
234
235      //----------------------------------------------------------------
236
237      bool CDate::setRelCalendar(const CCalendar& relCalendar)
238      {
239        this->relCalendar = &relCalendar;
240        return this->checkDate();
241      }
242
243      //----------------------------------------------------------------
244
245      CDate CDate::FromString(const StdString & str, const CCalendar & calendar)
246      {
247         CDate dt(calendar);
248         StdIStringStream iss(str);
249         iss >> dt;
250         return dt;
251      }
252     
253      //----------------------------------------------------------------
254     
255      StdString CDate::getStryyyymmdd(void) const
256      { 
257         std::streamsize s ; 
258         char c ;
259
260         ostringstream oss ;
261
262         s = oss.width (4);  c = oss.fill ('0') ; oss << year ;
263         s = oss.width (2);  c = oss.fill ('0') ; oss << month;
264         s = oss.width (2);  c = oss.fill ('0') ; oss << day ;
265
266         return oss.str();
267      }
268     
269
270      string CDate::getStr(const string& str) const
271      {
272        ostringstream oss ;
273        int level;
274       
275        level=0 ;
276        for(string::const_iterator it=str.begin();it!=str.end();++it)
277        {
278          if (level==0)
279          {
280            if (*it=='%') level++ ;
281            else oss<<*it ;
282          }
283          else if (level==1)
284          {
285            switch (*it)
286            {
287              case 'y' :
288                oss.width (4);  oss.fill ('0') ; oss << year ;
289                level=0 ;
290                break ;
291              case 'm' : // month or minute
292                level++ ;
293                break ;
294              case 'd' :
295                oss.width (2);  oss.fill ('0') ; oss << day ;
296                level=0;
297                break ;
298              case 'h' :
299                oss.width (2);  oss.fill ('0') ; oss << hour ;
300                level=0;
301                break ;
302              case 's' :
303                oss.width (2);  oss.fill ('0') ; oss << second ;
304                level=0 ;
305                break;
306              default :
307                oss<<'%'<<*it ;
308                level=0 ;
309            }
310          }
311          else if (level==2)
312          {
313            switch (*it)
314            {
315              case 'o' : // month
316                oss.width (2);  oss.fill ('0') ; oss << month ;
317                level=0 ;
318                break ;
319              case 'i' : //minute
320                oss.width (2);  oss.fill ('0') ; oss << minute ;
321                level=0 ;
322                break ;
323              default :
324                oss<<"%m"<<*it ;
325                level=0 ;
326            }
327          }
328        }
329        return oss.str();
330      }
331     
332      StdString CDate::toString(void) const
333      { 
334         StdOStringStream oss;
335         oss << (*this);
336         return (oss.str()); 
337      }
338
339      ///---------------------------------------------------------------
340
341} // namespace xios
Note: See TracBrowser for help on using the repository browser.