cmTimestamp.cxx 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162
  1. /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
  2. file Copyright.txt or https://cmake.org/licensing for details. */
  3. #include "cmTimestamp.h"
  4. #include <cstdlib>
  5. #include <cstring>
  6. #include <sstream>
  7. #include <sys/types.h>
  8. // include sys/stat.h after sys/types.h
  9. #include <sys/stat.h>
  10. std::string cmTimestamp::CurrentTime(const std::string& formatString,
  11. bool utcFlag)
  12. {
  13. time_t currentTimeT = time(CM_NULLPTR);
  14. if (currentTimeT == time_t(-1)) {
  15. return std::string();
  16. }
  17. return CreateTimestampFromTimeT(currentTimeT, formatString, utcFlag);
  18. }
  19. std::string cmTimestamp::FileModificationTime(const char* path,
  20. const std::string& formatString,
  21. bool utcFlag)
  22. {
  23. if (!cmsys::SystemTools::FileExists(path)) {
  24. return std::string();
  25. }
  26. time_t mtime = cmsys::SystemTools::ModifiedTime(path);
  27. return CreateTimestampFromTimeT(mtime, formatString, utcFlag);
  28. }
  29. std::string cmTimestamp::CreateTimestampFromTimeT(time_t timeT,
  30. std::string formatString,
  31. bool utcFlag) const
  32. {
  33. if (formatString.empty()) {
  34. formatString = "%Y-%m-%dT%H:%M:%S";
  35. if (utcFlag) {
  36. formatString += "Z";
  37. }
  38. }
  39. struct tm timeStruct;
  40. memset(&timeStruct, 0, sizeof(timeStruct));
  41. struct tm* ptr = (struct tm*)CM_NULLPTR;
  42. if (utcFlag) {
  43. ptr = gmtime(&timeT);
  44. } else {
  45. ptr = localtime(&timeT);
  46. }
  47. if (ptr == CM_NULLPTR) {
  48. return std::string();
  49. }
  50. timeStruct = *ptr;
  51. std::string result;
  52. for (std::string::size_type i = 0; i < formatString.size(); ++i) {
  53. char c1 = formatString[i];
  54. char c2 = (i + 1 < formatString.size()) ? formatString[i + 1]
  55. : static_cast<char>(0);
  56. if (c1 == '%' && c2 != 0) {
  57. result += AddTimestampComponent(c2, timeStruct, timeT);
  58. ++i;
  59. } else {
  60. result += c1;
  61. }
  62. }
  63. return result;
  64. }
  65. time_t cmTimestamp::CreateUtcTimeTFromTm(struct tm& tm) const
  66. {
  67. #if defined(_MSC_VER) && _MSC_VER >= 1400
  68. return _mkgmtime(&tm);
  69. #else
  70. // From Linux timegm() manpage.
  71. std::string tz_old = "";
  72. cmSystemTools::GetEnv("TZ", tz_old);
  73. tz_old = "TZ=" + tz_old;
  74. // The standard says that "TZ=" or "TZ=[UNRECOGNIZED_TZ]" means UTC.
  75. // It seems that "TZ=" does NOT work, at least under Windows
  76. // with neither MSVC nor MinGW, so let's use explicit "TZ=UTC"
  77. cmSystemTools::PutEnv("TZ=UTC");
  78. tzset();
  79. time_t result = mktime(&tm);
  80. cmSystemTools::PutEnv(tz_old);
  81. tzset();
  82. return result;
  83. #endif
  84. }
  85. std::string cmTimestamp::AddTimestampComponent(char flag,
  86. struct tm& timeStruct,
  87. const time_t timeT) const
  88. {
  89. std::string formatString = "%";
  90. formatString += flag;
  91. switch (flag) {
  92. case 'a':
  93. case 'b':
  94. case 'd':
  95. case 'H':
  96. case 'I':
  97. case 'j':
  98. case 'm':
  99. case 'M':
  100. case 'S':
  101. case 'U':
  102. case 'w':
  103. case 'y':
  104. case 'Y':
  105. break;
  106. case 's': // Seconds since UNIX epoch (midnight 1-jan-1970)
  107. {
  108. // Build a time_t for UNIX epoch and substract from the input "timeT":
  109. struct tm tmUnixEpoch;
  110. memset(&tmUnixEpoch, 0, sizeof(tmUnixEpoch));
  111. tmUnixEpoch.tm_mday = 1;
  112. tmUnixEpoch.tm_year = 1970 - 1900;
  113. const time_t unixEpoch = this->CreateUtcTimeTFromTm(tmUnixEpoch);
  114. if (unixEpoch == -1) {
  115. cmSystemTools::Error(
  116. "Error generating UNIX epoch in "
  117. "STRING(TIMESTAMP ...). Please, file a bug report aginst CMake");
  118. return std::string();
  119. }
  120. std::ostringstream ss;
  121. ss << static_cast<long int>(difftime(timeT, unixEpoch));
  122. return ss.str();
  123. }
  124. default: {
  125. return formatString;
  126. }
  127. }
  128. char buffer[16];
  129. size_t size =
  130. strftime(buffer, sizeof(buffer), formatString.c_str(), &timeStruct);
  131. return std::string(buffer, size);
  132. }