[llvm] r316419 - Support formatv of TimePoint with strftime-style formats.

Simon Dardis via llvm-commits llvm-commits at lists.llvm.org
Wed Oct 25 02:12:47 PDT 2017


Resending as I mis-spelt the list name.

Hi Sam,

This change appears to have broken llvm-mips-linux, would you be able to take a look?

http://lab.llvm.org:8011/builders/llvm-mips-linux/builds/2658

Thanks,
Simon

-----Original Message-----
From: llvm-commits [mailto:llvm-commits-bounces at lists.llvm.org] On Behalf Of Sam McCall via llvm-commits
Sent: 24 October 2017 09:30
To: llvm-commits at lists.llvm.org
Subject: [llvm] r316419 - Support formatv of TimePoint with strftime-style formats.

Author: sammccall
Date: Tue Oct 24 01:30:19 2017
New Revision: 316419

URL: http://llvm.org/viewvc/llvm-project?rev=316419&view=rev
Log:
Support formatv of TimePoint with strftime-style formats.

Summary:
Support formatv of TimePoint with strftime-style formats.

Extensions for millis/micros/nanos are added.
Inital use case is HH:MM:SS.MMM timestamps in clangd logs.

Reviewers: bkramer, ilya-biryukov

Subscribers: labath, llvm-commits

Differential Revision: https://reviews.llvm.org/D38992

Modified:
    llvm/trunk/include/llvm/Support/Chrono.h
    llvm/trunk/lib/Support/Chrono.cpp
    llvm/trunk/unittests/Support/Chrono.cpp

Modified: llvm/trunk/include/llvm/Support/Chrono.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Support/Chrono.h?rev=316419&r1=316418&r2=316419&view=diff
==============================================================================
--- llvm/trunk/include/llvm/Support/Chrono.h (original)
+++ llvm/trunk/include/llvm/Support/Chrono.h Tue Oct 24 01:30:19 2017
@@ -51,6 +51,20 @@ toTimePoint(std::time_t T) {
 
 raw_ostream &operator<<(raw_ostream &OS, sys::TimePoint<> TP);
 
+/// Format provider for TimePoint<>
+///
+/// The options string is a strftime format string, with extensions:
+///   - %L is millis: 000-999
+///   - %f is micros: 000000-999999
+///   - %N is nanos: 000000000 - 999999999
+///
+/// If no options are given, the default format is "%Y-%m-%d %H:%M:%S.%N".
+template <>
+struct format_provider<sys::TimePoint<>> {
+  static void format(const sys::TimePoint<> &TP, llvm::raw_ostream &OS,
+                     StringRef Style);
+};
+
 /// Implementation of format_provider<T> for duration types.
 ///
 /// The options string of a duration  type has the grammar:

Modified: llvm/trunk/lib/Support/Chrono.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Support/Chrono.cpp?rev=316419&r1=316418&r2=316419&view=diff
==============================================================================
--- llvm/trunk/lib/Support/Chrono.cpp (original)
+++ llvm/trunk/lib/Support/Chrono.cpp Tue Oct 24 01:30:19 2017
@@ -51,4 +51,44 @@ raw_ostream &operator<<(raw_ostream &OS,
                                .count()));  }
 
+void format_provider<TimePoint<>>::format(const TimePoint<> &T, raw_ostream &OS,
+                                          StringRef Style) {
+  using namespace std::chrono;
+  TimePoint<seconds> Truncated = time_point_cast<seconds>(T);
+  auto Fractional = T - Truncated;
+  struct tm LT = getStructTM(Truncated);
+  // Handle extensions first. strftime mangles unknown %x on some platforms.
+  if (Style.empty()) Style = "%Y-%m-%d %H:%M:%S.%N";
+  std::string Format;
+  raw_string_ostream FStream(Format);
+  for (unsigned I = 0; I < Style.size(); ++I) {
+    if (Style[I] == '%' && Style.size() > I + 1) switch (Style[I + 1]) {
+        case 'L':  // Milliseconds, from Ruby.
+          FStream << llvm::format(
+              "%.3lu", duration_cast<milliseconds>(Fractional).count());
+          ++I;
+          continue;
+        case 'f':  // Microseconds, from Python.
+          FStream << llvm::format(
+              "%.6lu", duration_cast<microseconds>(Fractional).count());
+          ++I;
+          continue;
+        case 'N':  // Nanoseconds, from date(1).
+          FStream << llvm::format(
+              "%.6lu", duration_cast<nanoseconds>(Fractional).count());
+          ++I;
+          continue;
+        case '%':  // Consume %%, so %%f parses as (%%)f not %(%f)
+          FStream << "%%";
+          ++I;
+          continue;
+      }
+    FStream << Style[I];
+  }
+  FStream.flush();
+  char Buffer[256];  // Should be enough for anywhen.
+  size_t Len = strftime(Buffer, sizeof(Buffer), Format.c_str(), &LT);
+  OS << (Len ? Buffer : "BAD-DATE-FORMAT"); }
+
 } // namespace llvm

