cmTimestamp.cxx 4.4 KB

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