BDE 4.39.x Production Release
Loading...
Searching...
No Matches
bdlt_datetimeutil.h
Go to the documentation of this file.
1/// @file bdlt_datetimeutil.h
2///
3/// The content of this file has been pre-processed for Doxygen.
4///
5
6
7// bdlt_datetimeutil.h -*-C++-*-
8#ifndef INCLUDED_BDLT_DATETIMEUTIL
9#define INCLUDED_BDLT_DATETIMEUTIL
10
11#include <bsls_ident.h>
12BSLS_IDENT("$Id: $")
13
14/// @defgroup bdlt_datetimeutil bdlt_datetimeutil
15/// @brief Provide common non-primitive operations on `bdlt::Datetime`.
16/// @addtogroup bdl
17/// @{
18/// @addtogroup bdlt
19/// @{
20/// @addtogroup bdlt_datetimeutil
21/// @{
22///
23/// <h1> Outline </h1>
24/// * <a href="#bdlt_datetimeutil-purpose"> Purpose</a>
25/// * <a href="#bdlt_datetimeutil-classes"> Classes </a>
26/// * <a href="#bdlt_datetimeutil-description"> Description </a>
27/// * <a href="#bdlt_datetimeutil-usage"> Usage </a>
28/// * <a href="#bdlt_datetimeutil-example-1-converting-between-bsl-tm-and-bdlt-datetime"> Example 1: Converting Between bsl::tm and bdlt::Datetime </a>
29///
30/// # Purpose {#bdlt_datetimeutil-purpose}
31/// Provide common non-primitive operations on `bdlt::Datetime`.
32///
33/// # Classes {#bdlt_datetimeutil-classes}
34///
35/// - bdlt::DatetimeUtil: non-primitive functions on `bdlt::Datetime`
36///
37/// @see bdlt_datetime, bdlt_datetimeinterval, bdlt_epochutil
38///
39/// # Description {#bdlt_datetimeutil-description}
40/// This component provides non-primitive operations on
41/// `bdlt::Datetime` objects. In particular, `bdlt::DatetimeUtil` supplies
42/// conversions of universal time to and from the C-standard `struct` `tm`
43/// (which we alias as `bsl::tm`) representations.
44///
45/// This utility component provides the following (static) methods:
46/// @code
47/// int convertFromTm(bdlt::Datetime *result, const tm& timeStruct);
48/// bsl::tm convertToTm(const bdlt::Datetime& datetime);
49/// bsl::optional<Datetime> fromYmdHms(int year,
50/// int month,
51/// int day,
52/// int hour,
53/// int minute,
54/// int second,
55/// int millisecond = 0,
56/// int microsecond = 0);
57/// @endcode
58///
59/// ## Usage {#bdlt_datetimeutil-usage}
60///
61///
62/// This section illustrates intended use of this component.
63///
64/// ### Example 1: Converting Between bsl::tm and bdlt::Datetime {#bdlt_datetimeutil-example-1-converting-between-bsl-tm-and-bdlt-datetime}
65///
66///
67/// When interfacing with legacy systems, we may encounter calls that represent
68/// date/time information using the standard `bsl::tm`. In such cases, we have
69/// to be able to convert that information to/from a `bdlt::Datetime` object in
70/// order to interface with the rest of our systems.
71///
72/// Suppose we have a legacy system that tracks last-access times in terms of
73/// `bsl::tm`. We can use the `convertToTm` and `convertFromTm` routines from
74/// this component to convert that information.
75///
76/// First, we define a class, `MyAccessTracker`, that the legacy system uses to
77/// manage last-access times (eliding the implementation for brevity):
78/// @code
79/// /// This class provides a facility for tracking last access times
80/// /// associated with usernames.
81/// class MyAccessTracker {
82///
83/// // LOCAL TYPE
84/// typedef bsl::map<bsl::string, bsl::tm> TStringTmMap;
85///
86/// // DATA
87/// TStringTmMap m_accesses; // map names to
88/// // accesses
89///
90/// public:
91/// // TRAITS
92/// BSLMF_NESTED_TRAIT_DECLARATION(MyAccessTracker,
93/// bslma::UsesBslmaAllocator);
94///
95/// // CREATORS
96///
97/// /// Create an object which will track the last access time ...
98/// explicit MyAccessTracker(bslma::Allocator *basicAllocator = 0);
99///
100/// // MANIPULATORS
101///
102/// /// Update the last access time for the specified `username` with
103/// /// the specified `accessTime`.
104/// void updateLastAccess(const bsl::string& username,
105/// const bsl::tm& accessTime);
106///
107/// // ACCESSORS
108///
109/// /// Load into the specified `result` the last access time associated
110/// /// with the specified `username`, if any. Return 0 on success, and
111/// /// non-0 (with no effect on `result`) if there's no access time
112/// /// associated with `username`.
113/// int getLastAccess(bsl::tm *result, const bsl::string& username) const;
114/// };
115/// @endcode
116/// Next, we define a utility to allow us to use `bdlt::Datetime` with our
117/// legacy access tracker:
118/// @code
119/// class MyAccessTrackerUtil {
120/// public:
121///
122/// /// Load into the specified `result` the last access time associated
123/// /// with the specified `username` in the specified `tracker`, if
124/// /// any. Returns 0 on success, and non-0 (with no effect on
125/// /// `result`) if there's no access time associated with `username`
126/// /// or the associated access time cannot be converted to
127/// /// `bdlt::Datetime`.
128/// static int getLastAccess(bdlt::Datetime *result,
129/// const MyAccessTracker& tracker,
130/// const bsl::string& username);
131///
132/// /// Update the instance pointed to by the specified `tracker` by
133/// /// adding the specified `username` with its associated specified
134/// /// `accessTime`.
135/// static void updateLastAccess(MyAccessTracker *tracker,
136/// const bsl::string& username,
137/// const bdlt::Datetime& accessTime);
138/// };
139/// @endcode
140/// Then, we implement `getLastAccess`:
141/// @code
142/// // -------------------------
143/// // class MyAccessTrackerUtil
144/// // -------------------------
145///
146/// int MyAccessTrackerUtil::getLastAccess(bdlt::Datetime *result,
147/// const MyAccessTracker& tracker,
148/// const bsl::string& username)
149/// {
150/// BSLS_ASSERT(result);
151///
152/// bsl::tm legacyAccessTime;
153///
154/// int rc = tracker.getLastAccess(&legacyAccessTime, username);
155///
156/// if (rc) {
157/// return rc; // RETURN
158/// }
159///
160/// return bdlt::DatetimeUtil::convertFromTm(result, legacyAccessTime);
161/// }
162/// @endcode
163/// Next, we implement `updateLastAccess`:
164/// @code
165/// void MyAccessTrackerUtil::updateLastAccess(
166/// MyAccessTracker *tracker,
167/// const bsl::string& username,
168/// const bdlt::Datetime& accessTime)
169/// {
170/// BSLS_ASSERT(tracker);
171///
172/// bsl::tm legacyAccessTime;
173///
174/// legacyAccessTime = bdlt::DatetimeUtil::convertToTm(accessTime);
175///
176/// tracker->updateLastAccess(username, legacyAccessTime);
177/// }
178/// @endcode
179/// Finally, we create an access tracker then interact with it using
180/// `bdlt::Datetime` times.
181/// @code
182/// /// Exercise `MyAccessTracker` for pedagogical purposes.
183/// void exerciseTracker()
184/// {
185/// MyAccessTracker accessTracker; // Datetime each user last accessed a
186/// // resource.
187///
188/// bsl::string richtofenName = "Baron von Richtofen";
189/// bdlt::Datetime richtofenDate(1918, 4, 21, 11, 0, 0);
190/// MyAccessTrackerUtil::updateLastAccess(&accessTracker,
191/// richtofenName,
192/// richtofenDate);
193///
194/// // ... some time later ....
195///
196/// bdlt::Datetime lastAccessTime;
197/// int rc = MyAccessTrackerUtil::getLastAccess(&lastAccessTime,
198/// accessTracker,
199/// richtofenName);
200/// assert(0 == rc);
201/// assert(lastAccessTime == richtofenDate);
202///
203/// // Do something with the retrieved date...
204/// }
205/// @endcode
206/// @}
207/** @} */
208/** @} */
209
210/** @addtogroup bdl
211 * @{
212 */
213/** @addtogroup bdlt
214 * @{
215 */
216/** @addtogroup bdlt_datetimeutil
217 * @{
218 */
219
220#include <bdlscm_version.h>
221
222#include <bdlt_datetime.h>
223
224#include <bsls_assert.h>
225#include <bsls_review.h>
226
227#include <bsl_ctime.h> // 'bsl::tm'
228#include <bsl_optional.h>
229
230
231namespace bdlt {
232
233 // ===================
234 // struct DatetimeUtil
235 // ===================
236
237/// This utility `struct` provides a namespace for a suite of functions
238/// operating on objects of type `Datetime`.
239///
240/// See @ref bdlt_datetimeutil
242
243 public:
244 // CLASS METHODS
245
246 /// Load into the specified `result` the value of the specified
247 /// `timeStruct`. Return 0 on success, and a non-zero value with no
248 /// effect on `result` if `timeStruct` is invalid or otherwise cannot be
249 /// represented as a `Datetime`. Values in fields `tm_wday`, `tm_yday`,
250 /// and `tm_isdst` are ignored. The time 24:00:00 will be recognized,
251 /// and leap seconds (i.e., values in `tm_sec` of 60 or 61) which can
252 /// otherwise be represented as a `Datetime` will cause the conversion
253 /// to succeed with the `result` "rolling over" into the zeroth second of next minute.
254 ///
255 /// \note Note that time zones are irrelevant for this
256 /// conversion.
257 static int convertFromTm(Datetime *result, const bsl::tm& timeStruct);
258
259 /// Return or load into the specified `result` the value of the
260 /// specified `datetime` expressed as a `bsl::tm`. Each field in the
261 /// result is set to its proper value except `tm_isdst`, which is set to
262 /// `-1` to indicate that no information on daylight saving time is
263 /// available. A time value of 24:00:00:00 will be converted to 0:00:00.
264 ///
265 /// \note Note that time zones are irrelevant for this conversion.
266 static bsl::tm convertToTm( const Datetime& datetime);
267 static void convertToTm(bsl::tm *result, const Datetime& datetime);
268
269 /// Return an `optional` having a `Datetime` with the specified `year`,
270 /// `month`, `day`, `hour`, `minute`, `second`, and the optionally
271 /// specified `millisecond` and `microsecond`, if those form a valid
272 /// `Datetime` (see `Datetime::isValid`); otherwise return an `optional`
273 /// without a value.
274 static bsl::optional<Datetime> fromYmdHms(int year,
275 int month,
276 int day,
277 int hour,
278 int minute,
279 int second,
280 int millisecond = 0,
281 int microsecond = 0);
282};
283
284// ============================================================================
285// INLINE DEFINITIONS
286// ============================================================================
287
288 // -------------------
289 // struct DatetimeUtil
290 // -------------------
291
292inline
294 const bsl::tm& timeStruct)
295{
296 BSLS_ASSERT(result);
297
298 bool isLeapSecond = false;
299 int seconds = timeStruct.tm_sec;
300
301 if (seconds > 59) {
302 // Start handling leap seconds by shifting to the previous non-leap
303 // second time.
304 isLeapSecond = true;
305 seconds = 59;
306 }
307
308 int rc = result->setDatetimeIfValid(timeStruct.tm_year + 1900,
309 timeStruct.tm_mon + 1,
310 timeStruct.tm_mday,
311 timeStruct.tm_hour,
312 timeStruct.tm_min,
313 seconds); // msec = 0
314
315 if (isLeapSecond && !rc) {
316 // Finish leap second handling by rolling over into second '0' in the
317 // next minute.
318 result->addSeconds(1);
319 }
320
321 return rc;
322}
323
324inline
325bsl::tm DatetimeUtil::convertToTm(const Datetime& datetime)
326{
327
328 // 'struct tm' may contain non POSIX standard fields (e.g., on Linux/OSX),
329 // which we want to 0 initialize.
330
331 bsl::tm result = bsl::tm();
332
333 result.tm_sec = datetime.second();
334 result.tm_min = datetime.minute();
335 const int hour = datetime.hour();
336 if (24 == hour) {
337 result.tm_hour = 0;
338 }
339 else {
340 result.tm_hour = hour;
341 }
342 result.tm_mday = datetime.day();
343 result.tm_mon = datetime.month() - 1;
344 result.tm_year = datetime.year() - 1900;
345 result.tm_wday = datetime.date().dayOfWeek() - 1;
346 result.tm_yday = datetime.date().dayOfYear() - 1;
347 result.tm_isdst = -1; // This information is unavailable.
348
349 return result;
350}
351
352inline
353void DatetimeUtil::convertToTm(bsl::tm *result, const Datetime& datetime)
354{
355 BSLS_ASSERT(result);
356
357 *result = convertToTm(datetime);
358}
359
360inline
362 int month,
363 int day,
364 int hour,
365 int minute,
366 int second,
367 int millisecond,
368 int microsecond)
369{
370 return Datetime::isValid(year,
371 month,
372 day,
373 hour,
374 minute,
375 second,
376 millisecond,
377 microsecond)
379 year,
380 month,
381 day,
382 hour,
383 minute,
384 second,
385 millisecond,
386 microsecond)
387 : bsl::nullopt;
388}
389
390} // close package namespace
391
392
393#endif
394
395// ----------------------------------------------------------------------------
396// Copyright 2014 Bloomberg Finance L.P.
397//
398// Licensed under the Apache License, Version 2.0 (the "License");
399// you may not use this file except in compliance with the License.
400// You may obtain a copy of the License at
401//
402// http://www.apache.org/licenses/LICENSE-2.0
403//
404// Unless required by applicable law or agreed to in writing, software
405// distributed under the License is distributed on an "AS IS" BASIS,
406// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
407// See the License for the specific language governing permissions and
408// limitations under the License.
409// ----------------------------- END-OF-FILE ----------------------------------
410
411/** @} */
412/** @} */
413/** @} */
int dayOfYear() const
Return the day of the year in the range [1 .. 366] of this date.
Definition bdlt_date.h:968
DayOfWeek::Enum dayOfWeek() const
Definition bdlt_date.h:961
Definition bdlt_datetime.h:330
Date date() const
Return the value of the "date" part of this object.
Definition bdlt_datetime.h:2234
int year() const
Return the value of the year attribute of this object.
Definition bdlt_datetime.h:2359
int hour() const
Return the value of the hour attribute of this object.
Definition bdlt_datetime.h:2293
int minute() const
Return the value of the minute attribute of this object.
Definition bdlt_datetime.h:2319
int setDatetimeIfValid(int year, int month, int day, int hour=0, int minute=0, int second=0, int millisecond=0, int microsecond=0)
Definition bdlt_datetime.h:1502
static bool isValid(int year, int month, int day, int hour=0, int minute=0, int second=0, int millisecond=0, int microsecond=0)
Definition bdlt_datetime.h:1264
Datetime & addSeconds(bsls::Types::Int64 seconds)
Definition bdlt_datetime.h:2094
int second() const
Return the value of the second attribute of this object.
Definition bdlt_datetime.h:2335
int month() const
Return the value of the month attribute of this object.
Definition bdlt_datetime.h:2329
int day() const
Definition bdlt_datetime.h:2242
Definition bslstl_optional.h:2043
#define BSLS_ASSERT(X)
Definition bsls_assert.h:1976
#define BSLS_IDENT(str)
BSLS_IDENT() - insert string into .comment binary segment (if supported)
Definition bsls_ident.h:238
Definition bbldc_basicisma30360.h:112
const nullopt_t nullopt
const in_place_t in_place
Definition bdlt_datetimeutil.h:241
static int convertFromTm(Datetime *result, const bsl::tm &timeStruct)
Definition bdlt_datetimeutil.h:293
static bsl::optional< Datetime > fromYmdHms(int year, int month, int day, int hour, int minute, int second, int millisecond=0, int microsecond=0)
Definition bdlt_datetimeutil.h:361
static bsl::tm convertToTm(const Datetime &datetime)
Definition bdlt_datetimeutil.h:325