incremental
diff --git a/g3log/time.cpp b/g3log/time.cpp
new file mode 100644
index 0000000..937e5d0
--- /dev/null
+++ b/g3log/time.cpp
@@ -0,0 +1,191 @@
+/** ==========================================================================
+* 2012 by KjellKod.cc. This is PUBLIC DOMAIN to use at your own risk and comes
+* with no warranties. This code is yours to share, use and modify with no
+* strings attached and no restrictions or obligations.
+*
+* For more information see g3log/LICENSE or refer refer to http://unlicense.org
+* ============================================================================*/
+
+#include "g3log/time.hpp"
+
+#include <sstream>
+#include <string>
+#include <cstring>
+#include <cmath>
+#include <chrono>
+#include <cassert>
+#include <iomanip>
+#ifdef __MACH__
+#include <sys/time.h>
+#endif
+
+namespace g3 {
+   namespace internal {
+      const std::string kFractionalIdentier   = "%f";
+      const size_t kFractionalIdentierSize = 2;
+
+
+
+      Fractional getFractional(const std::string& format_buffer, size_t pos) {
+         char  ch  = (format_buffer.size() > pos + kFractionalIdentierSize ? format_buffer.at(pos + kFractionalIdentierSize) : '\0');
+         Fractional type = Fractional::NanosecondDefault;
+         switch (ch) {
+            case '3': type = Fractional::Millisecond; break;
+            case '6': type = Fractional::Microsecond; break;
+            case '9': type = Fractional::Nanosecond; break;
+            default: type = Fractional::NanosecondDefault; break;
+         }
+         return type;
+      }
+
+
+      // Returns the fractional as a string with padded zeroes
+      // 1 ms --> 001
+      // 1 us --> 000001
+      // 1 ns --> 000000001
+      std::string to_string(const timespec& time_snapshot, Fractional fractional) {
+         auto ns = time_snapshot.tv_nsec;
+         auto zeroes = 9; // default ns
+         auto digitsToCut = 1; // default ns, divide by 1 makes no change
+         switch (fractional) {
+            case Fractional::Millisecond : {
+               zeroes = 3;
+               digitsToCut = 1000000;
+               break;
+            }
+            case Fractional::Microsecond : {
+               zeroes = 6;
+               digitsToCut = 1000;
+               break;
+            }
+            case Fractional::Nanosecond :
+            case Fractional::NanosecondDefault:
+            default:
+               zeroes = 9;
+               digitsToCut = 1;
+
+         }
+
+         ns /= digitsToCut;
+         // auto value = std::to_string(typeAdjustedValue);
+         // return value; // std::string(fractional_digit, '0') + value;
+         auto value = std::string(std::to_string(ns));
+         return std::string(zeroes - value.size(), '0') + value;
+      }
+   } // internal
+} // g3
+
+
+
+namespace g3 {
+   struct timespec systemtime_now() {
+      struct timespec ts;
+      timespec_get(&ts);
+      return ts;
+   }
+
+
+   // std::timespec_get or posix clock_gettime)(...) are not
+   // implemented on OSX and ubuntu gcc5 has no support for std::timespec_get(...) as of yet
+   // so instead we roll our own.
+   int timespec_get(struct timespec* ts/*, int base*/) {
+      using namespace std::chrono;
+      
+      // thanks @AndreasSchoenle for the implementation and the explanation:
+      // The time since epoch for the steady_clock is not necessarily really the time since 1970.
+      // It usually is the time since program start. Thus, here is calculated the offset between 
+      // the starting point and the real start of the epoch as reported by the system clock 
+      // with the precision of the system clock. 
+      // 
+      // Time stamps will later have system clock accuracy but relative times will have the precision
+      // of the high resolution clock.   
+      thread_local const auto os_system =
+         time_point_cast<nanoseconds>(system_clock::now()).time_since_epoch();
+      thread_local const auto os_high_resolution = 
+         time_point_cast<nanoseconds>(high_resolution_clock::now()).time_since_epoch();
+      thread_local auto os = os_system - os_high_resolution;
+
+      // 32-bit system work-around, where apparenetly the os correction above could sometimes 
+      // become negative. This correction will only be done once per thread
+      if (os.count() < 0 ) {
+         os =  os_system;
+      }
+
+      auto now_ns = (time_point_cast<nanoseconds>(high_resolution_clock::now()).time_since_epoch() + os).count();
+      const auto kNanos = 1000000000;
+      ts ->tv_sec = now_ns / kNanos;
+      ts ->tv_nsec = now_ns % kNanos;
+      #ifdef TIME_UTC
+         return TIME_UTC;
+      #endif
+      return 1;
+   }
+
+
+
+   // This mimics the original "std::put_time(const std::tm* tmb, const charT* fmt)"
+   // This is needed since latest version (at time of writing) of gcc4.7 does not implement this library function yet.
+   // return value is SIMPLIFIED to only return a std::string
+   std::string put_time(const struct tm* tmb, const char* c_time_format) {
+#if (defined(WIN32) || defined(_WIN32) || defined(__WIN32__)) && !defined(__MINGW32__)
+      std::ostringstream oss;
+      oss.fill('0');
+      // BOGUS hack done for VS2012: C++11 non-conformant since it SHOULD take a "const struct tm*  "
+      oss << std::put_time(const_cast<struct tm*> (tmb), c_time_format);
+      return oss.str();
+#else    // LINUX
+      const size_t size = 1024;
+      char buffer[size]; // IMPORTANT: check now and then for when gcc will implement std::put_time.
+      //                    ... also ... This is way more buffer space then we need
+
+      auto success = std::strftime(buffer, size, c_time_format, tmb);
+      // In DEBUG the assert will trigger a process exit. Once inside the if-statement
+      // the 'always true' expression will be displayed as reason for the exit
+      //
+      // In Production mode
+      // the assert will do nothing but the format string will instead be returned
+      if (0 == success) {
+         assert((0 != success) && "strftime fails with illegal formatting");
+         return c_time_format;
+      }
+
+      return buffer;
+#endif
+   }
+
+
+
+   tm localtime(const std::time_t& time) {
+      struct tm tm_snapshot;
+#if (defined(WIN32) || defined(_WIN32) || defined(__WIN32__) && !defined(__GNUC__))
+      localtime_s(&tm_snapshot, &time); // windsows
+#else
+      localtime_r(&time, &tm_snapshot); // POSIX
+#endif
+      return tm_snapshot;
+   }
+
+
+
+
+   std::string localtime_formatted(const timespec& time_snapshot, const std::string& time_format) {
+      auto format_buffer = time_format;  // copying format string to a separate buffer
+
+      // iterating through every "%f" instance in the format string
+      auto identifierExtraSize = 0;
+      for (size_t pos = 0; (pos = format_buffer.find(g3::internal::kFractionalIdentier, pos)) != std::string::npos; pos += g3::internal::kFractionalIdentierSize + identifierExtraSize) {
+         // figuring out whether this is nano, micro or milli identifier
+         auto type = g3::internal::getFractional(format_buffer, pos);
+         auto value = g3::internal::to_string(time_snapshot, type);
+         auto padding = 0;
+         if (type != g3::internal::Fractional::NanosecondDefault) {
+            padding = 1;
+         }
+
+         // replacing "%f[3|6|9]" with sec fractional part value
+         format_buffer.replace(pos, g3::internal::kFractionalIdentier.size() + padding, value);
+      }
+      std::tm t = localtime(time_snapshot.tv_sec);   
+      return g3::put_time(&t, format_buffer.c_str()); // format example: //"%Y/%m/%d %H:%M:%S");
+   }
+} // g3