BDE 4.14.0 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.
197struct EpochUtil {
198
199 public:
200 // TYPES
201
202 /// `TimeT64` is an alias for a 64-bit integral type representing
203 /// seconds from the epoch in UTC. Note that, in contrast with
204 /// `bsl::time_t`, this type can be used in conversions to and from
205 /// `Datetime` values that are less than the epoch (corresponding to
206 /// negative `TimeT64` values).
208
209 private:
210 // CLASS DATA
211 static const TimeT64 s_earliestAsTimeT64; // January 1, 0001 00:00:00
212 static const TimeT64 s_latestAsTimeT64; // December 31, 9999 23:59:59
213
214 public:
215 // CLASS METHODS
216
217 /// Return a reference providing non-modifiable access to the epoch
218 /// time: midnight on January 1, 1970. Note that this value exists
219 /// before any code is executed and will continue to exist, unchanged,
220 /// until the program exits.
221 static const Datetime& epoch();
222
223 // `time_t`-Based Methods
224
225 /// Return, as a `Datetime`, the absolute datetime computed as the sum
226 /// of the specified relative `time` and the epoch. The behavior is
227 /// undefined unless `0 <= time` and, for the resultant `Datetime` `dt`,
228 /// `0 == convertToTimeT(&time, dt)` (i.e., `time` is representable as a
229 /// 32-bit `int`). Note that the returned value will use Coordinated
230 /// Universal Time (UTC) as a reference.
231 static Datetime convertFromTimeT(bsl::time_t time);
232
233 /// Load into the specified `result` the absolute datetime converted to
234 /// a `Datetime`, computed as the sum of the specified relative `time`
235 /// and the epoch. The behavior is undefined unless `0 <= time` and
236 /// `0 == convertToTimeT(&time, *result)` (i.e., `time` is representable
237 /// as a 32-bit `int`). Note that `result` will use Coordinated
238 /// Universal Time (UTC) as a reference.
239 static void convertFromTimeT(Datetime *result, bsl::time_t time);
240
241 /// Return the relative time computed as the difference between the
242 /// specified absolute `datetime` and the epoch. The behavior is
243 /// undefined unless `datetime - epoch() >= DatetimeInterval()` and the
244 /// converted `datetime` can be represented in the destination format on
245 /// all supported platforms (i.e., the resultant value is representable
246 /// as a 32-bit `int`). Note that `datetime` is assumed to use
247 /// Coordinated Universal Time (UTC) as a reference. Also note that if
248 /// error detection is desired, the overloaded version that loads the
249 /// converted `datetime` into a supplied destination object should be
250 /// used.
251 static bsl::time_t convertToTimeT(const Datetime& datetime);
252
253 /// Load into the specified `result` the relative time computed as the
254 /// difference between the specified absolute `datetime` and the epoch.
255 /// Return 0 on success, and a non-zero value (with no effect on
256 /// `result`) if `datetime - epoch() < DatetimeInterval()` or `datetime`
257 /// cannot be represented in the destination format on all supported
258 /// platforms (i.e., the computed `*result` is not representable as a
259 /// 32-bit `int`). Note that `datetime` is assumed to use Coordinated
260 /// Universal Time (UTC) as a reference.
261 static int convertToTimeT(bsl::time_t *result,
262 const Datetime& datetime);
263
264 // `TimeT64`-Based Methods
265
266 /// Return, as a `Datetime`, the absolute datetime computed as the sum
267 /// of the specified relative `time` and the epoch. The behavior is
268 /// undefined unless the converted `time` can be represented in the
269 /// destination format. Note that the returned value will use
270 /// Coordinated Universal Time (UTC) as a reference. Also note that if
271 /// error detection is desired, the overloaded version that loads the
272 /// converted `time` into a supplied destination object should be used.
274
275 /// Load into the specified `result` the absolute datetime converted to
276 /// a `Datetime`, computed as the sum of the specified relative `time`
277 /// and the epoch. Return 0 on success, and a non-zero value (with no
278 /// effect on `result`) if `time` cannot be represented in the
279 /// destination format. Note that `result` will use Coordinated
280 /// Universal Time (UTC) as a reference.
281 static int convertFromTimeT64(Datetime *result, TimeT64 time);
282
283 /// Return the relative time computed as the difference between the
284 /// specified absolute `datetime` and the epoch. Note that `datetime`
285 /// is assumed to use Coordinated Universal Time (UTC) as a reference.
286 static TimeT64 convertToTimeT64(const Datetime& datetime);
287
288 /// Load into the specified `result` the relative time computed as the
289 /// difference between the specified absolute `datetime` and the epoch.
290 /// Note that `datetime` is assumed to use Coordinated Universal Time
291 /// (UTC) as a reference.
292 static void convertToTimeT64(TimeT64 *result,
293 const Datetime& datetime);
294
295 // `bsls::TimeInterval`-Based Methods
296
297 /// Return, as a `Datetime`, the absolute datetime computed as the sum
298 /// of the specified relative `timeInterval` and the epoch. The
299 /// behavior is undefined unless the conversion result can be
300 /// represented as a `Datetime`. Note that the conversion is
301 /// potentially lossy as the resolution of `bsls::TimeInterval` is
302 /// greater than that of `Datetime`.
304 const bsls::TimeInterval& timeInterval);
305
306 /// Load into the specified `result` the absolute datetime converted to
307 /// a `Datetime`, computed as the sum of the specified relative
308 /// `timeInterval` and the epoch. The behavior is undefined unless the
309 /// conversion result can be represented as a `Datetime`. Note that the
310 /// conversion is potentially lossy as the resolution of
311 /// `bsls::TimeInterval` is greater than that of `Datetime`.
312 static void convertFromTimeInterval(
313 Datetime *result,
314 const bsls::TimeInterval& timeInterval);
315
316 /// Return, as a `bsls::TimeInterval`, the relative time computed as the
317 /// difference between the specified absolute `datetime` and the epoch.
318 static bsls::TimeInterval convertToTimeInterval(const Datetime& datetime);
319
320 // `DatetimeInterval`-Based Methods
321
322 /// Return, as a `Datetime`, the absolute datetime computed as the sum
323 /// of the specified relative `datetimeInterval` and the epoch. The
324 /// behavior is undefined unless the conversion result can be
325 /// represented as a `Datetime`.
327 const DatetimeInterval& datetimeInterval);
328
329 /// Load into the specified `result` the absolute datetime converted to
330 /// a `Datetime`, computed as the sum of the specified relative
331 /// `datetimeInterval` and the epoch. The behavior is undefined unless
332 /// the conversion result can be represented as a `Datetime`.
333 static void convertFromDatetimeInterval(
334 Datetime *result,
335 const DatetimeInterval& datetimeInterval);
336
337 /// Return, as a `DatetimeInterval`, the relative time computed as the
338 /// difference between the specified absolute `datetime` and the epoch.
340 const Datetime& datetime);
341
342 // DEPRECATED CLASS METHODS
343
344 /// @deprecated Use @ref convertToTimeInterval(datetime) instead.
345 ///
346 /// If `datetime - epoch() >= DatetimeInterval()`, load into the
347 /// specified `result` the relative time converted to a
348 /// `bsls::TimeInterval`, computed as the difference between the
349 /// specified absolute `datetime` and the epoch, and return 0.
350 /// Otherwise, return a non-zero value (with no effect on `result`).
351 static int convertToTimeInterval(bsls::TimeInterval *result,
352 const Datetime& datetime);
353
354 /// @deprecated Use @ref convertToDatetimeInterval(datetime) instead.
355 ///
356 /// If `datetime - epoch() >= DatetimeInterval()`, load into the
357 /// specified `result` the relative time converted to a
358 /// `DatetimeInterval`, computed as the difference between the specified
359 /// absolute `datetime` and the epoch, and return 0. Otherwise, return
360 /// a non-zero value (with no effect on `result`).
362 const Datetime& datetime);
363};
364
365// ============================================================================
366// INLINE DEFINITIONS
367// ============================================================================
368
369 // ----------------
370 // struct EpochUtil
371 // ----------------
372
373// CLASS METHODS
374inline
379
380 // 'time_t'-Based Methods
381
382inline
384{
385 BSLS_REVIEW(0 <= time);
386
387 Datetime datetime(epoch());
388 datetime.addSeconds(time);
389
390 return datetime;
391}
392
393inline
394void EpochUtil::convertFromTimeT(Datetime *result, bsl::time_t time)
395{
396 BSLS_REVIEW(result);
397 BSLS_REVIEW(0 <= time);
398
399 *result = epoch();
400 result->addSeconds(time);
401}
402
403inline
404bsl::time_t EpochUtil::convertToTimeT(const Datetime& datetime)
405{
406 const DatetimeInterval dti = datetime - epoch();
407
409 BSLS_REVIEW(dti.totalSeconds() <= 0x7fffffffLL);
410
411 // Note that, with safe-assertions disabled, the representation of
412 // 'bsl::time_t' must not affect the resultant 'bsl::time_t' (i.e., in case
413 // 'bsl::time_t' is 64-bit).
414
415 return bsl::time_t(static_cast<int>(dti.totalSeconds()));
416}
417
418inline
419int EpochUtil::convertToTimeT(bsl::time_t *result, const Datetime& datetime)
420{
421 BSLS_REVIEW(result);
422
423 const DatetimeInterval dti = datetime - epoch();
424
425 if (dti < DatetimeInterval()) {
426 return 1; // RETURN
427 }
428
429 const bsls::Types::Int64 seconds = dti.totalSeconds();
430
431 if (seconds > 0x7fffffffLL) {
432 return 1; // RETURN
433 }
434
435 *result = static_cast<bsl::time_t>(seconds);
436
437 return 0;
438}
439
440 // 'TimeT64'-Based Methods
441
442inline
444{
445 BSLS_REVIEW(s_earliestAsTimeT64 <= time);
446 BSLS_REVIEW( time <= s_latestAsTimeT64);
447
448 Datetime datetime(epoch());
449 datetime.addSeconds(time);
450
451 return datetime;
452}
453
454inline
456{
457 BSLS_REVIEW(result);
458
459 if (time < s_earliestAsTimeT64 || time > s_latestAsTimeT64) {
460 return 1; // RETURN
461 }
462
463 *result = epoch();
464 result->addSeconds(time);
465
466 return 0;
467}
468
469inline
472{
473 int hour;
474 int minute;
475 int second;
476
477 datetime.getTime(&hour, &minute, &second);
478
479 Datetime dt(datetime.date());
480 dt.setTime(hour, minute, second);
481
482 return TimeT64((dt - epoch()).totalSeconds());
483}
484
485inline
486void EpochUtil::convertToTimeT64(TimeT64 *result, const Datetime& datetime)
487{
488 BSLS_REVIEW(result);
489
490 *result = EpochUtil::convertToTimeT64(datetime);
491}
492
493 // 'bsls::TimeInterval'-Based Methods
494
495inline
497 const bsls::TimeInterval& timeInterval)
498{
499 return epoch() + timeInterval;
500}
501
502inline
504 Datetime *result,
505 const bsls::TimeInterval& timeInterval)
506{
507 BSLS_REVIEW(result);
508
509 *result = epoch() + timeInterval;
510}
511
512inline
514{
515 const DatetimeInterval dti = datetime - epoch();
516
517 return bsls::TimeInterval(dti.totalSeconds(),
518 dti.milliseconds() * 1000000
519 + dti.microseconds() * 1000);
520}
521
522 // 'DatetimeInterval'-Based Methods
523
524inline
526 const DatetimeInterval& datetimeInterval)
527{
528 return epoch() + datetimeInterval;
529}
530
531inline
533 Datetime *result,
534 const DatetimeInterval& datetimeInterval)
535{
536 BSLS_REVIEW(result);
537
538 *result = epoch() + datetimeInterval;
539}
540
541inline
543{
544 return datetime - epoch();
545}
546
547// DEPRECATED CLASS METHODS
548inline
550 const Datetime& datetime)
551{
552 BSLS_REVIEW(result);
553
554 const DatetimeInterval dti = datetime - epoch();
555
556 if (dti < DatetimeInterval()) {
557 return 1; // RETURN
558 }
559 result->setInterval(dti.totalSeconds(),
560 dti.milliseconds() * 1000000
561 + dti.microseconds() * 1000);
562
563 return 0;
564}
565
566inline
568 const Datetime& datetime)
569{
570 BSLS_REVIEW(result);
571
572 if (datetime - epoch() < DatetimeInterval()) {
573 return 1; // RETURN
574 }
575 *result = datetime - epoch();
576
577 return 0;
578}
579
580} // close package namespace
581
582
583#endif
584
585// ----------------------------------------------------------------------------
586// Copyright 2017 Bloomberg Finance L.P.
587//
588// Licensed under the Apache License, Version 2.0 (the "License");
589// you may not use this file except in compliance with the License.
590// You may obtain a copy of the License at
591//
592// http://www.apache.org/licenses/LICENSE-2.0
593//
594// Unless required by applicable law or agreed to in writing, software
595// distributed under the License is distributed on an "AS IS" BASIS,
596// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
597// See the License for the specific language governing permissions and
598// limitations under the License.
599// ----------------------------- END-OF-FILE ----------------------------------
600
601/** @} */
602/** @} */
603/** @} */
Definition bdlt_datetimeinterval.h:201
int milliseconds() const
Definition bdlt_datetimeinterval.h:1137
bsls::Types::Int64 totalSeconds() const
Definition bdlt_datetimeinterval.h:1170
int microseconds() const
Definition bdlt_datetimeinterval.h:1144
Definition bdlt_datetime.h:331
Date date() const
Return the value of the "date" part of this object.
Definition bdlt_datetime.h:2164
void setTime(const Time &time)
Definition bdlt_datetime.h:1550
Datetime & addSeconds(bsls::Types::Int64 seconds)
Definition bdlt_datetime.h:2024
void getTime(int *hour, int *minute=0, int *second=0, int *millisecond=0, int *microsecond=0) const
Definition bdlt_datetime.h:2190
Definition bsls_timeinterval.h:301
BSLS_KEYWORD_CONSTEXPR_CPP14 void setInterval(bsls::Types::Int64 seconds, int nanoseconds=0)
Definition bsls_timeinterval.h:1245
#define BSLS_IDENT(str)
Definition bsls_ident.h:195
#define BSLS_REVIEW(X)
Definition bsls_review.h:949
Definition bbldc_basicisma30360.h:112
static const Datetime * epoch_1970_01_01()
Definition bdlt_epochutil.h:197
static Datetime convertFromDatetimeInterval(const DatetimeInterval &datetimeInterval)
Definition bdlt_epochutil.h:525
static Datetime convertFromTimeT64(TimeT64 time)
Definition bdlt_epochutil.h:443
static bsl::time_t convertToTimeT(const Datetime &datetime)
Definition bdlt_epochutil.h:404
static DatetimeInterval convertToDatetimeInterval(const Datetime &datetime)
Definition bdlt_epochutil.h:542
static Datetime convertFromTimeT(bsl::time_t time)
Definition bdlt_epochutil.h:383
static const Datetime & epoch()
Definition bdlt_epochutil.h:375
static Datetime convertFromTimeInterval(const bsls::TimeInterval &timeInterval)
Definition bdlt_epochutil.h:496
static TimeT64 convertToTimeT64(const Datetime &datetime)
Definition bdlt_epochutil.h:471
bsls::Types::Int64 TimeT64
Definition bdlt_epochutil.h:207
static bsls::TimeInterval convertToTimeInterval(const Datetime &datetime)
Definition bdlt_epochutil.h:513
long long Int64
Definition bsls_types.h:132