Streaming C++ API
Timestamp.hpp
1//
2// Copyright (c) 2004-2023 TIBCO Software Inc. All rights reserved.
3//
4
5#ifndef STREAMBASE_TIMESTAMP_H
6#define STREAMBASE_TIMESTAMP_H
7
8#include "StreamBase.hpp"
9
10#include <time.h>
11#include "Exceptions.hpp"
12#include <NMSTL/ntime.hpp>
13#include <NMSTL/platform.hpp>
14
15SB_NAMESPACE_BEGIN;
16class Timestamp;
17SB_NAMESPACE_END;
18
19SB_INTERNAL_FWD(TimestampTest);
20SB_INTERNAL_FWD(TimestampUtil);
21SB_INTERNAL_FWD(Errors);
22
23
24#ifndef DOXYGEN_SKIP
25NMSTL_NAMESPACE_BEGIN;
26inline sb::Timestamp getUnaligned(const sb::Timestamp *p);
27inline void setUnaligned(sb::Timestamp *p, sb::Timestamp value);
28NMSTL_NAMESPACE_END;
29#endif //DOXYGEN_SKIP
30
31
32SB_NAMESPACE_BEGIN;
33
34/// Attempted to parse an invalid Timestamp string.
35STREAMBASE_EXCEPTION_TYPE(TimestampException, sb_internal::Errors::NON_FATAL_ERROR);
36/// Class for representing moments in time and intervals at
37/// millisecond granularity.
39{
40 private:
41 enum TIMESTAMPTYPE { TIMESTAMP = 0, INTERVAL = 1 };
42 enum TIMESTAMP_FIELD {YEAR, MONTH, DAY, HOUR, MINUTE, SECOND};
43 // Field. Measures milliseconds since the start of the Unix epoch.
44 struct MS {
45#ifdef sparc
46 // swap order for sparc
47 long long int value : 63;
48 long long int type : 1;
49#else
50 long long int type : 1;
51 long long int value : 63;
52#endif
53 };
54
55 public:
56 static const int MIN_YEAR = 1400;
57 static const int MAX_YEAR = 9999;
58 static const int MIN_MONTH = 1;
59 static const int MAX_MONTH = 12;
60 static const int MIN_DAY = 1;
61 static const int MAX_DAY = 31;
62 static const int MIN_HOUR = 0;
63 static const int MAX_HOUR = 23;
64 static const int MIN_MINUTE = 0;
65 static const int MAX_MINUTE = 59;
66 static const int MIN_SECOND = 0;
67 static const int MAX_SECOND = 59;
68
69 /// Create a default Timestamp.
70 /// Will initialized to 00:00:00 1 Jan 1970.
72 {
73 _ms.type = TIMESTAMP;
74 _ms.value = 0;
75 }
76
77 /// Return a Timestamp representing the current moment in time.
78 static Timestamp now();
79
80 /// Negate an interval to return an interval. Negate a timestamp
81 /// to return a timestamp, even though that doesn't make much sense.
83
84 /// Subtract two Timestamps to return an interval. Subtract two
85 /// intervals to return an interval. Subtract an interval from a
86 /// Timestamp to return a Timestamp.
87 Timestamp operator-(const Timestamp &rhs) const;
88
89 /// Add a Timestamp and an interval to get a Timestamp. Add two
90 /// intervals to return an interval.
91 Timestamp operator+(const Timestamp &rhs) const;
92
93 /// Increment the Timestamp by the interval.
95
96 /// Decrement the Timestamp by the interval.
98
99 /// Multiply a Timestamp representing an interval by a constant.
100 template<typename T>
101 Timestamp operator*(T rhs) const {
102 MS t = makeMS((TIMESTAMPTYPE)_ms.type, (long long int)(_ms.value * rhs));
103 return Timestamp(t);
104 }
105 /// Multiply a Timestamp representing an interval by a constant.
106 template<typename T>
108 *this = *this * rhs;
109 return *this;
110 }
111 /// Divide a Timestamp representing an interval by a constant.
112 template<typename T>
113 Timestamp operator/(T rhs) const {
114 MS t = makeMS((TIMESTAMPTYPE)_ms.type, (long long int)(_ms.value / rhs));
115 return Timestamp(t);
116 }
117 /// Divide a Timestamp representing an interval by a constant.
118 template<typename T>
120 *this = *this / rhs;
121 return *this;
122 }
123
124 /// Divide two Timestamps representing an interval to find their
125 /// quotient.
126 double operator/(Timestamp rhs) const {
127 return (double)_ms.value / (double)rhs._ms.value;
128 }
129
130 /// Modulo a Timestamp by an interval.
131 Timestamp operator%(const Timestamp &rhs) const {
132 MS t = makeMS(INTERVAL, _ms.value % rhs._ms.value);
133 return Timestamp(t);
134 }
135
136 /// Modulo a Timestamp by an interval.
138 *this = *this % rhs;
139 return *this;
140 }
141
142 /// Return true if this Timestamp is before rhs.
143 bool operator<(const Timestamp &rhs) const {
144 return (_ms.value < rhs._ms.value);
145 }
146 /// Return true if this Timestamp is before or at the same time as
147 /// rhs.
148 bool operator<=(const Timestamp &rhs) const {
149 return (_ms.value <= rhs._ms.value);
150 }
151 /// Return true if this Timestamp is at the same time as rhs.
152 bool operator==(const Timestamp &rhs) const {
153 return (_ms.value == rhs._ms.value);
154 }
155 /// Return true if this Timestamp is not at the same time as rhs.
156 bool operator!=(const Timestamp &rhs) const {
157 return (_ms.value != rhs._ms.value);
158 }
159 /// Return true if this Timestamp is after or at the same time as
160 /// rhs.
161 bool operator>=(const Timestamp &rhs) const {
162 return (_ms.value >= rhs._ms.value);
163 }
164 /// Return true if this Timestamp is after rhs.
165 bool operator>(const Timestamp &rhs) const {
166 return (_ms.value > rhs._ms.value);
167 }
168
169 /// Return true if this Timestamp is an interval.
170 bool isInterval() const {
171 return (_ms.type != TIMESTAMP);
172 }
173
174 /// Create a time from a count of milliseconds.
175 static Timestamp milliseconds(long long milliseconds) {
176 MS t = makeMS(INTERVAL, milliseconds);
177 return Timestamp(t);
178 }
179
180 /// Create a time from a count of seconds.
181 template<typename T>
182 static Timestamp seconds(T seconds) {
183 MS t = makeMS(INTERVAL, ((long long)(seconds * THOUSAND)));
184 return Timestamp(t);
185 }
186 /// Create a time from a count of seconds.
187 static Timestamp seconds(double seconds) {
188 double roundingValue = seconds > 0 ? 0.5 : -0.5;
189 MS t = makeMS(INTERVAL, ((long long)(seconds * THOUSAND + roundingValue)));
190 return Timestamp(t);
191 }
192
193 /// Construct an interval from minutes
194 template<typename T>
195 static Timestamp minutes(T minutes) {
196 MS t = makeMS(INTERVAL, ((long long)minutes) * MILLISECONDS_PER_MINUTE);
197 return Timestamp(t);
198 }
199 /// Construct an interval from minutes
200 static Timestamp minutes(double minutes) {
201 double roundingValue = minutes > 0 ? 0.5 : -0.5;
202 MS t = makeMS(INTERVAL, (long long int)(minutes * MILLISECONDS_PER_MINUTE + roundingValue));
203 return Timestamp(t);
204 }
205
206 /// Construct an interval from hours
207 template<typename T>
208 static Timestamp hours(T hours) {
209 MS t = makeMS(INTERVAL, ((long long)hours) * MILLISECONDS_PER_HOUR);
210 return Timestamp(t);
211 }
212 /// Construct an interval from hours
213 static Timestamp hours(double hours) {
214 double roundingValue = hours > 0 ? 0.5 : -0.5;
215 MS t = makeMS(INTERVAL, (long long int)(hours * MILLISECONDS_PER_HOUR + roundingValue));
216 return Timestamp(t);
217 }
218
219 /// Construct an interval from days
220 template<typename T>
221 static Timestamp days(T days) {
222 MS t = makeMS(INTERVAL, ((long long)days) * MILLISECONDS_PER_DAY);
223 return Timestamp(t);
224 }
225 /// Construct an interval from days
226 static Timestamp days(double days) {
227 double roundingValue = days > 0 ? 0.5 : -0.5;
228 MS t = makeMS(INTERVAL, (long long int)(days * MILLISECONDS_PER_DAY + roundingValue));
229 return Timestamp(t);
230 }
231
232 /// Construct an interval from weeks
233 template<typename T>
234 static Timestamp weeks(T weeks) {
235 MS t = makeMS(INTERVAL, ((long long)weeks) * MILLISECONDS_PER_DAY * DAYS_PER_WEEK);
236 return Timestamp(t);
237 }
238 /// Construct an interval from weeks
239 static Timestamp weeks(double weeks) {
240 double roundingValue = weeks > 0 ? 0.5 : -0.5;
241 MS t = makeMS(INTERVAL, (long long int)(weeks * MILLISECONDS_PER_DAY * DAYS_PER_WEEK + roundingValue));
242 return Timestamp(t);
243 }
244
245 /// Return the time as milliseconds.
246 long long toMsecs() const {
247 return _ms.value;
248 }
249
250 /// Return the time as seconds
251 long long toSecs() const {
252 return _ms.value / THOUSAND;
253 }
254
255 /// compare 2 timestamps
256 /// return less than zero this < other
257 /// return greater than zero this > other
258 /// return 0 if they are the same
259 int compare(const Timestamp &other) const {
260 assert(_ms.type == other._ms.type);
261 if(_ms.value < other._ms.value) { return -1; }
262 if(_ms.value > other._ms.value) { return 1; }
263 return 0;
264 }
265
266 /// Return seconds after the minute
267 double getSecond() const;
268
269 /// Return milliseconds after the second
270 double getMillisecond() const;
271
272 /// Return minutes after hour
273 int getMinute() const;
274
275 /// Return hours since midnight
276 int getHour() const;
277
278 /// Return day since Sunday
279 int getDayOfWeek() const;
280
281 /// Return day of month
282 int getDayOfMonth() const;
283
284 /// Return month since January
285 int getMonth() const;
286
287 /// Return year
288 int getYear() const;
289
290 /// Set seconds after the minute
291 void setSecond(double seconds);
292
293 /// Set minutes after the hour
294 void setMinute(int minutes);
295
296 /// Set hours since midnight
297 void setHour(int hours);
298
299 /// Set day of month
300 void setDayOfMonth(int day_of_month);
301
302 /// Set month since January
303 void setMonth(int month);
304
305 /// Set year
306 void setYear(int year);
307
308 /// Return a human readable string rep of this Timestamp
309 std::string as_string(bool displayTimezone=true) const;
310
311private:
312 friend class sb_internal::TimestampTest;
313
314 /// Set an arbitrary Timestamp field
315 void setField(TIMESTAMP_FIELD, int *value);
316
317 // Constants for use in our math when dealing with timevals.
318 static const long long MILLISECONDS_PER_MINUTE = 60000LL;
319 static const long long MILLISECONDS_PER_HOUR = 3600000LL;
320 static const long long MILLISECONDS_PER_DAY = 86400000LL;
321 static const long long DAYS_PER_WEEK = 7LL;
322 static const long long THOUSAND = 1000LL;
323 static const long long MILLION = 1000000LL;
324
325 MS _ms;
326
327 static MS makeMS(TIMESTAMPTYPE t, long long v);
328
329 // Private constructor from a long long int.
330 explicit Timestamp(MS ms)
331 { _ms = ms;}
332
333 static bool validateTimestampFields(
334 int year,
335 int month,
336 int day,
337 int hour,
338 int minute,
339 int second);
340
341 Timestamp(long long int ts, int type=TIMESTAMP)
342 {
343 _ms.type = type;
344 _ms.value = ts;
345 }
346
347 // Routines for dealing with potentially unaligned Timestamps. On
348 // SPARC, copy an int at a time; on Intel, read/write directly.
349#ifdef sparc
350 union MSAndInts {
351 Timestamp::MS ms;
352 struct { int i1; int i2; };
353 };
354
355 inline static Timestamp
356 getUnaligned(const Timestamp *p)
357 {
358 const int *dip = (const int*)p;
359 MSAndInts di;
360 di.i1 = dip[0];
361 di.i2 = dip[1];
362 return Timestamp(di.ms);
363 }
364
365 inline static void
366 setUnaligned(Timestamp *p, Timestamp value)
367 {
368 int *dip = (int*)p;
369 MSAndInts di;
370 di.ms = value._ms;
371 dip[0] = di.i1;
372 dip[1] = di.i2;
373 }
374#else
375 // Intel
376 inline static Timestamp getUnaligned(const Timestamp *p) { return *p; }
377 inline static void setUnaligned(Timestamp *p, Timestamp value) { *p = value; }
378#endif
379
380 friend class sb_internal::TimestampUtil;
381
382#ifndef DOXYGEN_SKIP
383 friend sb::Timestamp NMSTL::getUnaligned(const sb::Timestamp *p);
384 friend void NMSTL::setUnaligned(sb::Timestamp *p, sb::Timestamp value);
385#endif
386
387 // constants to be used in conjunction with the cpu counter to determine current time more efficiently
388 static const long long RESOLUTION_PER_SEC = 1000LL; // time resolution units = milliseconds
389 static const long long MIN_SYSTEM_INTERVAL = 10LL; // min system synchronization time interval = 10ms
390 static const long long MAX_SYSTEM_INTERVAL = 100LL; // max system synchronization time interval = 100ms
391 static const unsigned long long TICKS_PER_SEC; // computed from cpu frequency
392 static const unsigned long long TICKS_PER_RESOLUTION; // computed from cpu frequency
393
394 // thread local storage to be used in conjunction with the cpu counter to determine current time more efficiently
395#ifndef sun
396#ifndef SWIG
397 static SB_THREAD_LOCAL unsigned long long systemTicks;
398 static SB_THREAD_LOCAL long long systemTime;
399 static SB_THREAD_LOCAL long long systemInterval;
400 static SB_THREAD_LOCAL long long lastTimestamp;
401#endif // SWIG
402#endif // sun
403 static unsigned long long initCpuTicksPerSecond();
404};
405
406SB_NAMESPACE_END;
407
408#ifndef DOXYGEN_SKIP
409NMSTL_NAMESPACE_BEGIN;
410
411inline sb::Timestamp getUnaligned(const sb::Timestamp *p)
412{
413 return sb::Timestamp::getUnaligned(p);
414}
415
416inline void setUnaligned(sb::Timestamp *p, sb::Timestamp value)
417{
418 sb::Timestamp::setUnaligned(p, value);
419}
420
421NMSTL_NAMESPACE_END;
422#endif //DOXYGEN_SKIP
423
424#endif
425
426// LocalWords: StreamBase NMSTL ntime Timestamp timevals timeval tm TODO rhs
427// LocalWords: gettimeofday
Attempted to parse an invalid Timestamp string.
Definition: Timestamp.hpp:35
Class for representing moments in time and intervals at millisecond granularity.
Definition: Timestamp.hpp:39
long long toSecs() const
Return the time as seconds.
Definition: Timestamp.hpp:251
void setMonth(int month)
Set month since January.
Timestamp()
Create a default Timestamp.
Definition: Timestamp.hpp:71
static Timestamp seconds(T seconds)
Create a time from a count of seconds.
Definition: Timestamp.hpp:182
double getSecond() const
Return seconds after the minute.
long long toMsecs() const
Return the time as milliseconds.
Definition: Timestamp.hpp:246
double operator/(Timestamp rhs) const
Divide two Timestamps representing an interval to find their quotient.
Definition: Timestamp.hpp:126
static Timestamp now()
Return a Timestamp representing the current moment in time.
int getMonth() const
Return month since January.
int compare(const Timestamp &other) const
compare 2 timestamps return less than zero this < other return greater than zero this > other return ...
Definition: Timestamp.hpp:259
int getMinute() const
Return minutes after hour.
Timestamp & operator/=(T rhs)
Divide a Timestamp representing an interval by a constant.
Definition: Timestamp.hpp:119
bool isInterval() const
Return true if this Timestamp is an interval.
Definition: Timestamp.hpp:170
Timestamp operator/(T rhs) const
Divide a Timestamp representing an interval by a constant.
Definition: Timestamp.hpp:113
static Timestamp minutes(T minutes)
Construct an interval from minutes.
Definition: Timestamp.hpp:195
Timestamp & operator+=(const Timestamp &rhs)
Increment the Timestamp by the interval.
bool operator!=(const Timestamp &rhs) const
Return true if this Timestamp is not at the same time as rhs.
Definition: Timestamp.hpp:156
Timestamp & operator-=(const Timestamp &rhs)
Decrement the Timestamp by the interval.
static Timestamp days(T days)
Construct an interval from days.
Definition: Timestamp.hpp:221
bool operator>=(const Timestamp &rhs) const
Return true if this Timestamp is after or at the same time as rhs.
Definition: Timestamp.hpp:161
static Timestamp hours(T hours)
Construct an interval from hours.
Definition: Timestamp.hpp:208
void setDayOfMonth(int day_of_month)
Set day of month.
static Timestamp days(double days)
Construct an interval from days.
Definition: Timestamp.hpp:226
int getHour() const
Return hours since midnight.
Timestamp & operator*=(T rhs)
Multiply a Timestamp representing an interval by a constant.
Definition: Timestamp.hpp:107
void setSecond(double seconds)
Set seconds after the minute.
static Timestamp milliseconds(long long milliseconds)
Create a time from a count of milliseconds.
Definition: Timestamp.hpp:175
static Timestamp weeks(T weeks)
Construct an interval from weeks.
Definition: Timestamp.hpp:234
bool operator>(const Timestamp &rhs) const
Return true if this Timestamp is after rhs.
Definition: Timestamp.hpp:165
void setHour(int hours)
Set hours since midnight.
Timestamp operator+(const Timestamp &rhs) const
Add a Timestamp and an interval to get a Timestamp.
Timestamp operator%(const Timestamp &rhs) const
Modulo a Timestamp by an interval.
Definition: Timestamp.hpp:131
static Timestamp hours(double hours)
Construct an interval from hours.
Definition: Timestamp.hpp:213
Timestamp operator-(const Timestamp &rhs) const
Subtract two Timestamps to return an interval.
Timestamp operator*(T rhs) const
Multiply a Timestamp representing an interval by a constant.
Definition: Timestamp.hpp:101
Timestamp operator-() const
Negate an interval to return an interval.
double getMillisecond() const
Return milliseconds after the second.
Timestamp operator%=(const Timestamp &rhs)
Modulo a Timestamp by an interval.
Definition: Timestamp.hpp:137
void setMinute(int minutes)
Set minutes after the hour.
void setYear(int year)
Set year.
static Timestamp minutes(double minutes)
Construct an interval from minutes.
Definition: Timestamp.hpp:200
int getDayOfWeek() const
Return day since Sunday.
int getYear() const
Return year.
int getDayOfMonth() const
Return day of month.
bool operator<(const Timestamp &rhs) const
Return true if this Timestamp is before rhs.
Definition: Timestamp.hpp:143
bool operator==(const Timestamp &rhs) const
Return true if this Timestamp is at the same time as rhs.
Definition: Timestamp.hpp:152
bool operator<=(const Timestamp &rhs) const
Return true if this Timestamp is before or at the same time as rhs.
Definition: Timestamp.hpp:148
static Timestamp weeks(double weeks)
Construct an interval from weeks.
Definition: Timestamp.hpp:239
static Timestamp seconds(double seconds)
Create a time from a count of seconds.
Definition: Timestamp.hpp:187
std::string as_string(bool displayTimezone=true) const
Return a human readable string rep of this Timestamp.