Modified: llvm/trunk/unittests/Support/Chrono.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/Support/Chrono.cpp?rev=316419&r1=316418&r2=316419&view=diff
==============================================================================
--- llvm/trunk/unittests/Support/Chrono.cpp (original)
+++ llvm/trunk/unittests/Support/Chrono.cpp Tue Oct 24 01:30:19 2017
@@ -31,33 +31,35 @@ TEST(Chrono, TimeTConversion) {
   EXPECT_EQ(TP, toTimePoint(toTimeT(TP)));  }
 
-TEST(Chrono, StringConversion) {
+TEST(Chrono, TimePointFormat) {
+  using namespace std::chrono;
+  struct tm TM {};
+  TM.tm_year = 106;
+  TM.tm_mon = 0;
+  TM.tm_mday = 2;
+  TM.tm_hour = 15;
+  TM.tm_min = 4;
+  TM.tm_sec = 5;
+  TM.tm_isdst = -1;
+  TimePoint<> T =
+      system_clock::from_time_t(mktime(&TM)) + nanoseconds(123456789);
+
+  // operator<< uses the format YYYY-MM-DD HH:MM:SS.NNNNNNNNN
   std::string S;
   raw_string_ostream OS(S);
-  OS << system_clock::now();
-
-  // Do a basic sanity check on the output.
-  // The format we expect is YYYY-MM-DD HH:MM:SS.MMMUUUNNN
-  StringRef Date, Time;
-  std::tie(Date, Time) = StringRef(OS.str()).split(' ');
-
-  SmallVector<StringRef, 3> Components;
-  Date.split(Components, '-');
-  ASSERT_EQ(3u, Components.size());
-  EXPECT_EQ(4u, Components[0].size());
-  EXPECT_EQ(2u, Components[1].size());
-  EXPECT_EQ(2u, Components[2].size());
-
-  StringRef Sec, Nano;
-  std::tie(Sec, Nano) = Time.split('.');
+  OS << T;
+  EXPECT_EQ("2006-01-02 15:04:05.123456789", OS.str());
 
-  Components.clear();
-  Sec.split(Components, ':');
-  ASSERT_EQ(3u, Components.size());
-  EXPECT_EQ(2u, Components[0].size());
-  EXPECT_EQ(2u, Components[1].size());
-  EXPECT_EQ(2u, Components[2].size());
-  EXPECT_EQ(9u, Nano.size());
+  // formatv default style matches operator<<.
+  EXPECT_EQ("2006-01-02 15:04:05.123456789", formatv("{0}", T).str()); 
+ // formatv supports strftime-style format strings.
+  EXPECT_EQ("15:04:05", formatv("{0:%H:%M:%S}", T).str());  // formatv 
+ supports our strftime extensions for sub-second precision.
+  EXPECT_EQ("123", formatv("{0:%L}", T).str());  EXPECT_EQ("123456", 
+ formatv("{0:%f}", T).str());  EXPECT_EQ("123456789", formatv("{0:%N}", 
+ T).str());  // our extensions don't interfere with %% escaping.
+  EXPECT_EQ("%foo", formatv("{0:%%foo}", T).str());
 }
 
 // Test that toTimePoint and toTimeT can be called with a arguments with varying


_______________________________________________
llvm-commits mailing list
llvm-commits at lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits


More information about the llvm-commits mailing list