source: XIOS/branchs/xios-1.0/src/date.cpp @ 647

Last change on this file since 647 was 647, checked in by rlacroix, 7 years ago

Fix a possible overflow when converting a date in seconds since the time origin.

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