BDE 4.39.x Production Release
Loading...
Searching...
No Matches
bdlt_epochutil.h
Go to the documentation of this file.
1/// @file bdlt_epochutil.h
2///
3/// The content of this file has been pre-processed for Doxygen.
4///
5
6
7// bdlt_epochutil.h -*-C++-*-
8#ifndef INCLUDED_BDLT_EPOCHUTIL
9#define INCLUDED_BDLT_EPOCHUTIL
10
11#include <bsls_ident.h>
12BSLS_IDENT("$Id: $")
13
14/// @defgroup bdlt_epochutil bdlt_epochutil
15/// @brief Conversion between absolute/relative time with respect to epoch.
16/// @addtogroup bdl
17/// @{
18/// @addtogroup bdlt
19/// @{
20/// @addtogroup bdlt_epochutil
21/// @{
22///
23/// <h1> Outline </h1>
24/// * <a href="#bdlt_epochutil-purpose"> Purpose</a>
25/// * <a href="#bdlt_epochutil-classes"> Classes </a>
26/// * <a href="#bdlt_epochutil-description"> Description </a>
27/// * <a href="#bdlt_epochutil-thread-safety"> Thread Safety </a>
28/// * <a href="#bdlt_epochutil-usage"> Usage </a>
29/// * <a href="#bdlt_epochutil-example-1-converting-between-various-representations-of-time"> Example 1: Converting Between Various Representations of Time </a>
30///
31/// # Purpose {#bdlt_epochutil-purpose}
32/// Conversion between absolute/relative time with respect to epoch.
33///
34/// # Classes {#bdlt_epochutil-classes}
35///
36/// - bdlt::EpochUtil: non-primitive functions on epoch-related conversions
37///
38/// @see bdlt_datetime, bdlt_datetimeinterval, bsls_timeinterval
39///
40/// # Description {#bdlt_epochutil-description}
41/// This component defines a namespace, `bdlt::EpochUtil`,
42/// providing non-primitive conversions between two different concepts of time.
43/// Clients can convert between absolute time (`bdlt::Datetime`) and relative
44/// time (such as `bsl::time_t`, `bdlt::EpochUtil::TimeT64`,
45/// `bsls::TimeInterval`, and `bdlt::DatetimeInterval`) with respect to the Unix
46/// standard "epoch" (1970/01/01_00:00:00.000 UTC), henceforth, simply referred
47/// to as "the epoch". Also provided is a fast, thread-safe method, `epoch`,
48/// for access to a pre-instantiated `bdlt::Datetime` object whose (constant)
49/// value is that of the epoch.
50///
51/// Due to different resolutions, conversions between absolute/relative time are
52/// possibly lossy when converting from a type with higher resolution to one
53/// with lower resolution. The value of the type with higher resolution will be
54/// truncated (not rounded). The following table lists the resolution of the
55/// types involved in this component:
56/// @code
57/// Type Reference Resolution
58/// --------------------- -------------- ------------
59/// bsl::time_t relative seconds
60/// bdlt::EpochUtil::TimeT64 relative seconds
61/// bdlt::Datetime absolute (UTC) microseconds
62/// bdlt::DatetimeInterval relative microseconds
63/// bsls::TimeInterval relative nanoseconds
64/// @endcode
65/// Note that the interfaces using `bdlt::EpochUtil::TimeT64` can be validly
66/// used for values before the epoch (corresponding to negative `TimeT64`
67/// values), whereas the interfaces using `bsl::time_t` have undefined behavior
68/// for such input. Furthermore, even on platforms where `bsl::time_t` is a
69/// 64-bit value, clients of this component are strongly encouraged to use the
70/// `TimeT64`-based methods to avoid limitations imposed by the
71/// `bsl::time_t`-based methods required to ensure identical behavior on all
72/// supported platforms (e.g., see the function-level documentation for
73/// `convertToTimeT(bsl::time_t)`).
74///
75/// Also note that these conversions do not take into account the leap seconds
76/// (25 as of this writing) added to UTC by the International Earth Rotation and
77/// Reference Systems Service, but simply regard each day as having a fixed
78/// number of seconds (24 hours * 60 minutes per hour * 60 seconds per minute).
79///
80/// ## Thread Safety {#bdlt_epochutil-thread-safety}
81///
82///
83/// It is safe to invoke any function defined in this component in two or more
84/// separate threads simultaneously, provided no other thread is simultaneously
85/// modifying the argument passed by reference to a non-modifiable user-defined
86/// type (such as `bsls::TimeInterval` or `bdlt::Datetime`).
87///
88/// ## Usage {#bdlt_epochutil-usage}
89///
90///
91/// This section illustrates intended use of this component.
92///
93/// ### Example 1: Converting Between Various Representations of Time {#bdlt_epochutil-example-1-converting-between-various-representations-of-time}
94///
95///
96/// When processing date/time data, we are often required to deal with a variety
97/// of ways in which to represent that data, and therefore we need to be able to
98/// convert between those representations. We can use the methods contained in
99/// `bdlt::EpochUtil` to do this.
100///
101/// First, we set up date/time input values in a variety of formats. We'll use
102/// 900ms past midnight of January 1, 2000 as the base date and time, dropping
103/// the 900ms if the resolution of a format doesn't support it:
104/// @code
105/// const bsl::time_t inputTime (946684800);
106/// const bsls::TimeInterval inputTimeInterval (946684800, 900000000);
107/// const bdlt::DatetimeInterval inputDatetimeInterval(
108/// 0, 0, 0, 0, 946684800900LL);
109/// const bdlt::Datetime inputDatetime (2000, 1, 1, 0, 0, 0, 900);
110/// @endcode
111/// Then, we set up a set of output variables to receive converted values:
112/// @code
113/// bsl::time_t outputTime = 0;
114/// bsls::TimeInterval outputTimeInterval;
115/// bdlt::DatetimeInterval outputDatetimeInterval;
116/// bdlt::Datetime outputDatetime;
117/// @endcode
118/// Next, because `bdlt::EpochUtil` uses `bdlt::Datetime` as the common format
119/// for conversion, we will set up a pair of variables in this format to
120/// represent the values we expect to see:
121/// @code
122/// const bdlt::Datetime epochDatetimeWithMs (2000, 1, 1, 0, 0, 0, 900);
123/// const bdlt::Datetime epochDatetimeWithoutMs(2000, 1, 1, 0, 0, 0, 0);
124/// @endcode
125/// Now, we perform a set of conversions to `bdlt::Datetime` and verify that the
126/// results are correct. We will use the conversion methods that return by
127/// value:
128/// @code
129/// outputDatetime = bdlt::EpochUtil::convertFromTimeT(inputTime);
130/// assert(epochDatetimeWithoutMs == outputDatetime);
131///
132/// outputDatetime =
133/// bdlt::EpochUtil::convertFromTimeInterval(inputTimeInterval);
134/// assert(epochDatetimeWithMs == outputDatetime);
135///
136/// outputDatetime =
137/// bdlt::EpochUtil::convertFromDatetimeInterval(inputDatetimeInterval);
138/// assert(epochDatetimeWithMs == outputDatetime);
139/// @endcode
140/// Finally, we perform a set of conversions from `bdlt::Datetime` and verify
141/// that the results are correct. This time, for variety, we will illustrate
142/// the conversion methods which return through an object pointer:
143/// @code
144/// assert(0 == bdlt::EpochUtil::convertToTimeT(&outputTime, inputDatetime));
145/// assert(inputTime == outputTime);
146///
147/// assert(0 == bdlt::EpochUtil::convertToTimeInterval(&outputTimeInterval,
148/// inputDatetime));
149/// assert(inputTimeInterval == outputTimeInterval);
150///
151/// assert(0 == bdlt::EpochUtil::convertToDatetimeInterval(
152/// &outputDatetimeInterval,
153/// inputDatetime));
154/// assert(inputDatetimeInterval == outputDatetimeInterval);
155/// @endcode
156/// @}
157/** @} */
158/** @} */
159
160/** @addtogroup bdl
161 * @{
162 */
163/** @addtogroup bdlt
164 * @{
165 */
166/** @addtogroup bdlt_epochutil
167 * @{
168 */
169
170#include <bdlscm_version.h>
171
172#include <bdlt_datetime.h>
173#include <bdlt_datetimeimputil.h>
175#include <bdlt_time.h>
176
177#include <bsls_assert.h>
178#include <bsls_review.h>
179#include <bsls_timeinterval.h>
180#include <bsls_types.h> // 'Int64', 'Uint64'
181
182#include <bsl_ctime.h> // 'bsl::time_t'
183
184
185namespace bdlt {
186
187 // ================
188 // struct EpochUtil
189 // ================
190
191/// This `struct` provides a namespace for a suite of non-primitive
192/// functions providing conversions between absolute `Datetime` values and
193/// corresponding relative time intervals with respect to the Unix standard
194/// epoch time, returned by the `epoch` method. These methods are
195/// alias-safe, thread-safe, and exception-neutral. Functions are provided
196/// for returning converted values by value or through a result pointer.
197///
198/// See @ref bdlt_epochutil
199struct EpochUtil {
200
201 public:
202 // TYPES
203
204 /// `TimeT64` is an alias for a 64-bit integral type representing seconds from the epoch in UTC.
205 ///
206 /// \note Note that, in contrast with
207 /// `bsl::time_t`, this type can be used in conversions to and from
208 /// `Datetime` values that are less than the epoch (corresponding to
209 /// negative `TimeT64` values).
211
212 private:
213 // CLASS DATA
214 static const TimeT64 s_earliestAsTimeT64; // January 1, 0001 00:00:00
215 static const TimeT64 s_latestAsTimeT64; // December 31, 9999 23:59:59
216
217 public:
218 // CLASS METHODS
219
220 /// Return a reference providing non-modifiable access to the epoch time: midnight on January 1, 1970.
221 ///
222 /// \note Note that this value exists
223 /// before any code is executed and will continue to exist, unchanged,
224 /// until the program exits.
225 static const Datetime& epoch();
226
227 // `time_t`-Based Methods
228
229 /// Return, as a `Datetime`, the absolute datetime computed as the sum
230 /// of the specified relative `time` and the epoch.
231 ///
232 /// \pre The behavior is undefined unless `0 <= time` and, for the resultant `Datetime` `dt`,
233 /// `0 == convertToTimeT(&time, dt)` (i.e., `time` is representable as a 32-bit `int`).
234 ///
235 /// \note Note that the returned value will use Coordinated
236 /// Universal Time (UTC) as a reference.
237 static Datetime convertFromTimeT(bsl::time_t time);
238
239 /// Load into the specified `result` the absolute datetime converted to
240 /// a `Datetime`, computed as the sum of the specified relative `time` and the epoch.
241 ///
242 /// \pre The behavior is undefined unless `0 <= time` and
243 /// `0 == convertToTimeT(&time, *result)` (i.e., `time` is representable as a 32-bit `int`).
244 ///
245 /// \note Note that `result` will use Coordinated
246 /// Universal Time (UTC) as a reference.
247 static void convertFromTimeT(Datetime *result, bsl::time_t time);
248
249 /// Return the relative time computed as the difference between the
250 /// specified absolute `datetime` and the epoch.
251 ///
252 /// \pre The behavior is undefined unless `datetime - epoch() >= DatetimeInterval()` and the
253 /// converted `datetime` can be represented in the destination format on
254 /// all supported platforms (i.e., the resultant value is representable as a 32-bit `int`).
255 ///
256 /// \note Note that `datetime` is assumed to use
257 /// Coordinated Universal Time (UTC) as a reference. Also note that if
258 /// error detection is desired, the overloaded version that loads the
259 /// converted `datetime` into a supplied destination object should be
260 /// used.
261 static bsl::time_t convertToTimeT(const Datetime& datetime);
262
263 /// Load into the specified `result` the relative time computed as the
264 /// difference between the specified absolute `datetime` and the epoch.
265 /// Return 0 on success, and a non-zero value (with no effect on
266 /// `result`) if `datetime - epoch() < DatetimeInterval()` or `datetime`
267 /// cannot be represented in the destination format on all supported
268 /// platforms (i.e., the computed `*result` is not representable as a 32-bit `int`).
269 ///
270 /// \note Note that `datetime` is assumed to use Coordinated
271 /// Universal Time (UTC) as a reference.
272 static int convertToTimeT(bsl::time_t *result,
273 const Datetime& datetime);
274
275 // `TimeT64`-Based Methods
276
277 /// Return, as a `Datetime`, the absolute datetime computed as the sum
278 /// of the specified relative `time` and the epoch.
279 ///
280 /// \pre The behavior is undefined unless the converted `time` can be represented in the destination format.
281 ///
282 /// \note Note that the returned value will use
283 /// Coordinated Universal Time (UTC) as a reference. Also note that if
284 /// error detection is desired, the overloaded version that loads the
285 /// converted `time` into a supplied destination object should be used.
287
288 /// Load into the specified `result` the absolute datetime converted to
289 /// a `Datetime`, computed as the sum of the specified relative `time`
290 /// and the epoch. Return 0 on success, and a non-zero value (with no
291 /// effect on `result`) if `time` cannot be represented in the destination format.
292 ///
293 /// \note Note that `result` will use Coordinated
294 /// Universal Time (UTC) as a reference.
295 static int convertFromTimeT64(Datetime *result, TimeT64 time);
296
297 /// Return the relative time computed as the difference between the specified absolute `datetime` and the epoch.
298 ///
299 /// \note Note that `datetime`
300 /// is assumed to use Coordinated Universal Time (UTC) as a reference.
301 static TimeT64 convertToTimeT64(const Datetime& datetime);
302
303 /// Load into the specified `result` the relative time computed as the
304 /// difference between the specified absolute `datetime` and the epoch.
305 ///
306 /// \note Note that `datetime` is assumed to use Coordinated Universal Time
307 /// (UTC) as a reference.
308 static void convertToTimeT64(TimeT64 *result,
309 const Datetime& datetime);
310
311 // `bsls::TimeInterval`-Based Methods
312
313 /// Return, as a `Datetime`, the absolute datetime computed as the sum
314 /// of the specified relative `timeInterval` and the epoch.
315 ///
316 /// \pre The behavior is undefined unless the conversion result can be represented as a `Datetime`.
317 ///
318 /// \note Note that the conversion is
319 /// potentially lossy as the resolution of `bsls::TimeInterval` is
320 /// greater than that of `Datetime`.
322 const bsls::TimeInterval& timeInterval);
323
324 /// Load into the specified `result` the absolute datetime converted to
325 /// a `Datetime`, computed as the sum of the specified relative `timeInterval` and the epoch.
326 ///
327 /// \pre The behavior is undefined unless the conversion result can be represented as a `Datetime`.
328 ///
329 /// \note Note that the
330 /// conversion is potentially lossy as the resolution of
331 /// `bsls::TimeInterval` is greater than that of `Datetime`.
332 static void convertFromTimeInterval(
333 Datetime *result,
334 const bsls::TimeInterval& timeInterval);
335
336 /// Return, as a `bsls::TimeInterval`, the relative time computed as the
337 /// difference between the specified absolute `datetime` and the epoch.
338 static bsls::TimeInterval convertToTimeInterval(const Datetime& datetime);
339
340 // `DatetimeInterval`-Based Methods
341
342 /// Return, as a `Datetime`, the absolute datetime computed as the sum
343 /// of the specified relative `datetimeInterval` and the epoch.
344 ///
345 /// \pre The behavior is undefined unless the conversion result can be
346 /// represented as a `Datetime`.
348 const DatetimeInterval& datetimeInterval);
349
350 /// Load into the specified `result` the absolute datetime converted to
351 /// a `Datetime`, computed as the sum of the specified relative `datetimeInterval` and the epoch.
352 ///
353 /// \pre The behavior is undefined unless
354 /// the conversion result can be represented as a `Datetime`.
355 static void convertFromDatetimeInterval(
356 Datetime *result,
357 const DatetimeInterval& datetimeInterval);
358
359 /// Return, as a `DatetimeInterval`, the relative time computed as the
360 /// difference between the specified absolute `datetime` and the epoch.
362 const Datetime& datetime);
363
364 // DEPRECATED CLASS METHODS
365
366 /// If `datetime - epoch() >= DatetimeInterval()`, load into the
367 /// specified `result` the relative time converted to a
368 /// `bsls::TimeInterval`, computed as the difference between the
369 /// specified absolute `datetime` and the epoch, and return 0.
370 /// Otherwise, return a non-zero value (with no effect on `result`).
371 ///
372 /// @deprecated Use @ref convertToTimeInterval(datetime) instead.
373 static int convertToTimeInterval(bsls::TimeInterval *result,
374 const Datetime& datetime);
375
376 /// If `datetime - epoch() >= DatetimeInterval()`, load into the
377 /// specified `result` the relative time converted to a
378 /// `DatetimeInterval`, computed as the difference between the specified
379 /// absolute `datetime` and the epoch, and return 0. Otherwise, return
380 /// a non-zero value (with no effect on `result`).
381 ///
382 /// @deprecated Use @ref convertToDatetimeInterval(datetime) instead.
384 const Datetime& datetime);
385};
386
387// ============================================================================
388// INLINE DEFINITIONS
389// ============================================================================
390
391 // ----------------
392 // struct EpochUtil
393 // ----------------
394
395// CLASS METHODS
396inline
401
402 // 'time_t'-Based Methods
403
404inline
406{
407 BSLS_REVIEW(0 <= time);
408
409 Datetime datetime(epoch());
410 datetime.addSeconds(time);
411
412 return datetime;
413}
414
415inline
416void EpochUtil::convertFromTimeT(Datetime *result, bsl::time_t time)
417{
418 BSLS_REVIEW(result);
419 BSLS_REVIEW(0 <= time);
420
421 *result = epoch();
422 result->addSeconds(time);
423}
424
425inline
426bsl::time_t EpochUtil::convertToTimeT(const Datetime& datetime)
427{
428 const DatetimeInterval dti = datetime - epoch();
429
431 BSLS_REVIEW(dti.totalSeconds() <= 0x7fffffffLL);
432
433 // Note that, with safe-assertions disabled, the representation of
434 // 'bsl::time_t' must not affect the resultant 'bsl::time_t' (i.e., in case
435 // 'bsl::time_t' is 64-bit).
436
437 return bsl::time_t(static_cast<int>(dti.totalSeconds()));
438}
439
440inline
441int EpochUtil::convertToTimeT(bsl::time_t *result, const Datetime& datetime)
442{
443 BSLS_REVIEW(result);
444
445 const DatetimeInterval dti = datetime - epoch();
446
447 if (dti < DatetimeInterval()) {
448 return 1; // RETURN
449 }
450
451 const bsls::Types::Int64 seconds = dti.totalSeconds();
452
453 if (seconds > 0x7fffffffLL) {
454 return 1; // RETURN
455 }
456
457 *result = static_cast<bsl::time_t>(seconds);
458
459 return 0;
460}
461
462 // 'TimeT64'-Based Methods
463
464inline
466{
467 BSLS_REVIEW(s_earliestAsTimeT64 <= time);
468 BSLS_REVIEW( time <= s_latestAsTimeT64);
469
470 Datetime datetime(epoch());
471 datetime.addSeconds(time);
472
473 return datetime;
474}
475
476inline
478{
479 BSLS_REVIEW(result);
480
481 if (time < s_earliestAsTimeT64 || time > s_latestAsTimeT64) {
482 return 1; // RETURN
483 }
484
485 *result = epoch();
486 result->addSeconds(time);
487
488 return 0;
489}
490
491inline
494{
495 int hour;
496 int minute;
497 int second;
498
499 datetime.getTime(&hour, &minute, &second);
500
501 Datetime dt(datetime.date());
502 dt.setTime(hour, minute, second);
503
504 return TimeT64((dt - epoch()).totalSeconds());
505}
506
507inline
508void EpochUtil::convertToTimeT64(TimeT64 *result, const Datetime& datetime)
509{
510 BSLS_REVIEW(result);
511
512 *result = EpochUtil::convertToTimeT64(datetime);
513}
514
515 // 'bsls::TimeInterval'-Based Methods
516
517inline
519 const bsls::TimeInterval& timeInterval)
520{
521 return epoch() + timeInterval;
522}
523
524inline
526 Datetime *result,
527 const bsls::TimeInterval& timeInterval)
528{
529 BSLS_REVIEW(result);
530
531 *result = epoch() + timeInterval;
532}
533
534inline
536{
537 const DatetimeInterval dti = datetime - epoch();
538
539 return bsls::TimeInterval(dti.totalSeconds(),
540 dti.milliseconds() * 1000000
541 + dti.microseconds() * 1000);
542}
543
544 // 'DatetimeInterval'-Based Methods
545
546inline
548 const DatetimeInterval& datetimeInterval)
549{
550 return epoch() + datetimeInterval;
551}
552
553inline
555 Datetime *result,
556 const DatetimeInterval& datetimeInterval)
557{
558 BSLS_REVIEW(result);
559
560 *result = epoch() + datetimeInterval;
561}
562
563inline
565{
566 return datetime - epoch();
567}
568
569// DEPRECATED CLASS METHODS
570inline
572 const Datetime& datetime)
573{
574 BSLS_REVIEW(result);
575
576 const DatetimeInterval dti = datetime - epoch();
577
578 if (dti < DatetimeInterval()) {
579 return 1; // RETURN
580 }
581 result->setInterval(dti.totalSeconds(),
582 dti.milliseconds() * 1000000
583 + dti.microseconds() * 1000);
584
585 return 0;
586}
587
588inline
590 const Datetime& datetime)
591{
592 BSLS_REVIEW(result);
593
594 if (datetime - epoch() < DatetimeInterval()) {
595 return 1; // RETURN
596 }
597 *result = datetime - epoch();
598
599 return 0;
600}
601
602} // close package namespace
603
604
605#endif
606
607// ----------------------------------------------------------------------------
608// Copyright 2017 Bloomberg Finance L.P.
609//
610// Licensed under the Apache License, Version 2.0 (the "License");
611// you may not use this file except in compliance with the License.
612// You may obtain a copy of the License at
613//
614// http://www.apache.org/licenses/LICENSE-2.0
615//
616// Unless required by applicable law or agreed to in writing, software
617// distributed under the License is distributed on an "AS IS" BASIS,
618// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
619// See the License for the specific language governing permissions and
620// limitations under the License.
621// ----------------------------- END-OF-FILE ----------------------------------
622
623/** @} */
624/** @} */
625/** @} */
Definition bdlt_datetimeinterval.h:201
int milliseconds() const
Definition bdlt_datetimeinterval.h:1188
bsls::Types::Int64 totalSeconds() const
Definition bdlt_datetimeinterval.h:1221
int microseconds() const
Definition bdlt_datetimeinterval.h:1195
Definition bdlt_datetime.h:330
Date date() const
Return the value of the "date" part of this object.
Definition bdlt_datetime.h:2234
void setTime(const Time &time)
Definition bdlt_datetime.h:1620
Datetime & addSeconds(bsls::Types::Int64 seconds)
Definition bdlt_datetime.h:2094
void getTime(int *hour, int *minute=0, int *second=0, int *millisecond=0, int *microsecond=0) const
Definition bdlt_datetime.h:2260
Definition bsls_timeinterval.h:307
BSLS_KEYWORD_CONSTEXPR_CPP14 void setInterval(bsls::Types::Int64 seconds, int nanoseconds=0)
Definition bsls_timeinterval.h:1320
#define BSLS_IDENT(str)
BSLS_IDENT() - insert string into .comment binary segment (if supported)
Definition bsls_ident.h:238
#define BSLS_REVIEW(X)
Definition bsls_review.h:1019
Definition bbldc_basicisma30360.h:112
static const Datetime * epoch_1970_01_01()
Definition bdlt_epochutil.h:199
static Datetime convertFromDatetimeInterval(const DatetimeInterval &datetimeInterval)
Definition bdlt_epochutil.h:547
static Datetime convertFromTimeT64(TimeT64 time)
Definition bdlt_epochutil.h:465
static bsl::time_t convertToTimeT(const Datetime &datetime)
Definition bdlt_epochutil.h:426
static DatetimeInterval convertToDatetimeInterval(const Datetime &datetime)
Definition bdlt_epochutil.h:564
static Datetime convertFromTimeT(bsl::time_t time)
Definition bdlt_epochutil.h:405
static const Datetime & epoch()
Definition bdlt_epochutil.h:397
static Datetime convertFromTimeInterval(const bsls::TimeInterval &timeInterval)
Definition bdlt_epochutil.h:518
static TimeT64 convertToTimeT64(const Datetime &datetime)
Definition bdlt_epochutil.h:493
bsls::Types::Int64 TimeT64
Definition bdlt_epochutil.h:210
static bsls::TimeInterval convertToTimeInterval(const Datetime &datetime)
Definition bdlt_epochutil.h:535
long long Int64
Definition bsls_types.h:134