all: Refactoring work with time using boost::chrono

Now the library has two clocks: time::steady_clock and
time::system_clock, following (boost|std)::chrono.  In addition to
standard now() method, the library contains several helpers to convert
to/from UnixTimestamp (microsecond resolution) and IsoString (optional
microsecond resolution).  The IsoString conversions use
boost::posix_time routines, since boost::chrono supports extended IO
support only starting boost version 1.52 (Boost Chrono V2).

This commit breaks compatibility with previous API.  All time-related
Data/Interest calls must explicitly use time units to specify
FreshnessPeriod/InterestLifetime.

Brief usage/conversion guide:

- creation of time units does not support double/float types.  If
  necessary to create time unit from double, ``ndn::duration<double>`` (for
  seconds) needs to be used instead.  In some cases, this would also
  require ``ndn::duration_cast``, if the target is not ``ndn::nanoseconds``.
- ndn::getNow, ndn::ndn_getNowMilliseconds, ndn::time::now are all
  removed in favor of the now() method in a specific clock:

    * time::system_clock::now();
    * time::steady_clock::now();

- When necessary to convert system_clock::TimePoint to unix timestamp,
  ``time::toUnixTimestamp`` can be used.  This method return number of
  milliseconds since UNIX epoch as ``ndn::time::milliseconds`` type.
  Use count() method to obtain number as an integral value.

Change-Id: Icd688bc6766e008d60c3d2888173627874526e47
Refs: #1152
diff --git a/src/util/command-interest-generator.hpp b/src/util/command-interest-generator.hpp
index 8b4d796..18bc960 100644
--- a/src/util/command-interest-generator.hpp
+++ b/src/util/command-interest-generator.hpp
@@ -25,7 +25,7 @@
   static const Name DEFAULT_CERTIFICATE_NAME;
 
   CommandInterestGenerator()
-    : m_lastTimestamp(time::now() / 1000000)
+    : m_lastTimestamp(time::toUnixTimestamp(time::system_clock::now()))
   {
   }
 
@@ -36,30 +36,29 @@
 
   void
   generate(Interest& interest, const Name& certificateName = Name());
-  
+
   void
   generateWithIdentity(Interest& interest, const Name& identity);
-  
+
 private:
-  int64_t m_lastTimestamp;
+  time::milliseconds m_lastTimestamp;
   KeyChain m_keyChain;
 };
 
 
 inline void
