Reduce allocations when parsing times

Change-Id: Ife37d75fef81f5ecff14259f4567b2e16fcd97ab
Signed-off-by: Austin Schuh <austin.linux@gmail.com>
diff --git a/aos/time/BUILD b/aos/time/BUILD
index c0bd99d..04ae38f 100644
--- a/aos/time/BUILD
+++ b/aos/time/BUILD
@@ -8,7 +8,10 @@
     ],
     visibility = ["//visibility:public"],
     deps = select({
-        "@platforms//os:linux": ["@com_github_google_glog//:glog"],
+        "@platforms//os:linux": [
+            "@com_github_google_glog//:glog",
+            "@com_google_absl//absl/strings",
+        ],
         "//conditions:default": ["//motors/core"],
     }),
 )
diff --git a/aos/time/time.cc b/aos/time/time.cc
index 05510e9..4f39c36 100644
--- a/aos/time/time.cc
+++ b/aos/time/time.cc
@@ -9,6 +9,7 @@
 
 #ifdef __linux__
 
+#include "absl/strings/numbers.h"
 #include "glog/logging.h"
 
 #else  // __linux__
@@ -80,6 +81,7 @@
   return stream;
 }
 
+#ifdef __linux__
 std::optional<monotonic_clock::time_point> monotonic_clock::FromString(
     const std::string_view now) {
   // This should undo the operator << above.
@@ -97,18 +99,28 @@
 
   bool negative = now[0] == '-';
 
-  std::string sec(
+  std::string_view sec(
       now.substr(negative ? 1 : 0, now.size() - (negative ? 14 : 13)));
-  std::string nsec(now.substr(now.size() - 12, 9));
+  std::string_view nsec(now.substr(now.size() - 12, 9));
 
   if (!std::all_of(sec.begin(), sec.end(), ::isdigit) ||
       !std::all_of(nsec.begin(), nsec.end(), ::isdigit)) {
     return std::nullopt;
   }
 
+  std::chrono::seconds::rep seconds_data;
+  if (!absl::SimpleAtoi(sec, &seconds_data)) {
+    return std::nullopt;
+  }
+
+  std::chrono::nanoseconds::rep nanoseconds_data;
+  if (!absl::SimpleAtoi(nsec, &nanoseconds_data)) {
+    return std::nullopt;
+  }
+
   return monotonic_clock::time_point(
-      std::chrono::seconds((negative ? -1 : 1) * atoll(sec.c_str())) +
-      std::chrono::nanoseconds((negative ? -1 : 1) * atoll(nsec.c_str())));
+      std::chrono::seconds((negative ? -1 : 1) * seconds_data) +
+      std::chrono::nanoseconds((negative ? -1 : 1) * nanoseconds_data));
 }
 
 std::optional<realtime_clock::time_point> realtime_clock::FromString(
@@ -123,7 +135,7 @@
     return std::nullopt;
   }
 
-  std::string nsec(now.substr(now.size() - 9, 9));
+  std::string_view nsec(now.substr(now.size() - 9, 9));
 
   if (!std::all_of(nsec.begin(), nsec.end(), ::isdigit)) {
     return std::nullopt;
@@ -139,10 +151,16 @@
 
   time_t seconds = mktime(&tm);
 
+  std::chrono::nanoseconds::rep nanoseconds_data;
+  if (!absl::SimpleAtoi(nsec, &nanoseconds_data)) {
+    return std::nullopt;
+  }
+
   return realtime_clock::time_point(
       std::chrono::seconds(seconds) +
-      std::chrono::nanoseconds(atoll(nsec.c_str())));
+      std::chrono::nanoseconds(nanoseconds_data));
 }
+#endif
 
 std::ostream &operator<<(std::ostream &stream,
                          const aos::realtime_clock::time_point &now) {
diff --git a/aos/time/time.h b/aos/time/time.h
index 52d763f..cd4ecda 100644
--- a/aos/time/time.h
+++ b/aos/time/time.h
@@ -26,8 +26,10 @@
 
   // Converts the time string to a time_point if it is well formatted.  This is
   // designed to reverse operator <<.
+#ifdef __linux__
   static std::optional<monotonic_clock::time_point> FromString(
       const std::string_view now);
+#endif
 
   // Returns the epoch (0).
   static constexpr monotonic_clock::time_point epoch() {
@@ -56,8 +58,10 @@
 
   // Converts the time string to a time_point if it is well formatted.  This is
   // designed to reverse operator <<.
+#ifdef __linux__
   static std::optional<realtime_clock::time_point> FromString(
       const std::string_view now);
+#endif
 
   // Returns the epoch (0).
   static constexpr realtime_clock::time_point epoch() {