source: XIOS/trunk/src/duration.cpp @ 1059

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

Fix: Do not allow redefining the same duration unit.

For example "4d 7d" used to be parsed as "7d", now an error will be thrown.

Fixes ticket #115.

  • 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: 6.3 KB
RevLine 
[219]1#include "duration.hpp"
2#include "date.hpp"
3#include "calendar.hpp"
[550]4#include "calendar_util.hpp"
[219]5
[335]6namespace xios
[219]7{
8      /// ////////////////////// Définitions ////////////////////// ///
[550]9      const CDuration Year     = { 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 },
10                      Month    = { 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0 },
11                      Week     = { 0.0, 0.0, 7.0, 0.0, 0.0, 0.0, 0.0 },
12                      Day      = { 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0 },
13                      Hour     = { 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0 },
14                      Minute   = { 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0 },
15                      Second   = { 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0 },
16                      TimeStep = { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0 },
17                      NoneDu   = { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 };
[219]18
19      ///---------------------------------------------------------------
20
[550]21      CDuration& CDuration::operator=(const CDuration& duration)
[219]22      {
[550]23        year = duration.year; month  = duration.month;  day    = duration.day;
24        hour = duration.hour; minute = duration.minute; second = duration.second; timestep = duration.timestep;
25        return *this;
[219]26      }
27
[550]28      StdOStream& operator<<(StdOStream& out, const CDuration& duration)
[219]29      {
[612]30         out << duration.toString();
31         return out;
[219]32      }
33
[539]34      StdIStream& operator>>(StdIStream& in , CDuration& duration)
[219]35      {
[539]36        duration = NoneDu;
37        double v = 1.0;
38        char   c = '/';
39        bool   invalidUnit = false;
[1049]40        CDuration sentinel = NoneDu;
[539]41
[1049]42#define setDuration(unit, value)                                                  \
43        {                                                                         \
44          if (sentinel.unit)                                                      \
45            ERROR("StdIStream& operator>>(StdIStream& in , CDuration& duration)", \
46                  << "Bad duration format: " #unit " has already been set.");      \
47                                                                                  \
48          duration.unit = value;                                                  \
49          sentinel.unit = 1.0;                                                    \
50        }
51
[539]52        do
53        {
54          in >> v >> c;
55          if (in.fail())
56            ERROR("StdIStream& operator>>(StdIStream& in , CDuration& duration)",
57                  << "Bad duration format: impossible to read a pair (value, unit).");
58
59          switch (c)
60          {
[1049]61            case 'y': setDuration(year, v) break;
62            case 'd': setDuration(day, v) break;
63            case 'h': setDuration(hour, v) break;
64            case 's': setDuration(second, v) break;
[539]65            case 'm':
66            {
67              in >> c;
[1049]68              if      (c == 'i') setDuration(minute, v)
69              else if (c == 'o') setDuration(month, v)
[539]70              else invalidUnit = true;
71              break;
[219]72            }
[539]73            case 't':
74            {
75              in >> c;
[1049]76              if (c == 's') setDuration(timestep, v)
[539]77              else invalidUnit = true;
78              break;
79            }
80            default:
[550]81              invalidUnit = true;
[539]82              break;
83          }
84
85          if (invalidUnit)
86            ERROR("StdIStream& operator>>(StdIStream& in , CDuration& duration)",
87                  << "Bad duration format: invalid unit, unexpected '" << c << "' character.");
[550]88        } while (in.peek() != EOF); // check whether there is a next character to read
[539]89
[1049]90#undef setDuration
91
[539]92        return in;
[219]93      }
94
95      //-----------------------------------------------------------------
96
97      bool CDuration::isNone(void) const
98      {
[550]99        return (*this == NoneDu);
[219]100      }
101
102      //-----------------------------------------------------------------
[550]103
104      CDuration& CDuration::solveTimeStep(const CCalendar& c)
[436]105      {
[550]106        CDuration timeStep = c.getTimeStep();
107        second += timestep * timeStep.second;
108        minute += timestep * timeStep.minute;
109        hour   += timestep * timeStep.hour;
110        day    += timestep * timeStep.day;
111        month  += timestep * timeStep.month;
112        year   += timestep * timeStep.year;
113        timestep = 0.0;
[579]114        return *this;
[550]115      }
[448]116
[550]117      CDuration& CDuration::resolve(const CCalendar& c, bool noNegativeTime /*= false*/)
[219]118      {
[550]119        return c.resolve(*this, noNegativeTime);
[219]120      }
121
122      //-----------------------------------------------------------------
123
124      StdString CDuration::toString(void) const
125      {
[612]126        StdOStringStream sout;
127        bool forceOutput = true;
128
129        if (year   != 0.0) { forceOutput = false; sout << year   << "y "; }
130        if (month  != 0.0) { forceOutput = false; sout << month  << "mo "; }
131        if (day    != 0.0) { forceOutput = false; sout << day    << "d "; }
132        if (hour   != 0.0) { forceOutput = false; sout << hour   << "h "; }
133        if (minute != 0.0) { forceOutput = false; sout << minute << "mi "; }
134        if (second != 0.0) { forceOutput = false; sout << second << "s "; }
135        if (timestep != 0.0 || forceOutput)     { sout << timestep << "ts "; }
136
137         // Remove the trailing space
138        StdString strOut = sout.str();
139        return strOut.erase(strOut.size() - 1);
[219]140      }
141
[612]142      StdString CDuration::toStringUDUnits(void) const
143      {
144         if (timestep != 0.0)
145           ERROR("StdString CDuration::toStringUDUnits(void) const",
146                 "Impossible to convert a duration to string using UDUnits when a timestep is set.");
147
148         StdOStringStream sout;
149         bool forceOutput = true;
150
151         if (year   != 0.0) { forceOutput = false; sout << year   << " yr "; }
152         if (month  != 0.0) { forceOutput = false; sout << month  << " month "; }
153         if (day    != 0.0) { forceOutput = false; sout << day    << " d "; }
154         if (hour   != 0.0) { forceOutput = false; sout << hour   << " h "; }
155         if (minute != 0.0) { forceOutput = false; sout << minute << " min "; }
156         if (second != 0.0 || forceOutput)       { sout << second << " s "; }
157
158         // Remove the trailing space
159         StdString strOut = sout.str();
160         return strOut.erase(strOut.size() - 1);
161      }
162
[550]163      CDuration CDuration::FromString(const StdString& str)
[219]164      {
[550]165        CDuration dr = NoneDu;
166        StdIStringStream iss(str); iss >> dr;
167        return dr;
[219]168      }
[335]169} // namespace xios
[219]170
Note: See TracBrowser for help on using the repository browser.