aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2016-01-05 23:18:05 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2016-01-07 20:45:51 +0200
commit304b4e97bef93bcbeb82b5339451bacbb72b4f31 (patch)
tree9281eee5194b2c9a7d0c744c9ae29fdac28c6e45
parent24e05cd878553ad2379d513951f06ec984b08594 (diff)
Fix nanoseconds formatting in to_stream(), operator<<()
-rw-r--r--butl/timestamp4
-rw-r--r--butl/timestamp.cxx50
2 files changed, 43 insertions, 11 deletions
diff --git a/butl/timestamp b/butl/timestamp
index e68a59f..aaef04d 100644
--- a/butl/timestamp
+++ b/butl/timestamp
@@ -61,6 +61,10 @@ namespace butl
//
// Note also that these operators/function may throw std::system_error.
//
+ // Finally, padding is not fully supported by these operators/function. They
+ // throw runtime_error if nanoseconds conversion specifier is present and
+ // the stream's width field has been set to non-zero value before the call.
+ //
// Potential improvements:
// - add flag to to_stream() to use
// - support %[<d>U] (microseconds) and %[<d>M] (milliseconds).
diff --git a/butl/timestamp.cxx b/butl/timestamp.cxx
index 8c53f60..6b99284 100644
--- a/butl/timestamp.cxx
+++ b/butl/timestamp.cxx
@@ -8,9 +8,10 @@
#include <errno.h> // EINVAL
#include <ctime> // tm, strftime()
-#include <iomanip> // put_time()
+#include <iomanip> // put_time(), setw(), dec, right
#include <cstring> // strlen(), memcpy()
#include <ostream>
+#include <stdexcept> // runtime_error
#include <system_error>
using namespace std;
@@ -101,6 +102,10 @@ namespace butl
{
if (fmt[j + 1] == '[')
{
+ if (os.width () != 0)
+ throw runtime_error (
+ "padding is not supported when printing nanoseconds");
+
// Our fragment. First see if we need to call put_time().
//
if (i != j)
@@ -129,9 +134,12 @@ namespace butl
{
if (d != '\0')
os << d;
- os.width (9);
- os.fill ('0');
- os << ns.count ();
+
+ ostream::fmtflags fl (os.flags ());
+ char fc (os.fill ('0'));
+ os << dec << right << setw (9) << ns.count ();
+ os.fill (fc);
+ os.flags (fl);
}
i = j + 1; // j is incremented in the for-loop header.
@@ -155,6 +163,10 @@ namespace butl
ostream&
operator<< (ostream& os, const duration& d)
{
+ if (os.width () != 0) // We always print nanosecond.
+ throw runtime_error (
+ "padding is not supported when printing nanoseconds");
+
timestamp ts; // Epoch.
ts += d;
@@ -162,17 +174,17 @@ namespace butl
const char* fmt (nullptr);
const char* unt ("nanoseconds");
- if (t >= 365 * 12 * 24 * 60 * 60)
+ if (t >= 365 * 24 * 60 * 60)
{
fmt = "%Y-%m-%d %H:%M:%S";
unt = "years";
}
- else if (t >= 12 * 24 * 60* 60)
+ else if (t >= 31 * 24 * 60 * 60)
{
fmt = "%m-%d %H:%M:%S";
unt = "months";
}
- else if (t >= 24 * 60* 60)
+ else if (t >= 24 * 60 * 60)
{
fmt = "%d %H:%M:%S";
unt = "days";
@@ -199,6 +211,18 @@ namespace butl
if (gmtime_r (&t, &tm) == nullptr)
throw system_error (errno, system_category ());
+ if (t >= 24 * 60 * 60)
+ tm.tm_mday -= 1; // Make day of the month to be a zero-based number.
+
+ if (t >= 31 * 24 * 60 * 60)
+ tm.tm_mon -= 1; // Make month of the year to be a zero-based number.
+
+ if (t >= 365 * 24 * 60 * 60)
+ // Make the year to be a 1970-based number. Negative values allowed
+ // according to the POSIX specification.
+ //
+ tm.tm_year -= 1970;
+
if (!(os << put_time (&tm, fmt)))
return os;
}
@@ -212,12 +236,16 @@ namespace butl
{
if (fmt != nullptr)
{
- os << '.';
- os.width (9);
- os.fill ('0');
+ ostream::fmtflags fl (os.flags ());
+ char fc (os.fill ('0'));
+ os << '.' << dec << right << setw (9) << ns.count ();
+ os.fill (fc);
+ os.flags (fl);
}
+ else
+ os << ns.count ();
- os << ns.count () << ' ' << unt;
+ os << ' ' << unt;
}
else if (fmt == nullptr)
os << '0';