1 /*
2  * Copyright (C) 2016 Open Source Robotics Foundation
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *
16 */
17 #ifndef IGNITION_COMMON_TIME_HH_
18 #define IGNITION_COMMON_TIME_HH_
19 
20 #include <string>
21 #include <iostream>
22 
23 #include <ignition/common/Export.hh>
24 #include <ignition/common/Util.hh>
25 
26 namespace ignition
27 {
28   namespace common
29   {
30     /// \class Time Time.hh common/common.hh
31     /// \brief A Time class, can be used to hold wall- or sim-time.
32     ///        stored as sec and nano-sec.
33     class IGNITION_COMMON_VISIBLE Time
34     {
35       /// \brief A static zero time variable set to common::Time(0, 0).
36       public: static const Time Zero;
37 
38       /// \enum Format options
39       /// \brief Options for formatting time as a string.
40       public: enum class FormatOption
41       {
42         /// \brief Days
43         DAYS = 0,
44         /// \brief Hours
45         HOURS = 1,
46         /// \brief Minutes
47         MINUTES = 2,
48         /// \brief Seconds
49         SECONDS = 3,
50         /// \brief Milliseconds
51         MILLISECONDS = 4
52       };
53 
54       /// \brief Constructors
55       public: Time();
56 
57       /// \brief Copy constructor
58       /// \param[in] time Time to copy
59       public: Time(const Time &_time);
60 
61       /// \brief Constructor
62       /// \param[in] _tv Time to initialize to
63       public: explicit Time(const struct timespec &_tv);
64 
65       /// \brief Constructor
66       /// \param[in] _sec Seconds
67       /// \param[in] _nsec Nanoseconds
68       public: Time(int32_t _sec, int32_t _nsec);
69 
70       /// \brief Constuctor
71       /// \param[in] _time Time in double format sec.nsec
72       public: explicit Time(double _time);
73 
74       /// \brief Destructor
75       public: virtual ~Time();
76 
77       /// \brief Get the wall time
78       /// \return the current time
79       public: static const Time &SystemTime();
80 
81       /// \brief Set to sec and nsec
82       /// \param[in] _sec Seconds
83       /// \param[in] _nsec Nanoseconds
84       public: void Set(int32_t _sec, int32_t _nsec);
85 
86       /// \brief Set to seconds
87       /// \param[in] _seconds Number of seconds
88       public: void Set(double _seconds);
89 
90       /// \brief Get the time as a double
91       /// \return Time as a double in seconds
92       public: double Double() const;
93 
94       /// \brief Get the time as a float
95       /// \return Time as a float in seconds
96       public: float Float() const;
97 
98       /// \brief Sleep for the specified time
99       /// \param[in] _time Sleep time
100       /// \return Time actually slept
101       public: static Time Sleep(const common::Time &_time);
102 
103       /// \brief Get the time as a string formatted as "DD hh:mm:ss.mmm", with
104       /// the option to choose the start/end.
105       /// \param[in] _start Start point.
106       /// \param[in] _end End point.
107       /// \return String representing time.
108       public: std::string FormattedString(
109           FormatOption _start = FormatOption::DAYS,
110           FormatOption _end = FormatOption::MILLISECONDS) const;
111 
112       /// \brief Assignment operator
113       /// \param[in] _time the new time
114       /// \return a reference to this instance
115       public: Time &operator=(const Time &_time);
116 
117       /// \brief Addition operators
118       /// \param[in] _time The time to add
119       /// \return a Time instance
120       public: Time operator+(const Time &_time) const;
121 
122       /// \brief Addition assignemtn operator
123       /// \param[in] _time The time to add
124       /// \return a Time instance
125       public: const Time &operator +=(const Time &_time);
126 
127       /// \brief Subtraction operator
128       /// \param[in] _tv The time to subtract
129       /// \return a Time instance
130       public: Time operator -(const struct timespec &_tv) const;
131 
132       /// \brief Subtraction assignment operator
133       /// \param[in] _tv The time to subtract
134       /// \return a Time instance
135       public: const Time &operator -=(const struct timespec &_tv);
136 
137       /// \brief Subtraction operator
138       /// \param[in] _time The time to subtract
139       /// \return a Time instance
140       public: Time operator -(const Time &_time) const;
141 
142       /// \brief Subtraction assignment operator
143       /// \param[in] _time The time to subtract
144       /// \return a reference to this instance
145       public: const Time &operator -=(const Time &_time);
146 
147       /// \brief Multiplication operator
148       /// \param[in] _tv the scaling duration
149       /// \return Time instance
150       public: Time operator *(const struct timespec &_tv) const;
151 
152       /// \brief Multiplication assignment operator
153       /// \param[in] _tv the scaling duration
154       /// \return a reference to this instance
155       public: const Time &operator *=(const struct timespec &_tv);
156 
157       /// \brief Multiplication operators
158       /// \param[in] _time the scaling factor
159       /// \return a scaled Time instance
160       public: Time operator *(const Time &_time) const;
161 
162       /// \brief Multiplication operators
163       /// \param[in] _time scale factor
164       /// \return a scaled Time instance
165       public: const Time &operator *=(const Time &_time);
166 
167       /// \brief Division assignment operator
168       /// \param[in] _tv a divisor
169       /// \return a Time instance
170       public: const Time &operator /=(const struct timespec &_tv);
171 
172       /// \brief Division operator
173       /// \param[in] _time the divisor
174       /// \return a Time instance
175       public: Time operator /(const Time &_time) const;
176 
177       /// \brief Division assignment operator
178       /// \param[in] time the divisor
179       /// \return a Time instance
180       public: const Time &operator /=(const Time &time);
181 
182       /// \brief Equal to operator
183       /// \param[in] _time the time to compare to
184       /// \return true if values are the same, false otherwise
185       public: bool operator==(const Time &_time) const;
186 
187       /// \brief Equal to operator
188       /// \param[in] _time the time to compare to
189       /// \return true if values are the same, false otherwise
190       public: bool operator==(double _time) const;
191 
192       /// \brief Equal to operator
193       /// \param[in] _time the time to compare to
194       /// \return true if values are the same, false otherwise
195       public: bool operator!=(const Time &_time) const;
196 
197       /// \brief Equal to operator
198       /// \param[in] _time the time to compare to
199       /// \return true if values are the same, false otherwise
200       public: bool operator!=(double _time) const;
201 
202       /// \brief Less than operator
203       /// \param[in] _time the time to compare with
204       /// \return true if time is shorter than this, false otherwise
205       public: bool operator<(const Time &_time) const;
206 
207       /// \brief Less than operator
208       /// \param[in] _time the time to compare with
209       /// \return true if time is shorter than this, false otherwise
210       public: bool operator<(double _time) const;
211 
212       /// \brief Less than or equal to operator
213       /// \param[in] _time the time to compare with
214       /// \return true if time is shorter than or equal to this, false otherwise
215       public: bool operator<=(const Time &_time) const;
216 
217       /// \brief Less than or equal to operator
218       /// \param[in] _time the time to compare with
219       /// \return true if time is shorter than or equal to this, false otherwise
220       public: bool operator<=(double _time) const;
221 
222       /// \brief Greater than operator
223       /// \param[in] _tv the time to compare with
224       /// \return true if time is greater than this, false otherwise
225       public: bool operator>(const struct timespec &_tv) const;
226 
227       /// \brief Greater than operator
228       /// \param[in] _time the time to compare with
229       /// \return true if time is greater than this, false otherwise
230       public: bool operator>(const Time &_time) const;
231 
232       /// \brief Greater than operator
233       /// \param[in] _time the time to compare with
234       /// \return true if time is greater than this, false otherwise
235       public: bool operator>(double _time) const;
236 
237       /// \brief Greater than or equal operator
238       /// \param[in] _time the time to compare with
239       /// \return true if time is greater than or equal to this, false otherwise
240       public: bool operator>=(const Time &_time) const;
241 
242       /// \brief Greater than or equal operator
243       /// \param[in] _tv the time to compare with
244       /// \return true if tv is greater than or equal to this, false otherwise
245       public: bool operator>=(const struct timespec &_tv) const;
246 
247       /// \brief Greater than or equal operator
248       /// \param[in] _time the time to compare with
249       /// \return true if time is greater than or equal to this, false otherwise
250       public: bool operator>=(double _time) const;
251 
252       /// \brief Stream insertion operator
253       /// \param[in] _out the output stream
254       /// \param[in] _time time to write to the stream
255       /// \return the output stream
operator <<(std::ostream & _out,const ignition::common::Time & _time)256       public: friend std::ostream &operator<<(std::ostream &_out,
257                   const ignition::common::Time &_time)
258               {
259                 _out << _time.sec << " " << _time.nsec;
260                 return _out;
261               }
262 
263       /// \brief Stream extraction operator
264       /// \param[in] _in the input stream
265       /// \param[in] _time time to read from to the stream
266       /// \return the input stream
operator >>(std::istream & _in,ignition::common::Time & _time)267       public: friend std::istream &operator>>(std::istream &_in,
268                                               ignition::common::Time &_time)
269               {
270                 // Skip white spaces
271                 _in.setf(std::ios_base::skipws);
272                 _in >> _time.sec >> _time.nsec;
273                 return _in;
274               }
275 
276       /// \brief Seconds
277       public: int32_t sec;
278 
279       /// \brief Nanoseconds
280       public: int32_t nsec;
281 
282       /// \brief a singleton value of the last GetWallTime() value
283       private: static Time wallTime;
284 
285       /// \brief Correct the time so that small additions/substractions
286       /// preserve the internal seconds and nanoseconds separation
Correct()287       private: inline void Correct()
288                {
289                  // In the case sec and nsec have different signs, normalize
290                  if (this->sec > 0 && this->nsec < 0)
291                  {
292                    int32_t n = abs(this->nsec / this->nsInSec) + 1;
293                    this->sec -= n;
294                    this->nsec += n * this->nsInSec;
295                  }
296                  if (this->sec < 0 && this->nsec > 0)
297                  {
298                    int32_t n = abs(this->nsec / this->nsInSec) + 1;
299                    this->sec += n;
300                    this->nsec -= n * this->nsInSec;
301                  }
302 
303                  // Make any corrections
304                  this->sec += this->nsec / this->nsInSec;
305                  this->nsec = this->nsec % this->nsInSec;
306                }
307 
308       /// \brief Constant multiplier to convert from nanoseconds to seconds.
309       private: static const int32_t nsInSec;
310 
311       /// \brief Constant multiplier to convert from nanoseconds to
312       /// milliseconds.
313       private: static const int32_t nsInMs;
314 
315       private: static struct timespec clockResolution;
316     };
317   }
318 }
319 #endif
320