util: avoid overflow in time::toIsoString

refs #3915

Change-Id: Ib1a1e7180a19984eb06fd5928430fa6a3b8c4e45
diff --git a/src/util/time.cpp b/src/util/time.cpp
index b652a7b..8452075 100644
--- a/src/util/time.cpp
+++ b/src/util/time.cpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /**
- * Copyright (c) 2013-2014 Regents of the University of California.
+ * Copyright (c) 2013-2017 Regents of the University of California.
  *
  * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
  *
@@ -130,16 +130,20 @@
 toIsoString(const system_clock::TimePoint& timePoint)
 {
   namespace bpt = boost::posix_time;
-  bpt::ptime ptime = bpt::from_time_t(system_clock::to_time_t(timePoint));
+  static bpt::ptime epoch(boost::gregorian::date(1970, 1, 1));
 
-  uint64_t micro = duration_cast<microseconds>(timePoint - getUnixEpoch()).count() % 1000000;
-  if (micro > 0)
-    {
-      ptime += bpt::microseconds(micro);
-      return bpt::to_iso_string(ptime);
-    }
-  else
-    return bpt::to_iso_string(ptime);
+#ifdef BOOST_DATE_TIME_POSIX_TIME_STD_CONFIG
+  using BptResolutionUnit = nanoseconds;
+#else
+  using BptResolutionUnit = microseconds;
+#endif
+  constexpr auto unitsPerHour = duration_cast<BptResolutionUnit>(hours(1)).count();
+
+  auto sinceEpoch = duration_cast<BptResolutionUnit>(timePoint - getUnixEpoch()).count();
+  bpt::ptime ptime = epoch + bpt::time_duration(sinceEpoch / unitsPerHour, 0, 0,
+                                                sinceEpoch % unitsPerHour);
+
+  return bpt::to_iso_string(ptime);
 }