summaryrefslogtreecommitdiff
path: root/Source/cmTimestamp.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'Source/cmTimestamp.cxx')
-rw-r--r--Source/cmTimestamp.cxx172
1 files changed, 105 insertions, 67 deletions
diff --git a/Source/cmTimestamp.cxx b/Source/cmTimestamp.cxx
index ac26503c6..4b9718847 100644
--- a/Source/cmTimestamp.cxx
+++ b/Source/cmTimestamp.cxx
@@ -1,112 +1,130 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2012 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmTimestamp.h"
+#include "cmConfigure.h"
#include <cstring>
+#include <sstream>
+#include <stdlib.h>
-#include <sys/types.h>
-#include <sys/stat.h>
+#include "cmSystemTools.h"
-//----------------------------------------------------------------------------
-std::string cmTimestamp::CurrentTime(
- const std::string& formatString, bool utcFlag)
+std::string cmTimestamp::CurrentTime(const std::string& formatString,
+ bool utcFlag)
{
- time_t currentTimeT = time(0);
- if(currentTimeT == time_t(-1))
- {
- return std::string();
+ time_t currentTimeT = time(CM_NULLPTR);
+ std::string source_date_epoch;
+ cmSystemTools::GetEnv("SOURCE_DATE_EPOCH", source_date_epoch);
+ if (!source_date_epoch.empty()) {
+ std::istringstream iss(source_date_epoch);
+ iss >> currentTimeT;
+ if (iss.fail() || !iss.eof()) {
+ cmSystemTools::Error("Cannot parse SOURCE_DATE_EPOCH as integer");
+ exit(27);
}
+ }
+ if (currentTimeT == time_t(-1)) {
+ return std::string();
+ }
return CreateTimestampFromTimeT(currentTimeT, formatString, utcFlag);
}
-//----------------------------------------------------------------------------
std::string cmTimestamp::FileModificationTime(const char* path,
- const std::string& formatString, bool utcFlag)
+ const std::string& formatString,
+ bool utcFlag)
{
- struct stat info;
- memset(&info, 0, sizeof(info));
-
- if(stat(path, &info) != 0)
- {
+ if (!cmsys::SystemTools::FileExists(path)) {
return std::string();
- }
+ }
- return CreateTimestampFromTimeT(info.st_mtime, formatString, utcFlag);
+ time_t mtime = cmsys::SystemTools::ModifiedTime(path);
+ return CreateTimestampFromTimeT(mtime, formatString, utcFlag);
}
-//----------------------------------------------------------------------------
std::string cmTimestamp::CreateTimestampFromTimeT(time_t timeT,
- std::string formatString, bool utcFlag)
+ std::string formatString,
+ bool utcFlag) const
{
- if(formatString.empty())
- {
+ if (formatString.empty()) {
formatString = "%Y-%m-%dT%H:%M:%S";
- if(utcFlag)
- {
+ if (utcFlag) {
formatString += "Z";
- }
}
+ }
struct tm timeStruct;
memset(&timeStruct, 0, sizeof(timeStruct));
- struct tm* ptr = (struct tm*) 0;
- if(utcFlag)
- {
+ struct tm* ptr = (struct tm*)CM_NULLPTR;
+ if (utcFlag) {
ptr = gmtime(&timeT);
- }
- else
- {
+ } else {
ptr = localtime(&timeT);
- }
+ }
- if(ptr == 0)
- {
+ if (ptr == CM_NULLPTR) {
return std::string();
- }
+ }
timeStruct = *ptr;
std::string result;
- for(std::string::size_type i = 0; i < formatString.size(); ++i)
- {
+ for (std::string::size_type i = 0; i < formatString.size(); ++i) {
char c1 = formatString[i];
- char c2 = (i+1 < formatString.size()) ?
- formatString[i+1] : static_cast<char>(0);
+ char c2 = (i + 1 < formatString.size()) ? formatString[i + 1]
+ : static_cast<char>(0);
- if(c1 == '%' && c2 != 0)
- {
- result += AddTimestampComponent(c2, timeStruct);
+ if (c1 == '%' && c2 != 0) {
+ result += AddTimestampComponent(c2, timeStruct, timeT);
++i;
- }
- else
- {
+ } else {
result += c1;
- }
}
+ }
return result;
}
-//----------------------------------------------------------------------------
-std::string cmTimestamp::AddTimestampComponent(
- char flag, struct tm& timeStruct)
+time_t cmTimestamp::CreateUtcTimeTFromTm(struct tm& tm) const
+{
+#if defined(_MSC_VER) && _MSC_VER >= 1400
+ return _mkgmtime(&tm);
+#else
+ // From Linux timegm() manpage.
+
+ std::string tz_old;
+ cmSystemTools::GetEnv("TZ", tz_old);
+ tz_old = "TZ=" + tz_old;
+
+ // The standard says that "TZ=" or "TZ=[UNRECOGNIZED_TZ]" means UTC.
+ // It seems that "TZ=" does NOT work, at least under Windows
+ // with neither MSVC nor MinGW, so let's use explicit "TZ=UTC"
+
+ cmSystemTools::PutEnv("TZ=UTC");
+
+ tzset();
+
+ time_t result = mktime(&tm);
+
+ cmSystemTools::PutEnv(tz_old);
+
+ tzset();
+
+ return result;
+#endif
+}
+
+std::string cmTimestamp::AddTimestampComponent(char flag,
+ struct tm& timeStruct,
+ const time_t timeT) const
{
std::string formatString = "%";
formatString += flag;
- switch(flag)
- {
+ switch (flag) {
+ case 'a':
+ case 'b':
case 'd':
case 'H':
case 'I':
@@ -118,17 +136,37 @@ std::string cmTimestamp::AddTimestampComponent(
case 'w':
case 'y':
case 'Y':
+ case '%':
break;
- default:
- {
- return formatString;
+ case 's': // Seconds since UNIX epoch (midnight 1-jan-1970)
+ {
+ // Build a time_t for UNIX epoch and substract from the input "timeT":
+ struct tm tmUnixEpoch;
+ memset(&tmUnixEpoch, 0, sizeof(tmUnixEpoch));
+ tmUnixEpoch.tm_mday = 1;
+ tmUnixEpoch.tm_year = 1970 - 1900;
+
+ const time_t unixEpoch = this->CreateUtcTimeTFromTm(tmUnixEpoch);
+ if (unixEpoch == -1) {
+ cmSystemTools::Error(
+ "Error generating UNIX epoch in "
+ "STRING(TIMESTAMP ...). Please, file a bug report aginst CMake");
+ return std::string();
}
+
+ std::ostringstream ss;
+ ss << static_cast<long int>(difftime(timeT, unixEpoch));
+ return ss.str();
+ }
+ default: {
+ return formatString;
}
+ }
char buffer[16];
- size_t size = strftime(buffer, sizeof(buffer),
- formatString.c_str(), &timeStruct);
+ size_t size =
+ strftime(buffer, sizeof(buffer), formatString.c_str(), &timeStruct);
return std::string(buffer, size);
}