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

Last change on this file since 544 was 544, checked in by rlacroix, 9 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
RevLine 
[219]1#include "date.hpp"
2#include "calendar.hpp"
[334]3#include "calendar_type.hpp"
[316]4#include <boost/date_time/gregorian/gregorian.hpp>
5#include <boost/date_time/posix_time/posix_time.hpp>
[219]6
[316]7using namespace boost::posix_time ;
8using namespace boost::gregorian ;
9
[335]10namespace xios
[219]11{
12      /// ////////////////////// Définitions ////////////////////// ///
[532]13      CDate::CDate(void)
14         : relCalendar(NULL)
15         , year(0), month(1) , day(1)
16         , hour(0), minute(0), second(0)
17      {}
18
[334]19      CDate::CDate(const CCalendar& calendar)
[532]20         : relCalendar(&calendar)
[334]21         , year(0), month(1) , day(1)
22         , hour(0), minute(0), second(0)
[532]23      {}
[334]24     
[219]25      CDate::CDate(const CCalendar& calendar,
26                   int yr, int mth, int d,
27                   int hr, int min, int sec)
[532]28         : relCalendar(&calendar)
[219]29         , year(yr), month(mth) , day(d)
30         , hour(hr), minute(min), second(sec)
31      {
32         if(!this->checkDate())
[231]33         {
[219]34            DEBUG(<< "La date initialisée a été modifiée "
35                  << "car elle était incorrecte par rapport au calendrier souhaité.");
[231]36         }
[219]37      }
38
[532]39      CDate::CDate(const CDate& date)
40            : relCalendar(date.relCalendar),
[219]41              year(date.year), month(date.month)  , day(date.day),
42              hour(date.hour), minute(date.minute), second(date.second)
43      {
[532]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        }
[219]50      }
51
52      CDate::~CDate(void)
53      { /* Ne rien faire de plus */ }
54
55      ///---------------------------------------------------------------
56
57      CDate & CDate::operator=(const CDate & date)
58      {
[532]59         relCalendar = date.relCalendar;
[219]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      {
[316]67         std::streamsize s ; 
68         char c ;
[494]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
[316]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
[219]86         return (out);
87      }
88
89      StdIStream & operator>>(StdIStream & in, CDate & date) // Non testée.
90      {
[316]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                {
[532]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);
[316]118                }
119              }
120            }
121          }
122        }
123        ERROR("StdIStream & operator >> (StdIStream & in, CDate & date)",<<"Bad date format or not conform to calendar" );
124        return (in);
[219]125      }
126
[334]127      CDate::operator Time(void) const // Non vérifiée, pas optimisée ...
[219]128      {
[532]129         // This will check that a calendar was correctly associated to the date
130         const CCalendar& c = getRelCalendar();
131
[219]132         // Todo : Tester si la date courante est supérieure à la date initiale.
[544]133         Time retvalue = - c.getNbSecond(c.getTimeOrigin())
[532]134                         + c.getNbSecond(*this);
[219]135
[532]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));
[219]141
[532]142         for(CDate _d(c.getTimeOrigin());
[219]143            _d.getYear() < getYear(); _d.setYear(_d.getYear()+1))
[532]144            retvalue += c.getYearTotalLength(_d);
[219]145         return (retvalue);
146      }
147
148      //----------------------------------------------------------------
149
150      bool CDate::checkDate(void)
151      {
152         bool retValue = true;
153
[532]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.
[219]158         if (month  < 1) { retValue = false; month  = 1; }
[532]159         if (month  > c.getYearLength())
160         { retValue = false; month = c.getYearLength(); }
[219]161
162         // Vérification de la valeur du jour.
[532]163         if (day    < 1) { retValue = false; day  = 1; }
164         if (day    > c.getMonthLength(*this))
165         { retValue = false; day = c.getMonthLength(*this); }
[219]166
167         // Vérification de la valeur de l'heure.
168         if (hour   < 0) { retValue = false; hour  = 0; }
[532]169         if (hour   >= c.getDayLength())
170         { retValue = false; hour = c.getDayLength() - 1; }
[219]171
172         // Vérification de la valeur des minutes.
173         if (minute < 0) { retValue = false; minute = 0; }
[532]174         if (minute >= c.getHourLength())
175         { retValue = false; minute = c.getHourLength() - 1; }
[219]176
177         // Vérification de la valeur des secondes.
[532]178         if (second < 0) { retValue = false; second = 0; }
179         if (second >= c.getMinuteLength())
180         { retValue = false; second = c.getMinuteLength() - 1; }
[219]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
[532]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      }
[219]203
[532]204      bool CDate::hasRelCalendar(void) const
205      { return (this->relCalendar != NULL); }
206
[219]207      //----------------------------------------------------------------
208
[532]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; }
[219]215
[532]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
[219]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
[532]237      bool CDate::setRelCalendar(const CCalendar& relCalendar)
238      {
239        this->relCalendar = &relCalendar;
240        return this->checkDate();
241      }
242
243      //----------------------------------------------------------------
244
[219]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     
[321]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     
[431]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
[219]333      { 
334         StdOStringStream oss;
335         oss << (*this);
336         return (oss.str()); 
337      }
338
339      ///---------------------------------------------------------------
340
[335]341} // namespace xios
Note: See TracBrowser for help on using the repository browser.