fix the year 2038 problem in getDateTime

The existing codes cast uint64_t into time_t which is int32_t in
most 32-bit systems. It results overflow if the timestamp is larger
than INT_MAX.
time_t will be 64 bits in future releases of glibc. See
https://sourceware.org/bugzilla/show_bug.cgi?id=28182.

This change workarounds the year 2038 problem via boost's ptime.
std::chrono doesn't help since it is still 32 bits.

Tested on QEMU.
Example output for certificate:
{
  "Name": "HTTPS Certificate",
  "Subject": null,
  "ValidNotAfter": "2106-01-28T20:40:31Z",
  "ValidNotBefore": "2106-02-06T18:28:16Z"
}
Previously, the format is like "1969-12-31T12:00:00+00:00". Note
that the ending "+00:00" is the time zone, not ms.

Tested the schema on QEMU. No new Redfish Service Validator errors.

Signed-off-by: Nan Zhou <nanzhoumails@gmail.com>
Signed-off-by: Ed Tanous <edtanous@google.com>
Change-Id: I8ef0bee3d724184d96253c23f3919447828d3f82
diff --git a/redfish-core/lib/certificate_service.hpp b/redfish-core/lib/certificate_service.hpp
index 045426e..8a78317 100644
--- a/redfish-core/lib/certificate_service.hpp
+++ b/redfish-core/lib/certificate_service.hpp
@@ -643,9 +643,8 @@
                         std::get_if<uint64_t>(&property.second);
                     if (value)
                     {
-                        std::time_t time = static_cast<std::time_t>(*value);
                         asyncResp->res.jsonValue["ValidNotAfter"] =
-                            crow::utility::getDateTime(time);
+                            crow::utility::getDateTimeUint(*value);
                     }
                 }
                 else if (property.first == "ValidNotBefore")
@@ -654,9 +653,8 @@
                         std::get_if<uint64_t>(&property.second);
                     if (value)
                     {
-                        std::time_t time = static_cast<std::time_t>(*value);
                         asyncResp->res.jsonValue["ValidNotBefore"] =
-                            crow::utility::getDateTime(time);
+                            crow::utility::getDateTimeUint(*value);
                     }
                 }
             }
diff --git a/redfish-core/lib/log_services.hpp b/redfish-core/lib/log_services.hpp
index fb515fe..074c927 100644
--- a/redfish-core/lib/log_services.hpp
+++ b/redfish-core/lib/log_services.hpp
@@ -180,8 +180,7 @@
                          << strerror(-ret);
         return false;
     }
-    entryTimestamp = crow::utility::getDateTime(
-        static_cast<std::time_t>(timestamp / 1000 / 1000));
+    entryTimestamp = crow::utility::getDateTimeUint(timestamp / 1000 / 1000);
     return true;
 }
 
@@ -419,7 +418,7 @@
                 {
                     continue;
                 }
-                std::time_t timestamp;
+                uint64_t timestamp = 0;
                 uint64_t size = 0;
                 std::string dumpStatus;
                 nlohmann::json thisEntry;
@@ -485,8 +484,7 @@
                                     messages::internalError(asyncResp->res);
                                     break;
                                 }
-                                timestamp =
-                                    static_cast<std::time_t>(*usecsTimeStamp);
+                                timestamp = (*usecsTimeStamp / 1000 / 1000);
                                 break;
                             }
                         }
@@ -505,7 +503,8 @@
                 thisEntry["@odata.id"] = dumpPath + entryID;
                 thisEntry["Id"] = entryID;
                 thisEntry["EntryType"] = "Event";
-                thisEntry["Created"] = crow::utility::getDateTime(timestamp);
+                thisEntry["Created"] =
+                    crow::utility::getDateTimeUint(timestamp);
                 thisEntry["Name"] = dumpType + " Dump Entry";
 
                 thisEntry["AdditionalDataSizeBytes"] = size;
@@ -578,7 +577,7 @@
                 }
 
                 foundDumpEntry = true;
-                std::time_t timestamp;
+                uint64_t timestamp = 0;
                 uint64_t size = 0;
                 std::string dumpStatus;
 
@@ -635,8 +634,7 @@
                                     messages::internalError(asyncResp->res);
                                     break;
                                 }
-                                timestamp =
-                                    static_cast<std::time_t>(*usecsTimeStamp);
+                                timestamp = *usecsTimeStamp / 1000 / 1000;
                                 break;
                             }
                         }
@@ -660,7 +658,7 @@
                 asyncResp->res.jsonValue["Id"] = entryID;
                 asyncResp->res.jsonValue["EntryType"] = "Event";
                 asyncResp->res.jsonValue["Created"] =
-                    crow::utility::getDateTime(timestamp);
+                    crow::utility::getDateTimeUint(timestamp);
                 asyncResp->res.jsonValue["Name"] = dumpType + " Dump Entry";
 
                 asyncResp->res.jsonValue["AdditionalDataSizeBytes"] = size;
@@ -1490,9 +1488,9 @@
                         thisEntry["Severity"] =
                             translateSeverityDbusToRedfish(*severity);
                         thisEntry["Created"] =
-                            crow::utility::getDateTime(timestamp);
+                            crow::utility::getDateTimeStdtime(timestamp);
                         thisEntry["Modified"] =
