// bdlt_currenttime.h -*-C++-*- #ifndef INCLUDED_BDLT_CURRENTTIME #define INCLUDED_BDLT_CURRENTTIME #include <bsls_ident.h> BSLS_IDENT("$Id: $") //@PURPOSE: Provide utilities to retrieve the current time. // //@CLASSES: // bdlt::CurrentTime: namespace for current-time procedures // //@SEE_ALSO: bsls_timeinterval, bdlt_systemtimeutil // //@DESCRIPTION: This component, 'bdlt::CurrentTime', provides static methods // for retrieving the current time in Coordinated Universal Time (UTC) and in // the local time zone of the executing process. It also provides a facility // for customizing the means by which the time is retrieved. // ///Thread Safety ///------------- // The functions provided by 'bdlt::CurrentTime' are *thread-safe* (meaning // they may be called concurrently from multiple threads), including those that // set and retrieve the callback function. In addition, user-supplied callback // functions must be *thread-safe*. // ///Usage ///----- // This section illustrates intended use of this component. // ///Example 1: Repeatable Tests Involving Current Time /// - - - - - - - - - - - - - - - - - - - - - - - - - // Suppose we are writing an application which involves dealing with the // current time (for example, a clock displaying it). In order to test the // application, we would like to be able to control the time it sees. We can // use 'bdlt::CurrentTime' for this purpose. // // First, we create a sample application. For this example, we simply have it // retrieve the current time in several formats: //.. // void sampleApplication(bdlt::Datetime *local, // bdlt::Datetime *utc, // bsls::TimeInterval *now) // // Retrieve versions of the current time into the specified 'local', // // 'utc', and 'now' parameters. // { // *local = bdlt::CurrentTime::local(); // *utc = bdlt::CurrentTime::utc(); // *now = bdlt::CurrentTime::now(); // } //.. // Then, we create a method to test whether the application is producing the // expected results: //.. // bool checkApplication(bdlt::Datetime expectedLocal, // bdlt::Datetime expectedUtc, // bsls::TimeInterval expectedNow) // // Return 'true' iff 'sampleApplication' returns values matching the // // specified expected values 'expectedLocal', 'expectedUtc', and // // 'expectedNow'. // { // bdlt::Datetime local; // bdlt::Datetime utc; // bsls::TimeInterval now; // // sampleApplication(&local, &utc, &now); // return expectedLocal == local && // expectedUtc == utc && // expectedNow == now; // } //.. // Next, we create a class allowing us to set the current time which will be // seen by the application: //.. // class TestCurrentTimeGuard { // // Maintain and return a "current time" value. // private: // bdlt::CurrentTime::CurrentTimeCallback d_prev; // old callback // // public: // TestCurrentTimeGuard(); // // Create an object of this type, installing the handler. // // ~TestCurrentTimeGuard(); // // Destroy an object of this type, restoring the handler. // // static bsls::TimeInterval time(); // // Return 's_time'. // // static bsls::TimeInterval s_time; // the "current time" // }; // // bsls::TimeInterval TestCurrentTimeGuard::s_time; // // TestCurrentTimeGuard::TestCurrentTimeGuard() // : d_prev(bdlt::CurrentTime::setCurrentTimeCallback(time)) // { // } // // TestCurrentTimeGuard::~TestCurrentTimeGuard() // { // bdlt::CurrentTime::setCurrentTimeCallback(d_prev); // } // // bsls::TimeInterval TestCurrentTimeGuard::time() // { // return s_time; // } //.. // Finally, we write a method that tests that our application is functioning // correctly: //.. // void testApplication() // // Test the application. // { // TestCurrentTimeGuard tct; // TestCurrentTimeGuard::s_time = bdlt::EpochUtil::convertToTimeInterval( // bdlt::EpochUtil::epoch()); // // bdlt::Datetime local; // bdlt::Datetime utc; // bsls::TimeInterval now; // // sampleApplication(&local, &utc, &now); // // TestCurrentTimeGuard::s_time += 1E6; // local.addSeconds(1000000); // utc.addSeconds(1000000); // now += 1E6; // // assert(checkApplication(local, utc, now)); // } //.. #include <bdlscm_version.h> #include <bdlt_datetime.h> #include <bdlt_datetimetz.h> #include <bdlt_epochutil.h> #include <bdlt_localtimeoffset.h> #include <bsls_assert.h> #include <bsls_atomicoperations.h> #include <bsls_timeinterval.h> #include <bsls_types.h> #ifndef BDE_DONT_ALLOW_TRANSITIVE_INCLUDES #include <bdlt_intervalconversionutil.h> #endif // BDE_DONT_ALLOW_TRANSITIVE_INCLUDES namespace BloombergLP { namespace bdlt { // ================== // struct CurrentTime // ================== struct CurrentTime { // This 'struct' provides a namespace for current-time-retrieval procedures // including a configurable global callback mechanism. The use of a // *subset* of these procedures is thread-safe (see 'Thread Safety'). public: // TYPES typedef bsls::TimeInterval (*CurrentTimeCallback)(); // 'CurrentTimeCallback' is a callback function pointer for a callback // function that returns a 'bsls::TimeInterval' object. This function // must be thread-safe in multi-threaded builds. private: static bsls::AtomicOperations::AtomicTypes::Pointer s_currenttimeCallback_p; // address of current-time callback public: // CLASS METHODS // ** now functions ** static Datetime local(); // Return the 'Datetime' value representing the current date/time in // the local time zone, as provided by the installed callback function // and the facilities of 'LocalTimeOffset'. static bsls::TimeInterval now(); // Return the 'TimeInterval' value between 'EpochUtil::epoch()' and the // current date/time as provided by the installed callback function. // Note that this value is independent of time zone. static Datetime utc(); // Return the 'Datetime' value representing the current date/time in // Coordinated Universal Time (UTC) as provided by the installed // callback function. static DatetimeTz asDatetimeTz(); // Return the 'DatetimeTz' value representing the current date/time in // the local time zone, and the local time zone's offset from UTC, as // provided by the installed callback function and the facilities of // 'LocalTimeOffset'. // ** callback functions ** static CurrentTimeCallback currentTimeCallback(); // Return the installed function used to retrieve the interval between // 'EpochUtil::epoch()' and the current date/time, static CurrentTimeCallback setCurrentTimeCallback(CurrentTimeCallback callback); // Set the specified 'callback' as the function to be used to retrieve // the interval between 'EpochUtil::epoch()' and the current date/time, // and return the previously set function. // ** default callback function ** static bsls::TimeInterval currentTimeDefault(); // Return the 'TimeInterval' value between 'EpochUtil::epoch()' and the // current date/time. This is the default current-time callback // implementation for current time retrieval. The obtained time is // expressed as a time interval from '00:00 UTC, January 1, 1970'. On // UNIX (Solaris, LINUX and DG-UNIX) this function provides a // microsecond resolution. On Windows (NT, WIN2000, 95, 98 etc) it // provides a resolution of 100 nanoseconds. }; // ============================================================================ // INLINE DEFINITIONS // ============================================================================ // ----------------- // class CurrentTime // ----------------- // CLASS METHODS // ** now functions ** inline Datetime CurrentTime::local() { Datetime now = utc(); now.addSeconds(LocalTimeOffset::localTimeOffset(now).totalSeconds()); return now; } inline bsls::TimeInterval CurrentTime::now() { return currentTimeCallback()(); } inline Datetime CurrentTime::utc() { return EpochUtil::epoch() + now(); } // ** callback functions ** inline CurrentTime::CurrentTimeCallback CurrentTime::currentTimeCallback() { return reinterpret_cast<CurrentTimeCallback>( reinterpret_cast<bsls::Types::IntPtr>( bsls::AtomicOperations::getPtrAcquire(&s_currenttimeCallback_p))); } inline CurrentTime::CurrentTimeCallback CurrentTime::setCurrentTimeCallback(CurrentTimeCallback callback) { BSLS_ASSERT_OPT(callback); CurrentTimeCallback previousCallback = currentTimeCallback(); bsls::AtomicOperations::setPtrRelease( &s_currenttimeCallback_p, reinterpret_cast<void *>( reinterpret_cast<bsls::Types::IntPtr>(callback))); return previousCallback; } } // close package namespace } // close enterprise namespace #endif // ---------------------------------------------------------------------------- // Copyright 2016 Bloomberg Finance L.P. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // ----------------------------- END-OF-FILE ----------------------------------