// file : butl/timestamp.cxx -*- C++ -*- // copyright : Copyright (c) 2014-2015 Code Synthesis Ltd // license : MIT; see accompanying LICENSE file #include <butl/timestamp> #include <time.h> // localtime, gmtime, strftime #include <ostream> #include <system_error> using namespace std; namespace butl { ostream& operator<< (ostream& os, const timestamp& ts) { // @@ replace with put_time() // time_t t (system_clock::to_time_t (ts)); if (t == 0) return os << "<nonexistent>"; std::tm tm; if (localtime_r (&t, &tm) == nullptr) throw system_error (errno, system_category ()); // If year is greater than 9999, we will overflow. // char buf[20]; // YYYY-MM-DD HH:MM:SS\0 if (strftime (buf, sizeof (buf), "%Y-%m-%d %H:%M:%S", &tm) == 0) return os << "<beyond year 9999>"; os << buf; using namespace chrono; timestamp sec (system_clock::from_time_t (t)); nanoseconds ns (duration_cast<nanoseconds> (ts - sec)); if (ns != nanoseconds::zero ()) { os << '.'; os.width (9); os.fill ('0'); os << ns.count (); } return os; } ostream& operator<< (ostream& os, const duration& d) { // @@ replace with put_time() // timestamp ts; // Epoch. ts += d; time_t t (system_clock::to_time_t (ts)); const char* fmt (nullptr); const char* unt ("nanoseconds"); if (t >= 365 * 12 * 24 * 60 * 60) { fmt = "%Y-%m-%d %H:%M:%S"; unt = "years"; } else if (t >= 12 * 24 * 60* 60) { fmt = "%m-%d %H:%M:%S"; unt = "months"; } else if (t >= 24 * 60* 60) { fmt = "%d %H:%M:%S"; unt = "days"; } else if (t >= 60 * 60) { fmt = "%H:%M:%S"; unt = "hours"; } else if (t >= 60) { fmt = "%M:%S"; unt = "minutes"; } else if (t >= 1) { fmt = "%S"; unt = "seconds"; } if (fmt != nullptr) { std::tm tm; if (gmtime_r (&t, &tm) == nullptr) throw system_error (errno, system_category ()); char buf[20]; // YYYY-MM-DD HH:MM:SS\0 if (strftime (buf, sizeof (buf), fmt, &tm) == 0) return os << "<beyond 9999>"; os << buf; } using namespace chrono; timestamp sec (system_clock::from_time_t (t)); nanoseconds ns (duration_cast<nanoseconds> (ts - sec)); if (ns != nanoseconds::zero ()) { if (fmt != nullptr) { os << '.'; os.width (9); os.fill ('0'); } os << ns.count () << ' ' << unt; } else if (fmt == 0) os << '0'; return os; } }