[Groonga-commit] groonga/grnxx [master] Implement grnxx::Time::universal/local_time().

Back to archive index

susumu.yata null+****@clear*****
Thu Feb 28 11:02:53 JST 2013


susumu.yata	2013-02-28 11:02:53 +0900 (Thu, 28 Feb 2013)

  New Revision: edcbaf42c06e457b6bcebce12f1b5ec578297dca
  https://github.com/groonga/grnxx/commit/edcbaf42c06e457b6bcebce12f1b5ec578297dca

  Log:
    Implement grnxx::Time::universal/local_time().

  Modified files:
    lib/broken_down_time.hpp
    lib/features.hpp
    lib/time.cpp
    lib/time.hpp

  Modified: lib/broken_down_time.hpp (+4 -0)
===================================================================
--- lib/broken_down_time.hpp    2013-02-28 10:31:24 +0900 (43c7295)
+++ lib/broken_down_time.hpp    2013-02-28 11:02:53 +0900 (34dd118)
@@ -35,6 +35,10 @@ struct BrokenDownTime {
   int yday;   // Day in the year.
   int isdst;  // Daylight saving time.
 
+  static constexpr BrokenDownTime invalid_value() {
+    return BrokenDownTime{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
+  }
+
   StringBuilder &write_to(StringBuilder &builder) const;
 };
 

  Modified: lib/features.hpp (+1 -0)
===================================================================
--- lib/features.hpp    2013-02-28 10:31:24 +0900 (87f579c)
+++ lib/features.hpp    2013-02-28 11:02:53 +0900 (f6414f8)
@@ -174,6 +174,7 @@
 
 #if (GRNXX_POSIX_C_SOURCE >= 1) || GRNXX_XOPEN_SOURCE || GRNXX_BSD_SOURCE ||\
     GRNXX_SVID_SOURCE || GRNXX_POSIX_SOURCE
+# define GRNXX_HAS_GMTIME_R
 # define GRNXX_HAS_LOCALTIME_R
 #endif  // (GRNXX_POSIX_C_SOURCE >= 1) || ...
 

  Modified: lib/time.cpp (+70 -0)
===================================================================
--- lib/time.cpp    2013-02-28 10:31:24 +0900 (1ac00f2)
+++ lib/time.cpp    2013-02-28 11:02:53 +0900 (3678f5c)
@@ -33,9 +33,79 @@
 #include "error.hpp"
 #include "intrinsic.hpp"
 #include "logger.hpp"
+#include "lock.hpp"
 #include "string_format.hpp"
 
 namespace grnxx {
+namespace {
+
+// Note: std::tm does not support usec (microseconds).
+BrokenDownTime create_broken_down_time(const std::tm &tm, std::int64_t count) {
+  BrokenDownTime time;
+  time.usec = static_cast<int>(count % 1000000);
+  time.sec = tm.tm_sec;
+  time.min = tm.tm_min;
+  time.hour = tm.tm_hour;
+  time.mday = tm.tm_mday;
+  time.mon = tm.tm_mon;
+  time.year = tm.tm_year;
+  time.wday = tm.tm_wday;
+  time.yday = tm.tm_yday;
+  time.isdst = tm.tm_isdst;
+  return time;
+}
+
+}  // namespace
+
+BrokenDownTime Time::universal_time() const {
+  const std::time_t posix_time = static_cast<std::time_t>(count_ / 1000000);
+  std::tm tm;
+#ifdef GRNXX_MSC
+  if (::gmtime_s(&posix_time, &tm) != 0) {
+    return BrokenDownTime::invalid_value();
+  }
+#elif defined(GRNXX_HAS_GMTIME_R)
+  if (::gmtime_r(&posix_time, &tm) == nullptr) {
+    return BrokenDownTime::invalid_value();
+  }
+#else  // defined(GRNXX_HAS_GMTIME_R)
+  // Lock is used for exclusive access, but it is still not thread-safe
+  // because other threads may call std::gmtime().
+  static Mutex mutex(MUTEX_UNLOCKED);
+  Lock lock(&mutex);
+  std::tm * const shared_tm = std::gmtime(&posix_time);
+  if (!shared_tm) {
+    return BrokenDownTime::invalid_value();
+  }
+  tm = *shared_tm;
+#endif  // defined(GRNXX_HAS_GMTIME_R)
+  return create_broken_down_time(tm, count_);
+}
+
+BrokenDownTime Time::local_time() const {
+  const std::time_t posix_time = static_cast<std::time_t>(count_ / 1000000);
+  std::tm tm;
+#ifdef GRNXX_MSC
+  if (::localtime_s(&posix_time, &tm) != 0) {
+    return BrokenDownTime::invalid_value();
+  }
+#elif defined(GRNXX_HAS_LOCALTIME_R)
+  if (::localtime_r(&posix_time, &tm) == nullptr) {
+    return BrokenDownTime::invalid_value();
+  }
+#else  // defined(GRNXX_HAS_LOCALTIME_R)
+  // Lock is used for exclusive access, but it is still not thread-safe
+  // because other threads may call std::localtime().
+  static Mutex mutex(MUTEX_UNLOCKED);
+  Lock lock(&mutex);
+  std::tm * const shared_tm = std::localtime(&posix_time);
+  if (!shared_tm) {
+    return BrokenDownTime::invalid_value();
+  }
+  tm = *shared_tm;
+#endif  // defined(GRNXX_HAS_LOCALTIME_R)
+  return create_broken_down_time(tm, count_);
+}
 
 StringBuilder &Time::write_to(StringBuilder &builder) const {
   if (!builder) {

  Modified: lib/time.hpp (+0 -1)
===================================================================
--- lib/time.hpp    2013-02-28 10:31:24 +0900 (849bf12)
+++ lib/time.hpp    2013-02-28 11:02:53 +0900 (f5feaa7)
@@ -42,7 +42,6 @@ class Time {
     return Time(std::numeric_limits<int64_t>::max());
   }
 
-  // TODO: To be implemented.
   // Transform tick count to broken-down time (UTC).
   BrokenDownTime universal_time() const;
   // Transform tick count to broken-down time (local).
-------------- next part --------------
HTML����������������������������...
Download 



More information about the Groonga-commit mailing list
Back to archive index