-                            crow::utility::getDateTime(updateTimestamp);
+                            crow::utility::getDateTimeStdtime(updateTimestamp);
                         if (filePath != nullptr)
                         {
                             thisEntry["AdditionalDataURI"] =
@@ -1628,9 +1626,9 @@
                         asyncResp->res.jsonValue["Severity"] =
                             translateSeverityDbusToRedfish(*severity);
                         asyncResp->res.jsonValue["Created"] =
-                            crow::utility::getDateTime(timestamp);
+                            crow::utility::getDateTimeStdtime(timestamp);
                         asyncResp->res.jsonValue["Modified"] =
-                            crow::utility::getDateTime(updateTimestamp);
+                            crow::utility::getDateTimeStdtime(updateTimestamp);
                         if (filePath != nullptr)
                         {
                             asyncResp->res.jsonValue["AdditionalDataURI"] =
@@ -3154,8 +3152,8 @@
 
         // Get the Created time from the timestamp
         std::string entryTimeStr;
-        entryTimeStr = crow::utility::getDateTime(
-            static_cast<std::time_t>(usecSinceEpoch / 1000 / 1000));
+        entryTimeStr =
+            crow::utility::getDateTimeUint(usecSinceEpoch / 1000 / 1000);
 
         // assemble messageArgs: BootIndex, TimeOffset(100us), PostCode(hex)
         std::ostringstream hexCode;
diff --git a/redfish-core/lib/managers.hpp b/redfish-core/lib/managers.hpp
index 12af99d..ca5d8c5 100644
--- a/redfish-core/lib/managers.hpp
+++ b/redfish-core/lib/managers.hpp
@@ -1739,12 +1739,11 @@
             }
             // LastRebootTime is epoch time, in milliseconds
             // https://github.com/openbmc/phosphor-dbus-interfaces/blob/7f9a128eb9296e926422ddc312c148b625890bb6/xyz/openbmc_project/State/BMC.interface.yaml#L19
-            time_t lastResetTimeStamp =
-                static_cast<time_t>(*lastResetTimePtr / 1000);
+            uint64_t lastResetTimeStamp = *lastResetTimePtr / 1000;
 
             // Convert to ISO 8601 standard
             aResp->res.jsonValue["LastResetTime"] =
-                crow::utility::getDateTime(lastResetTimeStamp);
+                crow::utility::getDateTimeUint(lastResetTimeStamp);
         },
         "xyz.openbmc_project.State.BMC", "/xyz/openbmc_project/state/bmc0",
         "org.freedesktop.DBus.Properties", "Get",
diff --git a/redfish-core/lib/metric_report.hpp b/redfish-core/lib/metric_report.hpp
index c959495..5ecab77 100644
--- a/redfish-core/lib/metric_report.hpp
+++ b/redfish-core/lib/metric_report.hpp
@@ -26,8 +26,7 @@
             {"MetricId", id},
             {"MetricProperty", metadata},
             {"MetricValue", std::to_string(sensorValue)},
-            {"Timestamp",
-             crow::utility::getDateTime(static_cast<time_t>(timestamp))},
+            {"Timestamp", crow::utility::getDateTimeUint(timestamp)},
         });
     }
 
@@ -53,8 +52,7 @@
     }
 
     const auto& [timestamp, readings] = *timestampReadings;
-    json["Timestamp"] =
-        crow::utility::getDateTime(static_cast<time_t>(timestamp));
+    json["Timestamp"] = crow::utility::getDateTimeUint(timestamp);
     json["MetricValues"] = toMetricValues(readings);
     return true;
 }
diff --git a/redfish-core/lib/systems.hpp b/redfish-core/lib/systems.hpp
index 2f88a77..8e1a6f4 100644
--- a/redfish-core/lib/systems.hpp
+++ b/redfish-core/lib/systems.hpp
@@ -1171,12 +1171,11 @@
             }
             // LastStateChangeTime is epoch time, in milliseconds
             // https://github.com/openbmc/phosphor-dbus-interfaces/blob/33e8e1dd64da53a66e888d33dc82001305cd0bf9/xyz/openbmc_project/State/Chassis.interface.yaml#L19
-            time_t lastResetTimeStamp =
-                static_cast<time_t>(*lastResetTimePtr / 1000);
+            uint64_t lastResetTimeStamp = *lastResetTimePtr / 1000;
 
             // Convert to ISO 8601 standard
             aResp->res.jsonValue["LastResetTime"] =
-                crow::utility::getDateTime(lastResetTimeStamp);
+                crow::utility::getDateTimeUint(lastResetTimeStamp);
         },
         "xyz.openbmc_project.State.Chassis",
         "/xyz/openbmc_project/state/chassis0",
diff --git a/redfish-core/lib/task.hpp b/redfish-core/lib/task.hpp
index 22e9743..b7795a7 100644
--- a/redfish-core/lib/task.hpp
+++ b/redfish-core/lib/task.hpp
@@ -388,11 +388,11 @@
                 asyncResp->res.jsonValue["Name"] = "Task " + strParam;
                 asyncResp->res.jsonValue["TaskState"] = ptr->state;
                 asyncResp->res.jsonValue["StartTime"] =
-                    crow::utility::getDateTime(ptr->startTime);
+                    crow::utility::getDateTimeStdtime(ptr->startTime);
                 if (ptr->endTime)
                 {
                     asyncResp->res.jsonValue["EndTime"] =
-                        crow::utility::getDateTime(*(ptr->endTime));
+                        crow::utility::getDateTimeStdtime(*(ptr->endTime));
                 }
                 asyncResp->res.jsonValue["TaskStatus"] = ptr->status;
                 asyncResp->res.jsonValue["Messages"] = ptr->messages;