source: XIOS/branchs/xios-1.0/src/duration.cpp @ 648

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

Fix possible overflows when simplifying a duration.

Affected XIOS 1.0 only.

  • 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: 7.1 KB
Line 
1#include "duration.hpp"
2#include "date.hpp"
3#include "calendar.hpp"
4
5namespace xios
6{
7      /// ////////////////////// Définitions ////////////////////// ///
8      const CDuration Year   = {1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
9                      Month  = {0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0},
10                      Week   = {0.0, 0.0, 7.0, 0.0, 0.0, 0.0, 0.0},
11                      Day    = {0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0},
12                      Hour   = {0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0},
13                      Minute = {0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0},
14                      Second = {0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0},
15                      NoneDu = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
16                      TimeStep = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0};
17
18      ///---------------------------------------------------------------
19
20      CDuration & CDuration::operator=(const CDuration & duration)
21      {
22         year = duration.year;  month  = duration.month;  day    = duration.day;
23         hour = duration.hour;  minute = duration.minute; second = duration.second; timestep=duration.timestep;
24         return *this;
25      }
26
27      StdOStream & operator<<(StdOStream & out, const CDuration & duration)
28      {
29         out << duration.toString();
30         return out;
31      }
32
33      StdIStream & operator>>(StdIStream & in , CDuration & duration)
34      {
35         duration.year = duration.month  = duration.day    =
36         duration.hour = duration.minute = duration.second = duration.timestep=0.0;
37         double v = 1.0;
38         char   c = '/';
39         while (!in.eof())
40         {
41               if (!(in >> v >> c))
42               {
43                 //DEBUG("----> Pb StdIStream & operator>>(StdIStream & in , CDuration & duration)");
44                 //if (in.eof())  DEBUG("----> Fin de fichier StdIStream & operator>>(StdIStream & in , CDuration & duration)");
45               }
46               if (in.eof())
47               {
48                 //DEBUG("----> Fin de fichier StdIStream & operator>>(StdIStream & in , CDuration & duration)");
49                 break;
50               }
51               switch (c)
52               {
53                  case 'y': duration.year   = v; break;
54                  case 'd': duration.day    = v; break;
55                  case 'h': duration.hour   = v; break;
56                  case 's': duration.second = v; break;
57                  case 'm':
58                  {
59                     in >> c;
60                     if     (c == 'i') duration.minute = v;
61                     else if(c == 'o') duration.month  = v;
62                     else
63                     {
64                        StdString valc("m"); valc.append(1, c);
65                        //DEBUG("La chaine \"" << valc << "\" ne permet pas de définir une unité de durée.");
66                        break;
67                     }
68                     break;
69                  }
70                  case 't' :
71                  {
72                    in >> c;
73                    if (c=='s') duration.timestep = v;
74                    break;
75                  }
76
77                  default:
78                     StdString valc; valc.append(1, c);
79                     //DEBUG("La chaine \"" << valc << "\" ne permet pas de définir une unité de durée.");
80                     break;
81               }
82            }
83            return in;
84      }
85
86      //-----------------------------------------------------------------
87
88      bool CDuration::isNone(void) const
89      {
90         if ((year == 0) && (month  == 0) && (day    == 0) &&
91             (hour == 0) && (minute == 0) && (second == 0) && (timestep == 0))
92            return true;
93         return false;
94      }
95
96      //-----------------------------------------------------------------
97      CDuration & CDuration::solveTimeStep(const CCalendar & c)
98      {
99        CDuration timeStep=c.getTimeStep();
100        second +=timestep*timeStep.second;
101        minute +=timestep*timeStep.minute;
102        hour +=timestep*timeStep.hour;
103        day +=timestep*timeStep.day;
104        month +=timestep*timeStep.month;
105        year +=timestep*timeStep.year;
106        timestep = 0;
107        return *this;
108      }
109
110      CDuration & CDuration::resolve(const CCalendar & c)
111      {
112        // Convert year, day, hour and minute to integer
113        month  += modf(year, &year) * c.getYearLength();
114        hour   += modf(day, &day) * c.getDayLength();
115        minute += modf(hour , &hour) * c.getHourLength();
116        second += modf(minute, &minute) * c.getMinuteLength();
117
118        // Simplify second, minute, day and year
119        double remain;
120        remain = fmod(second, c.getMinuteLength());
121        minute += (second - remain) / c.getMinuteLength();
122        second = remain;
123
124        remain = fmod(minute, c.getHourLength());
125        hour   += (minute - remain) / c.getHourLength();
126        minute = remain;
127
128        remain = fmod(hour, c.getDayLength());
129        day    += (hour - remain) / c.getDayLength();
130        hour   = remain;
131
132        remain = fmod(month, c.getYearLength());
133        year   += (month - remain) / c.getYearLength();
134        month  = remain;
135
136        return *this;
137      }
138
139      //-----------------------------------------------------------------
140
141      StdString CDuration::toString(void) const
142      {
143         StdOStringStream sout;
144         bool forceOutput = true;
145
146         if (year   != 0.0) { forceOutput = false; sout << year   << "y "; }
147         if (month  != 0.0) { forceOutput = false; sout << month  << "mo "; }
148         if (day    != 0.0) { forceOutput = false; sout << day    << "d "; }
149         if (hour   != 0.0) { forceOutput = false; sout << hour   << "h "; }
150         if (minute != 0.0) { forceOutput = false; sout << minute << "mi "; }
151         if (second != 0.0) { forceOutput = false; sout << second << "s "; }
152         if (timestep != 0.0 || forceOutput)     { sout << timestep << "ts "; }
153
154         // Remove the trailing space
155         StdString strOut = sout.str();
156         return strOut.erase(strOut.size() - 1);
157      }
158
159      StdString CDuration::toStringUDUnits(void) const
160      {
161         if (timestep != 0.0)
162           ERROR("StdString CDuration::toStringUDUnits(void) const",
163                 "Impossible to convert a duration to string using UDUnits when a timestep is set.");
164
165         StdOStringStream sout;
166         bool forceOutput = true;
167
168         if (year   != 0.0) { forceOutput = false; sout << year   << " yr "; }
169         if (month  != 0.0) { forceOutput = false; sout << month  << " month "; }
170         if (day    != 0.0) { forceOutput = false; sout << day    << " d "; }
171         if (hour   != 0.0) { forceOutput = false; sout << hour   << " h "; }
172         if (minute != 0.0) { forceOutput = false; sout << minute << " min "; }
173         if (second != 0.0 || forceOutput)       { sout << second << " s "; }
174
175         // Remove the trailing space
176         StdString strOut = sout.str();
177         return strOut.erase(strOut.size() - 1);
178      }
179
180      CDuration CDuration::FromString(const StdString & str)
181      {
182         CDuration dr = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0};
183         StdIStringStream iss(str); iss >> dr;
184         return dr;
185      }
186
187      ///---------------------------------------------------------------
188} // namespace xios
189
Note: See TracBrowser for help on using the repository browser.