-CommandInterestGenerator::generate(Interest& interest, 
+CommandInterestGenerator::generate(Interest& interest,
 				   const Name& certificateName /*= Name()*/)
 {
-  int64_t timestamp = time::now() / 1000000;
-  while(timestamp == m_lastTimestamp)
+  time::milliseconds timestamp = time::toUnixTimestamp(time::system_clock::now());
+  while(timestamp <= m_lastTimestamp)
     {
-      usleep(1000); //Guarantee unqiueness of timestamp
-      timestamp = time::now();
+      timestamp += time::milliseconds(1);
     }
 
   Name commandInterestName = interest.getName();
   commandInterestName
-    .append(name::Component::fromNumber(timestamp))
+    .append(name::Component::fromNumber(timestamp.count()))
     .append(name::Component::fromNumber(random::generateWord64()));
   interest.setName(commandInterestName);
 
@@ -70,17 +69,19 @@
 
   m_lastTimestamp = timestamp;
 }
-  
+
 inline void
 CommandInterestGenerator::generateWithIdentity(Interest& interest, const Name& identity)
 {
-  int64_t timestamp = time::now() / 1000000;
-  if(timestamp <= m_lastTimestamp)
-    timestamp = m_lastTimestamp + 1;
+  time::milliseconds timestamp = time::toUnixTimestamp(time::system_clock::now());
+  while(timestamp <= m_lastTimestamp)
+    {
+      timestamp += time::milliseconds(1);
+    }
 
   Name commandInterestName = interest.getName();
   commandInterestName
-    .append(name::Component::fromNumber(timestamp))
+    .append(name::Component::fromNumber(timestamp.count()))
     .append(name::Component::fromNumber(random::generateWord64()));
   interest.setName(commandInterestName);
 
diff --git a/src/util/command-interest-validator.hpp b/src/util/command-interest-validator.hpp
index af8c796..257f476 100644
--- a/src/util/command-interest-validator.hpp
+++ b/src/util/command-interest-validator.hpp
@@ -24,10 +24,11 @@
 
     GRACE_INTERVAL = 3000 // ms
   };
-  
-  CommandInterestValidator(int64_t graceInterval = GRACE_INTERVAL/*ms*/) 
+
+  CommandInterestValidator(const time::milliseconds& graceInterval = time::milliseconds(static_cast<int>(GRACE_INTERVAL)))
+    : m_graceInterval(graceInterval < time::milliseconds::zero() ?
+                      time::milliseconds(static_cast<int>(GRACE_INTERVAL)) : graceInterval)
   {
-    m_graceInterval = (graceInterval < 0 ? GRACE_INTERVAL : graceInterval);
   }
 
   virtual
@@ -43,26 +44,28 @@
 
 protected:
   virtual void
-  checkPolicy (const Data& data, 
-               int stepCount, 
-               const OnDataValidated &onValidated, 
+  checkPolicy (const Data& data,
+               int stepCount,
+               const OnDataValidated &onValidated,
                const OnDataValidationFailed &onValidationFailed,
                std::vector<shared_ptr<ValidationRequest> > &nextSteps)
   {
     onValidationFailed(data.shared_from_this(), "No policy for data checking");
   }
-  
+
   virtual void
-  checkPolicy (const Interest& interest, 
-               int stepCount, 
-               const OnInterestValidated &onValidated, 
+  checkPolicy (const Interest& interest,
+               int stepCount,
+               const OnInterestValidated &onValidated,
                const OnInterestValidationFailed &onValidationFailed,
                std::vector<shared_ptr<ValidationRequest> > &nextSteps);
 private:
-  int64_t m_graceInterval; //ms
+  time::milliseconds m_graceInterval; //ms
   std::map<Name, PublicKey> m_trustAnchorsForInterest;
   std::list<SecRuleSpecific> m_trustScopeForInterest;
-  std::map<Name, uint64_t> m_lastTimestamp;
+
+  typedef std::map<Name, time::system_clock::TimePoint> LastTimestampMap;
+  LastTimestampMap m_lastTimestamp;
 };
 
 inline void
@@ -82,28 +85,28 @@
 }
 
 inline void
-CommandInterestValidator::checkPolicy (const Interest& interest, 
-                                       int stepCount, 
-                                       const OnInterestValidated &onValidated, 
+CommandInterestValidator::checkPolicy (const Interest& interest,
+                                       int stepCount,
+                                       const OnInterestValidated &onValidated,
                                        const OnInterestValidationFailed &onValidationFailed,
                                        std::vector<shared_ptr<ValidationRequest> > &nextSteps)
 {
   const Name& interestName = interest.getName();
-  
-  //Prepare 
+
+  //Prepare
   if (interestName.size() < 4)
-    return onValidationFailed(interest.shared_from_this(), 
+    return onValidationFailed(interest.shared_from_this(),
                               "Interest is not signed: " + interest.getName().toUri());
-  
-  Signature signature(interestName[POS_SIG_INFO].blockFromValue(), 
+
+  Signature signature(interestName[POS_SIG_INFO].blockFromValue(),
                       interestName[POS_SIG_VALUE].blockFromValue());
-  
+
   SignatureSha256WithRsa sig(signature);
   const Name& keyLocatorName = sig.getKeyLocator().getName();
   Name keyName = IdentityCertificate::certificateNameToPublicKeyName(keyLocatorName);
-  
+
   //Check if command is in the trusted scope
-  bool inScope = false;  
+  bool inScope = false;
   for(std::list<SecRuleSpecific>::iterator scopeIt = m_trustScopeForInterest.begin();
       scopeIt != m_trustScopeForInterest.end();
       ++scopeIt)
@@ -115,23 +118,28 @@
         }
     }
   if(inScope == false)
-    return onValidationFailed(interest.shared_from_this(), 
+    return onValidationFailed(interest.shared_from_this(),
                               "Signer cannot be authorized for the command: " + keyName.toUri());
 
   //Check if timestamp is valid
-  uint64_t timestamp = interestName.get(POS_TIMESTAMP).toNumber();
-  uint64_t current = static_cast<uint64_t>(time::now()/1000000);
-  std::map<Name, uint64_t>::const_iterator timestampIt = m_lastTimestamp.find(keyName);
-  if(timestampIt == m_lastTimestamp.end())
+  time::system_clock::TimePoint interestTime = time::fromUnixTimestamp(
+                                           time::milliseconds(interestName.get(POS_TIMESTAMP).toNumber()));
+  time::system_clock::TimePoint currentTime = time::system_clock::now();
+
+  LastTimestampMap::iterator timestampIt = m_lastTimestamp.find(keyName);
+  if (timestampIt == m_lastTimestamp.end())
     {
-      if(timestamp > (current + m_graceInterval) || (timestamp + m_graceInterval) < current)
-        return onValidationFailed(interest.shared_from_this(), 
-                                  "The command is not in grace interval: " + interest.getName().toUri());
+      if (!(currentTime - m_graceInterval <= interestTime &&
+            interestTime <= currentTime + m_graceInterval))
+        {
+          return onValidationFailed(interest.shared_from_this(),
+                                    "The command is not in grace interval: " + interest.getName().toUri());
+        }
     }
-  else 
+  else
     {
-      if(m_lastTimestamp[keyName] >= timestamp)
-        return onValidationFailed(interest.shared_from_this(), 
+      if(interestTime <= timestampIt->second)
+        return onValidationFailed(interest.shared_from_this(),
                                   "The command is outdated: " + interest.getName().toUri());
     }
 
@@ -139,16 +147,22 @@
   if(!Validator::verifySignature(interestName.wireEncode().value(),
                                  interestName.wireEncode().value_size() - interestName[-1].size(),
                                  sig, m_trustAnchorsForInterest[keyName]))
-    return onValidationFailed(interest.shared_from_this(), 
+    return onValidationFailed(interest.shared_from_this(),
                               "Signature cannot be validated: " + interest.getName().toUri());
 
   //Update timestamp
-  m_lastTimestamp[keyName] = timestamp;
+  if (timestampIt == m_lastTimestamp.end())
+    {
+      m_lastTimestamp[keyName] = interestTime;
+    }
+  else
+    {
+      timestampIt->second = interestTime;
+    }
 
   return onValidated(interest.shared_from_this());
 }
 
-
 } // namespace ndn
 
 #endif // NDN_HELPERS_COMMAND_INTEREST_VALIDATOR_HPP
diff --git a/src/util/monotonic_deadline_timer.hpp b/src/util/monotonic_deadline_timer.hpp
index 3cfb05f..2b1558d 100644
--- a/src/util/monotonic_deadline_timer.hpp
+++ b/src/util/monotonic_deadline_timer.hpp
@@ -17,20 +17,20 @@
 namespace boost {
 namespace asio {
 
-template <> 
-struct time_traits<ndn::time::monotonic_clock>
+template <>
+struct time_traits<ndn::time::steady_clock::TimePoint::clock>
 {
-  typedef ndn::time::Point time_type;
-  typedef ndn::time::Duration duration_type;
+  typedef ndn::time::steady_clock::TimePoint time_type;
+  typedef ndn::time::steady_clock::TimePoint::clock::duration duration_type;
 
   static time_type
   now()
   {
-    return ndn::time::now();
+    return ndn::time::steady_clock::now();
   }
 
   static time_type
-  add(const time_type& time, const duration_type& duration) 
+  add(const time_type& time, const duration_type& duration)
   {
     return time + duration;
   }
@@ -50,13 +50,25 @@
   static boost::posix_time::time_duration
   to_posix_duration(const duration_type& duration)
   {
-    return boost::posix_time::microseconds(duration/1000);
+    return
+#ifdef BOOST_DATE_TIME_HAS_NANOSECONDS
+      boost::posix_time::nanoseconds(
+        ndn::time::duration_cast<ndn::time::nanoseconds>(duration).count())
+#else
+      boost::posix_time::microseconds(
+        ndn::time::duration_cast<ndn::time::microseconds>(duration).count())
+#endif
+      ;
   }
 };
 
-typedef basic_deadline_timer<ndn::time::monotonic_clock> monotonic_deadline_timer; 
-
 } // namespace asio
 } // namespace boost
 
+namespace ndn {
+
+typedef boost::asio::basic_deadline_timer<time::steady_clock::TimePoint::clock> monotonic_deadline_timer;
+
+} // namespace ndn
+
 #endif // NDN_UTIL_MONOTONIC_DEADLINE_TIMER_HPP
diff --git a/src/util/scheduler.cpp b/src/util/scheduler.cpp
index 388d5e7..377800f 100644
--- a/src/util/scheduler.cpp
+++ b/src/util/scheduler.cpp
@@ -47,16 +47,16 @@
   bool m_isValid;
 };
 
-Scheduler::EventInfo::EventInfo(const time::Duration& after,
-                        const time::Duration& period,
-                        const Event& event)
-  : m_scheduledTime(time::now() + after)
+Scheduler::EventInfo::EventInfo(const time::nanoseconds& after,
+                                const time::nanoseconds& period,
+                                const Event& event)
+  : m_scheduledTime(time::steady_clock::now() + after)
   , m_period(period)
   , m_event(event)
 {
 }
 
-Scheduler::EventInfo::EventInfo(const time::Point& when, const EventInfo& previousEvent)
+Scheduler::EventInfo::EventInfo(const time::steady_clock::TimePoint& when, const EventInfo& previousEvent)
   : m_scheduledTime(when)
   , m_period(previousEvent.m_period)
   , m_event(previousEvent.m_event)
@@ -64,10 +64,10 @@
 {
 }
 
-time::Duration
+time::nanoseconds
 Scheduler::EventInfo::expiresFromNow() const
 {
-  time::Point now = time::now();
+  time::steady_clock::TimePoint now = time::steady_clock::now();
   if (now > m_scheduledTime)
     return time::seconds(0); // event should be scheduled ASAP
   else
@@ -84,15 +84,15 @@
 }
 
 EventId
-Scheduler::scheduleEvent(const time::Duration& after,
+Scheduler::scheduleEvent(const time::nanoseconds& after,
                          const Event& event)
 {
   return schedulePeriodicEvent(after, time::nanoseconds(-1), event);
 }
 
 EventId
-Scheduler::schedulePeriodicEvent(const time::Duration& after,
-                                 const time::Duration& period,
+Scheduler::schedulePeriodicEvent(const time::nanoseconds& after,
+                                 const time::nanoseconds& period,
                                  const Event& event)
 {
   EventQueue::iterator i = m_events.insert(EventInfo(after, period, event));
@@ -154,13 +154,13 @@
   m_isEventExecuting = true;
 
   // process all expired events
-  time::Point now = time::now();
+  time::steady_clock::TimePoint now = time::steady_clock::now();
   while(!m_events.empty() && m_events.begin()->m_scheduledTime <= now)
     {
       EventQueue::iterator head = m_events.begin();
       
       Event event = head->m_event;
-      if (head->m_period < 0)
+      if (head->m_period < time::nanoseconds::zero())
         {
           head->m_eventId->invalidate();
           m_events.erase(head);
diff --git a/src/util/scheduler.hpp b/src/util/scheduler.hpp
index 18c3004..b7364ce 100644
--- a/src/util/scheduler.hpp
+++ b/src/util/scheduler.hpp
@@ -33,7 +33,7 @@
    * \returns EventId that can be used to cancel the scheduled event
    */
   EventId
-  scheduleEvent(const time::Duration& after, const Event& event);
+  scheduleEvent(const time::nanoseconds& after, const Event& event);
 
   /**
    * \brief Schedule periodic event that should be fired every specified period.
@@ -41,8 +41,8 @@
    * \returns EventId that can be used to cancel the scheduled event
    */
   EventId
-  schedulePeriodicEvent(const time::Duration& after,
-                        const time::Duration& period,
+  schedulePeriodicEvent(const time::nanoseconds& after,
+                        const time::nanoseconds& period,
                         const Event& event);
   
   /**
@@ -60,10 +60,11 @@
 
   struct EventInfo
   {
-    EventInfo(const time::Duration& after,
-              const time::Duration& period,
+    EventInfo(const time::nanoseconds& after,
+              const time::nanoseconds& period,
               const Event& event);
-    EventInfo(const time::Point& when, const EventInfo& previousEvent);
+
+    EventInfo(const time::steady_clock::TimePoint& when, const EventInfo& previousEvent);
 
     bool
     operator <=(const EventInfo& other) const
@@ -77,11 +78,11 @@
       return this->m_scheduledTime < other.m_scheduledTime;
     }
 
-    time::Duration
+    time::nanoseconds
     expiresFromNow() const;
     
-    time::Point m_scheduledTime;
-    time::Duration m_period;
+    time::steady_clock::TimePoint m_scheduledTime;
+    time::nanoseconds m_period;
     Event m_event;
     mutable EventId m_eventId;
   };
@@ -91,7 +92,7 @@
 
   EventQueue m_events;
   EventQueue::iterator m_scheduledEvent;
-  boost::asio::monotonic_deadline_timer m_deadlineTimer;
+  monotonic_deadline_timer m_deadlineTimer;
 
   bool m_isEventExecuting;
 };
diff --git a/src/util/time.cpp b/src/util/time.cpp
deleted file mode 100644
index 07e7f34..0000000
--- a/src/util/time.cpp
+++ /dev/null
@@ -1,49 +0,0 @@
-/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-/**
- * Copyright (C) 2014 Named Data Networking Project
- * See COPYING for copyright and distribution information.
- */
-
-#include "common.hpp"
-
-#include "time.hpp"
-#include <time.h>
-#include <stdexcept>
-#include <sys/time.h>
-
-namespace ndn {
-namespace time {
-
-Point
-now()
-{
-// based on suggestion from https://svn.boost.org/trac/boost/ticket/3504
-#if defined(_POSIX_TIMERS) && ( _POSIX_TIMERS > 0 ) && defined(_POSIX_MONOTONIC_CLOCK)
-
-  struct timespec t;
-  int res = clock_gettime(CLOCK_MONOTONIC, &t);
-
-  if (res == -1) {
-    throw std::runtime_error("clock_gettime");
-  }
-
-  return Point(time::seconds(t.tv_sec) + time::nanoseconds(t.tv_nsec));
-
-#else
-
-  // fallback to wall clock time
-
-  struct timeval tv;
-  int res = gettimeofday(&tv, 0);
-
-  if (res == -1) {
-    throw std::runtime_error("gettimeofday");
-  }
-
-  return Point(time::seconds(tv.tv_sec) + time::microseconds(tv.tv_usec));
-
-#endif
-}
-
-} // namespace time
-} // namespace ndn
diff --git a/src/util/time.hpp b/src/util/time.hpp
index e0b3727..afcb979 100644
--- a/src/util/time.hpp
+++ b/src/util/time.hpp
@@ -1,7 +1,5 @@
 /**
- * Copyright (C) 2013 Regents of the University of California.
- * @author: Jeff Thompson <jefft0@remap.ucla.edu>
- * @author: Yingdi Yu <yingdi@cs.ucla.edu>
+ * Copyright (C) 2013-2014 Regents of the University of California.
  * See COPYING for copyright and distribution information.
  */
 
@@ -9,228 +7,171 @@
 #define NDN_TIME_HPP
 
 #include "../common.hpp"
+#include <boost/chrono.hpp>
+#include <boost/date_time/posix_time/posix_time.hpp>
 
 namespace ndn {
-
-/**
- * A time interval represented as the number of milliseconds.
- */
-typedef int64_t Milliseconds;
-   
-/**
- * The calendar time represented as the number of milliseconds since 1/1/1970.
- */
-typedef int64_t MillisecondsSince1970;
-
-
-const boost::posix_time::ptime UNIX_EPOCH_TIME =
-  boost::posix_time::ptime (boost::gregorian::date (1970, boost::gregorian::Jan, 1));
-
-/**
- * @brief Get the current time in milliseconds since 1/1/1970, including fractions of a millisecond
- */
-inline MillisecondsSince1970 
-getNowMilliseconds()
-{
-  return (boost::posix_time::microsec_clock::universal_time() - UNIX_EPOCH_TIME).total_milliseconds();
-}
-
-inline MillisecondsSince1970 
-ndn_getNowMilliseconds()
-{
-  return getNowMilliseconds();
-}
-
-inline MillisecondsSince1970
-getNow()
-{
-  return getNowMilliseconds();
-}
-
-/**
- * Convert to the ISO string representation of the time.
- * @param time Milliseconds since 1/1/1970.
- * @return The ISO string.
- */
-inline std::string
-toIsoString(const MillisecondsSince1970& time)
-{
-  boost::posix_time::ptime boostTime = UNIX_EPOCH_TIME + boost::posix_time::milliseconds(time);
-
-  /// @todo Determine whether this is necessary at all
-  if ((time % 1000) == 0)
-    return boost::posix_time::to_iso_string(boostTime) + ".000000"; 
-  else
-    return boost::posix_time::to_iso_string(boostTime);
-}
-  
-/**
- * Convert from the ISO string representation to the internal time format.
- * @param isoString The ISO time formatted string. 
- * @return The time in milliseconds since 1/1/1970.
- */
-inline MillisecondsSince1970
-fromIsoString(const std::string& isoString)
-{
-  boost::posix_time::ptime boostTime = boost::posix_time::from_iso_string(isoString);
-  
-  return (boostTime-UNIX_EPOCH_TIME).total_milliseconds();
-}
-
 namespace time {
 
-class monotonic_clock;
+using boost::chrono::duration;
 
-/** \class Duration
- *  \brief represents a time interval
- *  Time unit is nanosecond.
+typedef duration<boost::int_least32_t, boost::ratio<86400> > days;
+using boost::chrono::hours;
+using boost::chrono::minutes;
+using boost::chrono::seconds;
+
+using boost::chrono::milliseconds;
+using boost::chrono::microseconds;
+using boost::chrono::nanoseconds;
+
+using boost::chrono::duration_cast;
+
+/**
+ * \brief System clock
+ *
+ * System clock represents the system-wide real time wall clock.
+ *
+ * It may not be monotonic: on most systems, the system time can be
+ * adjusted at any moment. It is the only clock that has the ability
+ * to be displayed and converted to/from UNIX timestamp.
+ *
+ * To get current TimePoint:
+ *
+ * <code>
+ *     system_clock::TimePoint now = system_clock::now();
+ * </code>
+ *
+ * To convert TimePoint to/from UNIX timestamp:
+ *
+ * <code>
+ *     system_clock::TimePoint time = ...;
+ *     uint64_t timestampInMilliseconds = toUnixTimestamp(time).count();
+ *     system_clock::TimePoint time2 = fromUnixTimestamp(time::milliseconds(timestampInMilliseconds));
+ * </code>
  */
-class Duration
+class system_clock : public boost::chrono::system_clock
 {
 public:
-  Duration()
-    : m_value(0)
-  {
-  }
+  typedef time_point TimePoint;
+  typedef duration Duration;
 
-  explicit
-  Duration(int64_t value)
-    : m_value(value)
-  {
-  }
-  
-  operator int64_t&()
-  {
-    return m_value;
-  }
+  // /// \brief Get current TimePoint
+  // TimePoint
+  // now();
+}; // class system_clock
 
-  operator const int64_t&() const
-  {
-    return m_value;
-  }
-
-  Duration
-  operator+(const Duration& other) const
-  {
-    return Duration(this->m_value + other.m_value);
-  }
-  
-  Duration
-  operator-(const Duration& other) const
-  {
-    return Duration(this->m_value - other.m_value);
-  }
-
-private:
-  int64_t m_value;
-};
-
-/** \class Point
- *  \brief represents a point in time
- *  This uses monotonic clock.
+/**
+ * \brief Steady clock
+ *
+ * Steady clock represents a monotonic clock. The time points of this
+ * clock cannot decrease as physical time moves forward. This clock is
+ * not related to wall clock time, and is best suitable for measuring
+ * intervals.
+ *
+ * Note that on OS X platform this defaults to system clock and is not
+ * truly monotonic. Refer to https://svn.boost.org/trac/boost/ticket/7719)
  */
-class Point
+class steady_clock : public
+#ifdef __APPLE__
+// steady_clock may go backwards on OS X platforms, so use system_clock
+// instead
+    boost::chrono::system_clock
+#else
+    boost::chrono::steady_clock
+#endif
 {
 public:
-  Point()
-    : m_value(0)
-  {
-  }
+  typedef time_point TimePoint;
+  typedef duration Duration;
 
-  explicit
-  Point(int64_t value)
-    : m_value(value)
-  {
-  }
-  
-  operator int64_t&()
-  {
-    return m_value;
-  }
+  // /// \brief Get current TimePoint
+  // TimePoint
+  // now();
+}; // class steady_clock
 
-  operator const int64_t&() const
-  {
-    return m_value;
-  }
 
-  Point
-  operator+(const Duration& other) const
-  {
-    return Point(this->m_value + static_cast<int64_t>(other));
-  }
-  
-  Duration
-  operator-(const Point& other) const
-  {
-    return Duration(this->m_value - other.m_value);
-  }
-
-  Point
-  operator-(const Duration& other) const
-  {
-    return Point(this->m_value  - static_cast<int64_t>(other));
-  }
-  
-private:
-  int64_t m_value;
-};
-
-inline std::ostream&
-operator<<(std::ostream &os, const Duration& duration)
+/**
+ * \brief Get system_clock::TimePoint representing UNIX time epoch (00:00:00 on Jan 1, 1970)
+ */
+inline const system_clock::TimePoint&
+getUnixEpoch()
 {
-  os << static_cast<int64_t>(duration) / 1000000000.0 << " s";
-  return os;
+  static system_clock::TimePoint epoch = system_clock::from_time_t(0);
+  return epoch;
 }
 
 /**
- * \brief Get current time
- * \return{ the current time in monotonic clock }
+ * \brief Convert system_clock::TimePoint to UNIX timestamp
  */
-Point
-now();
-
-/**
- * \brief Get time::Duration for the specified number of seconds
- */
-template<class T>
-inline Duration
-seconds(T value)
+inline milliseconds
+toUnixTimestamp(const system_clock::TimePoint& point)
 {
-  return Duration(value * static_cast<int64_t>(1000000000));
+  return duration_cast<milliseconds>(point - getUnixEpoch());
 }
 
 /**
- * \brief Get time::Duration for the specified number of milliseconds
+ * \brief Convert UNIX timestamp to system_clock::TimePoint
  */
-template<class T>
-inline Duration
-milliseconds(T value)
+inline system_clock::TimePoint
+fromUnixTimestamp(const milliseconds& duration)
 {
-  return Duration(value * static_cast<int64_t>(1000000));
+  return getUnixEpoch() + duration;
 }
 
 /**
- * \brief Get time::Duration for the specified number of microseconds
+ * \brief Convert to the ISO string representation of the time (YYYYMMDDTHHMMSS,fffffffff)
+ *
+ * If timePoint contains doesn't contain fractional seconds the
+ * output format is YYYYMMDDTHHMMSS
+ *
+ * Examples:
+ *
+ *   - with fractional nanoseconds:  20020131T100001,123456789
+ *   - with fractional microseconds: 20020131T100001,123456
+ *   - with fractional milliseconds: 20020131T100001,123
+ *   - without fractional seconds:   20020131T100001
  */
-template<class T>
-inline Duration
-microseconds(T value)
+inline std::string
+toIsoString(const system_clock::TimePoint& timePoint)
 {
-  return Duration(value * static_cast<int64_t>(1000));
+  boost::posix_time::ptime ptime = boost::posix_time::from_time_t(
+                                     system_clock::TimePoint::clock::to_time_t(timePoint));
+
+  uint64_t micro = duration_cast<microseconds>(timePoint - getUnixEpoch()).count() % 1000000;
+  if (micro > 0)
+    {
+      ptime += boost::posix_time::microseconds(micro);
+      return boost::posix_time::to_iso_string(ptime);
+    }
+  else
+    return boost::posix_time::to_iso_string(ptime);
 }
 
 /**
- * \brief Get time::Duration for the specified number of nanoseconds
+ * \brief Convert from the ISO string (YYYYMMDDTHHMMSS,fffffffff) representation
+ *        to the internal time format
+ *
+ * Examples of accepted ISO strings:
+ *
+ *   - with fractional nanoseconds:  20020131T100001,123456789
+ *   - with fractional microseconds: 20020131T100001,123456
+ *   - with fractional milliseconds: 20020131T100001,123
+ *   - without fractional seconds:   20020131T100001
+ *
  */
-inline Duration
-nanoseconds(int64_t value)
+inline system_clock::TimePoint
+fromIsoString(const std::string& isoString)
 {
-  return Duration(value);
-}
+  static boost::posix_time::ptime posixTimeEpoch = boost::posix_time::from_time_t(0);
 
+  boost::posix_time::ptime ptime = boost::posix_time::from_iso_string(isoString);
+
+  system_clock::TimePoint point = system_clock::from_time_t((ptime - posixTimeEpoch).total_seconds());
+  point += microseconds((ptime - posixTimeEpoch).total_microseconds() % 1000000);
+  return point;
+}
 
 } // namespace time
-
 } // namespace ndn
 
 #endif // NDN_TIME_HPP