time.cpp 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132
  1. // Copyright (c) 2014-2021 Thomas Fussell
  2. //
  3. // Permission is hereby granted, free of charge, to any person obtaining a copy
  4. // of this software and associated documentation files (the "Software"), to deal
  5. // in the Software without restriction, including without limitation the rights
  6. // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  7. // copies of the Software, and to permit persons to whom the Software is
  8. // furnished to do so, subject to the following conditions:
  9. //
  10. // The above copyright notice and this permission notice shall be included in
  11. // all copies or substantial portions of the Software.
  12. //
  13. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  14. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  15. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  16. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  17. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  18. // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  19. // THE SOFTWARE
  20. //
  21. // @license: http://www.opensource.org/licenses/mit-license.php
  22. // @author: see AUTHORS file
  23. #include <cmath>
  24. #include <ctime>
  25. #include <xlnt/utils/time.hpp>
  26. namespace {
  27. std::tm safe_localtime(std::time_t raw_time)
  28. {
  29. #ifdef _MSC_VER
  30. std::tm result;
  31. localtime_s(&result, &raw_time);
  32. return result;
  33. #else
  34. return *localtime(&raw_time);
  35. #endif
  36. }
  37. } // namespace
  38. namespace xlnt {
  39. time time::from_number(double raw_time)
  40. {
  41. time result;
  42. double integer_part;
  43. double fractional_part = std::modf(static_cast<double>(raw_time), &integer_part);
  44. fractional_part *= 24;
  45. result.hour = static_cast<int>(fractional_part);
  46. fractional_part = 60 * (fractional_part - result.hour);
  47. result.minute = static_cast<int>(fractional_part);
  48. fractional_part = 60 * (fractional_part - result.minute);
  49. result.second = static_cast<int>(fractional_part);
  50. fractional_part = 1000000 * (fractional_part - result.second);
  51. result.microsecond = static_cast<int>(fractional_part);
  52. if (result.microsecond == 999999 && fractional_part - result.microsecond > 0.5)
  53. {
  54. result.microsecond = 0;
  55. result.second += 1;
  56. if (result.second == 60)
  57. {
  58. result.second = 0;
  59. result.minute += 1;
  60. // TODO: too much nesting
  61. if (result.minute == 60)
  62. {
  63. result.minute = 0;
  64. result.hour += 1;
  65. }
  66. }
  67. }
  68. return result;
  69. }
  70. time::time(int hour_, int minute_, int second_, int microsecond_)
  71. : hour(hour_), minute(minute_), second(second_), microsecond(microsecond_)
  72. {
  73. }
  74. bool time::operator==(const time &comparand) const
  75. {
  76. return hour == comparand.hour && minute == comparand.minute && second == comparand.second
  77. && microsecond == comparand.microsecond;
  78. }
  79. time::time(const std::string &time_string)
  80. : hour(0), minute(0), second(0), microsecond(0)
  81. {
  82. std::string remaining = time_string;
  83. auto colon_index = remaining.find(':');
  84. hour = std::stoi(remaining.substr(0, colon_index));
  85. remaining = remaining.substr(colon_index + 1);
  86. colon_index = remaining.find(':');
  87. minute = std::stoi(remaining.substr(0, colon_index));
  88. colon_index = remaining.find(':');
  89. if (colon_index != std::string::npos)
  90. {
  91. remaining = remaining.substr(colon_index + 1);
  92. second = std::stoi(remaining);
  93. }
  94. }
  95. double time::to_number() const
  96. {
  97. std::uint64_t microseconds = static_cast<std::uint64_t>(microsecond);
  98. microseconds += static_cast<std::uint64_t>(second * 1e6);
  99. microseconds += static_cast<std::uint64_t>(minute * 1e6 * 60);
  100. auto microseconds_per_hour = static_cast<std::uint64_t>(1e6) * 60 * 60;
  101. microseconds += static_cast<std::uint64_t>(hour) * microseconds_per_hour;
  102. auto number = static_cast<double>(microseconds) / (24.0 * static_cast<double>(microseconds_per_hour));
  103. number = std::floor(number * 100e9 + 0.5) / 100e9;
  104. return number;
  105. }
  106. time time::now()
  107. {
  108. std::tm now = safe_localtime(std::time(nullptr));
  109. return time(now.tm_hour, now.tm_min, now.tm_sec);
  110. }
  111. } // namespace xlnt