111be35a1SLionel Sambuc // Copyright 2010 Google Inc.
211be35a1SLionel Sambuc // All rights reserved.
311be35a1SLionel Sambuc //
411be35a1SLionel Sambuc // Redistribution and use in source and binary forms, with or without
511be35a1SLionel Sambuc // modification, are permitted provided that the following conditions are
611be35a1SLionel Sambuc // met:
711be35a1SLionel Sambuc //
811be35a1SLionel Sambuc // * Redistributions of source code must retain the above copyright
911be35a1SLionel Sambuc // notice, this list of conditions and the following disclaimer.
1011be35a1SLionel Sambuc // * Redistributions in binary form must reproduce the above copyright
1111be35a1SLionel Sambuc // notice, this list of conditions and the following disclaimer in the
1211be35a1SLionel Sambuc // documentation and/or other materials provided with the distribution.
1311be35a1SLionel Sambuc // * Neither the name of Google Inc. nor the names of its contributors
1411be35a1SLionel Sambuc // may be used to endorse or promote products derived from this software
1511be35a1SLionel Sambuc // without specific prior written permission.
1611be35a1SLionel Sambuc //
1711be35a1SLionel Sambuc // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
1811be35a1SLionel Sambuc // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
1911be35a1SLionel Sambuc // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
2011be35a1SLionel Sambuc // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
2111be35a1SLionel Sambuc // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
2211be35a1SLionel Sambuc // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
2311be35a1SLionel Sambuc // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2411be35a1SLionel Sambuc // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2511be35a1SLionel Sambuc // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2611be35a1SLionel Sambuc // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
2711be35a1SLionel Sambuc // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2811be35a1SLionel Sambuc
2911be35a1SLionel Sambuc #include "utils/datetime.hpp"
3011be35a1SLionel Sambuc
3111be35a1SLionel Sambuc extern "C" {
3211be35a1SLionel Sambuc #include <sys/time.h>
3311be35a1SLionel Sambuc
3411be35a1SLionel Sambuc #include <time.h>
3511be35a1SLionel Sambuc }
3611be35a1SLionel Sambuc
3711be35a1SLionel Sambuc #include "utils/optional.ipp"
3811be35a1SLionel Sambuc #include "utils/sanity.hpp"
3911be35a1SLionel Sambuc
4011be35a1SLionel Sambuc namespace datetime = utils::datetime;
4111be35a1SLionel Sambuc
4211be35a1SLionel Sambuc using utils::none;
4311be35a1SLionel Sambuc using utils::optional;
4411be35a1SLionel Sambuc
4511be35a1SLionel Sambuc
4611be35a1SLionel Sambuc namespace {
4711be35a1SLionel Sambuc
4811be35a1SLionel Sambuc
4911be35a1SLionel Sambuc /// Fake value for the current time.
5011be35a1SLionel Sambuc static optional< datetime::timestamp > mock_now = none;
5111be35a1SLionel Sambuc
5211be35a1SLionel Sambuc
5311be35a1SLionel Sambuc } // anonymous namespace
5411be35a1SLionel Sambuc
5511be35a1SLionel Sambuc
5611be35a1SLionel Sambuc /// Creates a zero time delta.
delta(void)5711be35a1SLionel Sambuc datetime::delta::delta(void) :
5811be35a1SLionel Sambuc seconds(0),
5911be35a1SLionel Sambuc useconds(0)
6011be35a1SLionel Sambuc {
6111be35a1SLionel Sambuc }
6211be35a1SLionel Sambuc
6311be35a1SLionel Sambuc
6411be35a1SLionel Sambuc /// Creates a time delta.
6511be35a1SLionel Sambuc ///
6611be35a1SLionel Sambuc /// \param seconds_ The seconds in the delta.
6711be35a1SLionel Sambuc /// \param useconds_ The microseconds in the delta.
delta(const int64_t seconds_,const unsigned long useconds_)6811be35a1SLionel Sambuc datetime::delta::delta(const int64_t seconds_,
6911be35a1SLionel Sambuc const unsigned long useconds_) :
7011be35a1SLionel Sambuc seconds(seconds_),
7111be35a1SLionel Sambuc useconds(useconds_)
7211be35a1SLionel Sambuc {
7311be35a1SLionel Sambuc }
7411be35a1SLionel Sambuc
7511be35a1SLionel Sambuc
7611be35a1SLionel Sambuc /// Converts a time expressed in microseconds to a delta.
7711be35a1SLionel Sambuc ///
7811be35a1SLionel Sambuc /// \param useconds The amount of microseconds representing the delta.
7911be35a1SLionel Sambuc ///
8011be35a1SLionel Sambuc /// \return A new delta object.
8111be35a1SLionel Sambuc datetime::delta
from_microseconds(const int64_t useconds)8211be35a1SLionel Sambuc datetime::delta::from_microseconds(const int64_t useconds)
8311be35a1SLionel Sambuc {
8411be35a1SLionel Sambuc return delta(useconds / 1000000, useconds % 1000000);
8511be35a1SLionel Sambuc }
8611be35a1SLionel Sambuc
8711be35a1SLionel Sambuc
8811be35a1SLionel Sambuc /// Convers the delta to a flat representation expressed in microseconds.
8911be35a1SLionel Sambuc ///
9011be35a1SLionel Sambuc /// \return The amount of microseconds that corresponds to this delta.
9111be35a1SLionel Sambuc int64_t
to_microseconds(void) const9211be35a1SLionel Sambuc datetime::delta::to_microseconds(void) const
9311be35a1SLionel Sambuc {
9411be35a1SLionel Sambuc return seconds * 1000000 + useconds;
9511be35a1SLionel Sambuc }
9611be35a1SLionel Sambuc
9711be35a1SLionel Sambuc
9811be35a1SLionel Sambuc /// Checks if two time deltas are equal.
9911be35a1SLionel Sambuc ///
10011be35a1SLionel Sambuc /// \param other The object to compare to.
10111be35a1SLionel Sambuc ///
10211be35a1SLionel Sambuc /// \return True if the two time deltas are equals; false otherwise.
10311be35a1SLionel Sambuc bool
operator ==(const datetime::delta & other) const10411be35a1SLionel Sambuc datetime::delta::operator==(const datetime::delta& other) const
10511be35a1SLionel Sambuc {
10611be35a1SLionel Sambuc return seconds == other.seconds && useconds == other.useconds;
10711be35a1SLionel Sambuc }
10811be35a1SLionel Sambuc
10911be35a1SLionel Sambuc
11011be35a1SLionel Sambuc /// Checks if two time deltas are different.
11111be35a1SLionel Sambuc ///
11211be35a1SLionel Sambuc /// \param other The object to compare to.
11311be35a1SLionel Sambuc ///
11411be35a1SLionel Sambuc /// \return True if the two time deltas are different; false otherwise.
11511be35a1SLionel Sambuc bool
operator !=(const datetime::delta & other) const11611be35a1SLionel Sambuc datetime::delta::operator!=(const datetime::delta& other) const
11711be35a1SLionel Sambuc {
11811be35a1SLionel Sambuc return !(*this == other);
11911be35a1SLionel Sambuc }
12011be35a1SLionel Sambuc
12111be35a1SLionel Sambuc
12211be35a1SLionel Sambuc /// Adds a time delta to this one.
12311be35a1SLionel Sambuc ///
12411be35a1SLionel Sambuc /// \param other The time delta to add.
12511be35a1SLionel Sambuc ///
12611be35a1SLionel Sambuc /// \return The addition of this time delta with the other time delta.
12711be35a1SLionel Sambuc datetime::delta
operator +(const datetime::delta & other) const12811be35a1SLionel Sambuc datetime::delta::operator+(const datetime::delta& other) const
12911be35a1SLionel Sambuc {
13011be35a1SLionel Sambuc return delta::from_microseconds(to_microseconds() +
13111be35a1SLionel Sambuc other.to_microseconds());
13211be35a1SLionel Sambuc }
13311be35a1SLionel Sambuc
13411be35a1SLionel Sambuc
13511be35a1SLionel Sambuc /// Adds a time delta to this one and updates this with the result.
13611be35a1SLionel Sambuc ///
13711be35a1SLionel Sambuc /// \param other The time delta to add.
13811be35a1SLionel Sambuc ///
13911be35a1SLionel Sambuc /// \return The addition of this time delta with the other time delta.
14011be35a1SLionel Sambuc datetime::delta
operator +=(const datetime::delta & other)14111be35a1SLionel Sambuc datetime::delta::operator+=(const datetime::delta& other)
14211be35a1SLionel Sambuc {
14311be35a1SLionel Sambuc *this = *this + other;
14411be35a1SLionel Sambuc return *this;
14511be35a1SLionel Sambuc }
14611be35a1SLionel Sambuc
14711be35a1SLionel Sambuc
14811be35a1SLionel Sambuc /// Injects the object into a stream.
14911be35a1SLionel Sambuc ///
15011be35a1SLionel Sambuc /// \param output The stream into which to inject the object.
15111be35a1SLionel Sambuc /// \param object The object to format.
15211be35a1SLionel Sambuc ///
15311be35a1SLionel Sambuc /// \return The output stream.
15411be35a1SLionel Sambuc std::ostream&
operator <<(std::ostream & output,const delta & object)15511be35a1SLionel Sambuc datetime::operator<<(std::ostream& output, const delta& object)
15611be35a1SLionel Sambuc {
15711be35a1SLionel Sambuc return (output << object.to_microseconds() << "us");
15811be35a1SLionel Sambuc }
15911be35a1SLionel Sambuc
16011be35a1SLionel Sambuc
16111be35a1SLionel Sambuc namespace utils {
16211be35a1SLionel Sambuc namespace datetime {
16311be35a1SLionel Sambuc
16411be35a1SLionel Sambuc
16511be35a1SLionel Sambuc /// Internal representation for datetime::timestamp.
16611be35a1SLionel Sambuc struct timestamp::impl {
16711be35a1SLionel Sambuc /// The raw timestamp as provided by libc.
16811be35a1SLionel Sambuc ::timeval data;
16911be35a1SLionel Sambuc
17011be35a1SLionel Sambuc /// Constructs an impl object from initialized data.
17111be35a1SLionel Sambuc ///
17211be35a1SLionel Sambuc /// \param data_ The raw timestamp to use.
implutils::datetime::timestamp::impl17311be35a1SLionel Sambuc impl(const ::timeval& data_) : data(data_)
17411be35a1SLionel Sambuc {
17511be35a1SLionel Sambuc }
17611be35a1SLionel Sambuc };
17711be35a1SLionel Sambuc
17811be35a1SLionel Sambuc
17911be35a1SLionel Sambuc } // namespace datetime
18011be35a1SLionel Sambuc } // namespace utils
18111be35a1SLionel Sambuc
18211be35a1SLionel Sambuc
18311be35a1SLionel Sambuc /// Constructs a new timestamp.
18411be35a1SLionel Sambuc ///
18511be35a1SLionel Sambuc /// \param pimpl_ An existing impl representation.
timestamp(std::shared_ptr<impl> pimpl_)18684d9c625SLionel Sambuc datetime::timestamp::timestamp(std::shared_ptr< impl > pimpl_) :
18711be35a1SLionel Sambuc _pimpl(pimpl_)
18811be35a1SLionel Sambuc {
18911be35a1SLionel Sambuc }
19011be35a1SLionel Sambuc
19111be35a1SLionel Sambuc
19211be35a1SLionel Sambuc /// Constructs a timestamp from the amount of microseconds since the epoch.
19311be35a1SLionel Sambuc ///
19411be35a1SLionel Sambuc /// \param value Microseconds since the epoch in UTC. Must be positive.
19511be35a1SLionel Sambuc ///
19611be35a1SLionel Sambuc /// \return A new timestamp.
19711be35a1SLionel Sambuc datetime::timestamp
from_microseconds(const int64_t value)19811be35a1SLionel Sambuc datetime::timestamp::from_microseconds(const int64_t value)
19911be35a1SLionel Sambuc {
20011be35a1SLionel Sambuc PRE(value >= 0);
20111be35a1SLionel Sambuc ::timeval data;
20211be35a1SLionel Sambuc data.tv_sec = static_cast< time_t >(value / 1000000);
20311be35a1SLionel Sambuc data.tv_usec = static_cast< suseconds_t >(value % 1000000);
20484d9c625SLionel Sambuc return timestamp(std::shared_ptr< impl >(new impl(data)));
20511be35a1SLionel Sambuc }
20611be35a1SLionel Sambuc
20711be35a1SLionel Sambuc
20811be35a1SLionel Sambuc /// Constructs a timestamp based on user-friendly values.
20911be35a1SLionel Sambuc ///
21011be35a1SLionel Sambuc /// \param year The year in the [1900,inf) range.
21111be35a1SLionel Sambuc /// \param month The month in the [1,12] range.
21211be35a1SLionel Sambuc /// \param day The day in the [1,30] range.
21311be35a1SLionel Sambuc /// \param hour The hour in the [0,23] range.
21411be35a1SLionel Sambuc /// \param minute The minute in the [0,59] range.
21511be35a1SLionel Sambuc /// \param second The second in the [0,60] range. Yes, that is 60, which can be
21611be35a1SLionel Sambuc /// the case on leap seconds.
21711be35a1SLionel Sambuc /// \param microsecond The microsecond in the [0,999999] range.
21811be35a1SLionel Sambuc ///
21911be35a1SLionel Sambuc /// \return A new timestamp.
22011be35a1SLionel Sambuc datetime::timestamp
from_values(const int year,const int month,const int day,const int hour,const int minute,const int second,const int microsecond)22111be35a1SLionel Sambuc datetime::timestamp::from_values(const int year, const int month,
22211be35a1SLionel Sambuc const int day, const int hour,
22311be35a1SLionel Sambuc const int minute, const int second,
22411be35a1SLionel Sambuc const int microsecond)
22511be35a1SLionel Sambuc {
22611be35a1SLionel Sambuc PRE(year >= 1900);
22711be35a1SLionel Sambuc PRE(month >= 1 && month <= 12);
22811be35a1SLionel Sambuc PRE(day >= 1 && day <= 30);
22911be35a1SLionel Sambuc PRE(hour >= 0 && hour <= 23);
23011be35a1SLionel Sambuc PRE(minute >= 0 && minute <= 59);
23111be35a1SLionel Sambuc PRE(second >= 0 && second <= 60);
23211be35a1SLionel Sambuc PRE(microsecond >= 0 && microsecond <= 999999);
23311be35a1SLionel Sambuc
23411be35a1SLionel Sambuc // The code below is quite convoluted. The problem is that we can't assume
23511be35a1SLionel Sambuc // that some fields (like tm_zone) of ::tm exist, and thus we can't blindly
23611be35a1SLionel Sambuc // set them from the code. Instead of detecting their presence in the
23711be35a1SLionel Sambuc // configure script, we just query the current time to initialize such
23811be35a1SLionel Sambuc // fields and then we override the ones we are interested in. (There might
23911be35a1SLionel Sambuc // be some better way to do this, but I don't know it and the documentation
24011be35a1SLionel Sambuc // does not shed much light into how to create your own fake date.)
24111be35a1SLionel Sambuc
24211be35a1SLionel Sambuc const time_t current_time = ::time(NULL);
24311be35a1SLionel Sambuc
24411be35a1SLionel Sambuc ::tm timedata;
24511be35a1SLionel Sambuc if (::gmtime_r(¤t_time, &timedata) == NULL)
24611be35a1SLionel Sambuc UNREACHABLE;
24711be35a1SLionel Sambuc
24811be35a1SLionel Sambuc timedata.tm_sec = second;
24911be35a1SLionel Sambuc timedata.tm_min = minute;
25011be35a1SLionel Sambuc timedata.tm_hour = hour;
25111be35a1SLionel Sambuc timedata.tm_mday = day;
25211be35a1SLionel Sambuc timedata.tm_mon = month - 1;
25311be35a1SLionel Sambuc timedata.tm_year = year - 1900;
25411be35a1SLionel Sambuc // Ignored: timedata.tm_wday
25511be35a1SLionel Sambuc // Ignored: timedata.tm_yday
25611be35a1SLionel Sambuc
25711be35a1SLionel Sambuc ::timeval data;
25811be35a1SLionel Sambuc data.tv_sec = ::mktime(&timedata);
25911be35a1SLionel Sambuc data.tv_usec = static_cast< suseconds_t >(microsecond);
26084d9c625SLionel Sambuc return timestamp(std::shared_ptr< impl >(new impl(data)));
26111be35a1SLionel Sambuc }
26211be35a1SLionel Sambuc
26311be35a1SLionel Sambuc
26411be35a1SLionel Sambuc /// Constructs a new timestamp representing the current time in UTC.
26511be35a1SLionel Sambuc ///
26611be35a1SLionel Sambuc /// \return A new timestamp.
26711be35a1SLionel Sambuc datetime::timestamp
now(void)26811be35a1SLionel Sambuc datetime::timestamp::now(void)
26911be35a1SLionel Sambuc {
27011be35a1SLionel Sambuc if (mock_now)
27111be35a1SLionel Sambuc return mock_now.get();
27211be35a1SLionel Sambuc
27311be35a1SLionel Sambuc ::timeval data;
27411be35a1SLionel Sambuc {
275*3260d16fSLionel Sambuc #if defined(__minix) && !defined(NDEBUG)
276*3260d16fSLionel Sambuc const int ret =
277*3260d16fSLionel Sambuc #endif /* defined(__minix) && !defined(NDEBUG) */
278*3260d16fSLionel Sambuc ::gettimeofday(&data, NULL);
27911be35a1SLionel Sambuc INV(ret != -1);
28011be35a1SLionel Sambuc }
28111be35a1SLionel Sambuc
28284d9c625SLionel Sambuc return timestamp(std::shared_ptr< impl >(new impl(data)));
28311be35a1SLionel Sambuc }
28411be35a1SLionel Sambuc
28511be35a1SLionel Sambuc
28611be35a1SLionel Sambuc /// Formats a timestamp.
28711be35a1SLionel Sambuc ///
28811be35a1SLionel Sambuc /// \param format The format string to use as consumed by strftime(3).
28911be35a1SLionel Sambuc ///
29011be35a1SLionel Sambuc /// \return The formatted time.
29111be35a1SLionel Sambuc std::string
strftime(const std::string & format) const29211be35a1SLionel Sambuc datetime::timestamp::strftime(const std::string& format) const
29311be35a1SLionel Sambuc {
29411be35a1SLionel Sambuc ::tm timedata;
29511be35a1SLionel Sambuc // This conversion to time_t is necessary because tv_sec is not guaranteed
29611be35a1SLionel Sambuc // to be a time_t. For example, it isn't in NetBSD 5.x
29711be35a1SLionel Sambuc ::time_t epoch_seconds;
29811be35a1SLionel Sambuc epoch_seconds = _pimpl->data.tv_sec;
29911be35a1SLionel Sambuc if (::gmtime_r(&epoch_seconds, &timedata) == NULL)
30011be35a1SLionel Sambuc UNREACHABLE_MSG("gmtime_r(3) did not accept the value returned by "
30111be35a1SLionel Sambuc "gettimeofday(2)");
30211be35a1SLionel Sambuc
30311be35a1SLionel Sambuc char buf[128];
30411be35a1SLionel Sambuc if (::strftime(buf, sizeof(buf), format.c_str(), &timedata) == 0)
30511be35a1SLionel Sambuc UNREACHABLE_MSG("Arbitrary-long format strings are unimplemented");
30611be35a1SLionel Sambuc return buf;
30711be35a1SLionel Sambuc }
30811be35a1SLionel Sambuc
30911be35a1SLionel Sambuc
31011be35a1SLionel Sambuc /// Returns the number of microseconds since the epoch in UTC.
31111be35a1SLionel Sambuc ///
31211be35a1SLionel Sambuc /// \return A number of microseconds.
31311be35a1SLionel Sambuc int64_t
to_microseconds(void) const31411be35a1SLionel Sambuc datetime::timestamp::to_microseconds(void) const
31511be35a1SLionel Sambuc {
31611be35a1SLionel Sambuc return static_cast< int64_t >(_pimpl->data.tv_sec) * 1000000 +
31711be35a1SLionel Sambuc _pimpl->data.tv_usec;
31811be35a1SLionel Sambuc }
31911be35a1SLionel Sambuc
32011be35a1SLionel Sambuc
32111be35a1SLionel Sambuc /// Returns the number of seconds since the epoch in UTC.
32211be35a1SLionel Sambuc ///
32311be35a1SLionel Sambuc /// \return A number of seconds.
32411be35a1SLionel Sambuc int64_t
to_seconds(void) const32511be35a1SLionel Sambuc datetime::timestamp::to_seconds(void) const
32611be35a1SLionel Sambuc {
32711be35a1SLionel Sambuc return static_cast< int64_t >(_pimpl->data.tv_sec);
32811be35a1SLionel Sambuc }
32911be35a1SLionel Sambuc
33011be35a1SLionel Sambuc
33111be35a1SLionel Sambuc /// Sets the current time for testing purposes.
33211be35a1SLionel Sambuc void
set_mock_now(const int year,const int month,const int day,const int hour,const int minute,const int second,const int microsecond)33311be35a1SLionel Sambuc datetime::set_mock_now(const int year, const int month,
33411be35a1SLionel Sambuc const int day, const int hour,
33511be35a1SLionel Sambuc const int minute, const int second,
33611be35a1SLionel Sambuc const int microsecond)
33711be35a1SLionel Sambuc {
33811be35a1SLionel Sambuc mock_now = timestamp::from_values(year, month, day, hour, minute, second,
33911be35a1SLionel Sambuc microsecond);
34011be35a1SLionel Sambuc }
34111be35a1SLionel Sambuc
34211be35a1SLionel Sambuc
34311be35a1SLionel Sambuc /// Checks if two timestamps are equal.
34411be35a1SLionel Sambuc ///
34511be35a1SLionel Sambuc /// \param other The object to compare to.
34611be35a1SLionel Sambuc ///
34711be35a1SLionel Sambuc /// \return True if the two timestamps are equals; false otherwise.
34811be35a1SLionel Sambuc bool
operator ==(const datetime::timestamp & other) const34911be35a1SLionel Sambuc datetime::timestamp::operator==(const datetime::timestamp& other) const
35011be35a1SLionel Sambuc {
35111be35a1SLionel Sambuc return _pimpl->data.tv_sec == other._pimpl->data.tv_sec &&
35211be35a1SLionel Sambuc _pimpl->data.tv_usec == other._pimpl->data.tv_usec;
35311be35a1SLionel Sambuc }
35411be35a1SLionel Sambuc
35511be35a1SLionel Sambuc
35611be35a1SLionel Sambuc /// Checks if two timestamps are different.
35711be35a1SLionel Sambuc ///
35811be35a1SLionel Sambuc /// \param other The object to compare to.
35911be35a1SLionel Sambuc ///
36011be35a1SLionel Sambuc /// \return True if the two timestamps are different; false otherwise.
36111be35a1SLionel Sambuc bool
operator !=(const datetime::timestamp & other) const36211be35a1SLionel Sambuc datetime::timestamp::operator!=(const datetime::timestamp& other) const
36311be35a1SLionel Sambuc {
36411be35a1SLionel Sambuc return !(*this == other);
36511be35a1SLionel Sambuc }
36611be35a1SLionel Sambuc
36711be35a1SLionel Sambuc
36811be35a1SLionel Sambuc /// Calculates the delta between two timestamps.
36911be35a1SLionel Sambuc ///
37011be35a1SLionel Sambuc /// \param other The subtrahend.
37111be35a1SLionel Sambuc ///
37211be35a1SLionel Sambuc /// \return The difference between this object and the other object.
37311be35a1SLionel Sambuc datetime::delta
operator -(const datetime::timestamp & other) const37411be35a1SLionel Sambuc datetime::timestamp::operator-(const datetime::timestamp& other) const
37511be35a1SLionel Sambuc {
37611be35a1SLionel Sambuc return datetime::delta::from_microseconds(to_microseconds() -
37711be35a1SLionel Sambuc other.to_microseconds());
37811be35a1SLionel Sambuc }
37911be35a1SLionel Sambuc
38011be35a1SLionel Sambuc
38111be35a1SLionel Sambuc /// Injects the object into a stream.
38211be35a1SLionel Sambuc ///
38311be35a1SLionel Sambuc /// \param output The stream into which to inject the object.
38411be35a1SLionel Sambuc /// \param object The object to format.
38511be35a1SLionel Sambuc ///
38611be35a1SLionel Sambuc /// \return The output stream.
38711be35a1SLionel Sambuc std::ostream&
operator <<(std::ostream & output,const timestamp & object)38811be35a1SLionel Sambuc datetime::operator<<(std::ostream& output, const timestamp& object)
38911be35a1SLionel Sambuc {
39011be35a1SLionel Sambuc return (output << object.to_microseconds() << "us");
39111be35a1SLionel Sambuc }
392