datetime.h 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170
  1. #pragma once
  2. #include <yql/essentials/public/udf/udf_value_builder.h>
  3. #include <yql/essentials/public/udf/tz/udf_tz.h>
  4. #include <util/datetime/base.h>
  5. #include <util/string/printf.h>
  6. namespace NYql::DateTime {
  7. constexpr size_t MAX_TIMEZONE_NAME_LEN = 64;
  8. struct TTMStorage {
  9. unsigned int Year : 12;
  10. unsigned int DayOfYear : 9;
  11. unsigned int WeekOfYear : 6;
  12. unsigned int WeekOfYearIso8601 : 6;
  13. unsigned int DayOfWeek : 3;
  14. unsigned int Month : 4;
  15. unsigned int Day : 5;
  16. unsigned int Hour : 5;
  17. unsigned int Minute : 6;
  18. unsigned int Second : 6;
  19. unsigned int Microsecond : 20;
  20. unsigned int TimezoneId : 16;
  21. TTMStorage() {
  22. Zero(*this);
  23. }
  24. inline static bool IsUniversal(ui16 timezoneId) {
  25. return timezoneId == 0;
  26. }
  27. inline void MakeDefault() {
  28. Year = 1970;
  29. Month = 1;
  30. Day = 1;
  31. Hour = 0;
  32. Minute = 0;
  33. Second = 0;
  34. Microsecond = 0;
  35. TimezoneId = 0;
  36. }
  37. inline void FromDate(const NUdf::IDateBuilder& builder, ui16 value, ui16 timezoneId = 0) {
  38. ui32 year, month, day, dayOfYear, weekOfYear, weekOfYearIso8601, dayOfWeek;
  39. if (!builder.FullSplitDate2(value, year, month, day, dayOfYear, weekOfYear, weekOfYearIso8601, dayOfWeek, timezoneId)) {
  40. ythrow yexception() << "Error in FullSplitDate";
  41. }
  42. TimezoneId = timezoneId;
  43. Year = year;
  44. Month = month;
  45. Day = day;
  46. DayOfYear = dayOfYear;
  47. WeekOfYear = weekOfYear;
  48. WeekOfYearIso8601 = weekOfYearIso8601;
  49. DayOfWeek = dayOfWeek;
  50. }
  51. inline ui16 ToDate(const NUdf::IDateBuilder& builder, bool local) const {
  52. if (!IsUniversal(TimezoneId)) {
  53. ui32 datetime;
  54. if (!builder.MakeDatetime(Year, Month, Day, local ? 0 : Hour, local ? 0 : Minute, local ? 0 : Second, datetime, TimezoneId)) {
  55. ythrow yexception() << "Error in MakeDatetime";
  56. }
  57. return datetime / 86400u;
  58. } else {
  59. ui16 date;
  60. if (!builder.MakeDate(Year, Month, Day, date)) {
  61. ythrow yexception() << "Error in MakeDate";
  62. }
  63. return date;
  64. }
  65. }
  66. inline void FromDatetime(const NUdf::IDateBuilder& builder, ui32 value, ui16 timezoneId = 0) {
  67. ui32 year, month, day, hour, minute, second, dayOfYear, weekOfYear, weekOfYearIso8601, dayOfWeek;
  68. if (!builder.FullSplitDatetime2(value, year, month, day, hour, minute, second, dayOfYear, weekOfYear, weekOfYearIso8601, dayOfWeek, timezoneId)) {
  69. ythrow yexception() << "Error in FullSplitDatetime";
  70. }
  71. TimezoneId = timezoneId;
  72. Year = year;
  73. Month = month;
  74. Day = day;
  75. Hour = hour;
  76. Minute = minute;
  77. Second = second;
  78. DayOfYear = dayOfYear;
  79. WeekOfYear = weekOfYear;
  80. WeekOfYearIso8601 = weekOfYearIso8601;
  81. DayOfWeek = dayOfWeek;
  82. }
  83. inline ui32 ToDatetime(const NUdf::IDateBuilder& builder) const {
  84. ui32 datetime = 0;
  85. if (!builder.MakeDatetime(Year, Month, Day, Hour, Minute, Second, datetime, TimezoneId)) {
  86. ythrow yexception() << "Error in MakeDatetime";
  87. }
  88. return datetime;
  89. }
  90. inline void FromTimestamp(const NUdf::IDateBuilder& builder, ui64 value, ui16 timezoneId = 0) {
  91. const ui32 seconds = value / 1000000ull;
  92. FromDatetime(builder, seconds, timezoneId);
  93. Microsecond = value - seconds * 1000000ull;
  94. }
  95. inline ui64 ToTimestamp(const NUdf::IDateBuilder& builder) const {
  96. return ToDatetime(builder) * 1000000ull + Microsecond;
  97. }
  98. inline bool Validate(const NUdf::IDateBuilder& builder) {
  99. ui32 datetime;
  100. if (!builder.MakeDatetime(Year, Month, Day, Hour, Minute, Second, datetime, TimezoneId)) {
  101. return false;
  102. }
  103. ui32 year, month, day, hour, minute, second, dayOfYear, weekOfYear, weekOfYearIso8601, dayOfWeek;
  104. if (!builder.FullSplitDatetime2(datetime, year, month, day, hour, minute, second, dayOfYear, weekOfYear, weekOfYearIso8601, dayOfWeek, TimezoneId)) {
  105. ythrow yexception() << "Error in FullSplitDatetime.";
  106. }
  107. DayOfYear = dayOfYear;
  108. WeekOfYear = weekOfYear;
  109. WeekOfYearIso8601 = weekOfYearIso8601;
  110. DayOfWeek = dayOfWeek;
  111. return true;
  112. }
  113. inline void FromTimeOfDay(ui64 value) {
  114. Hour = value / 3600000000ull;
  115. value -= Hour * 3600000000ull;
  116. Minute = value / 60000000ull;
  117. value -= Minute * 60000000ull;
  118. Second = value / 1000000ull;
  119. Microsecond = value - Second * 1000000ull;
  120. }
  121. inline ui64 ToTimeOfDay() const {
  122. return ((Hour * 60ull + Minute) * 60ull + Second) * 1000000ull + Microsecond;
  123. }
  124. const TString ToString() const {
  125. const auto& tzName = NUdf::GetTimezones()[TimezoneId];
  126. return Sprintf("%4d-%02d-%02dT%02d:%02d:%02d.%06d,%.*s",
  127. Year, Month, Day, Hour, Minute, Second, Microsecond,
  128. static_cast<int>(tzName.size()), tzName.data());
  129. }
  130. };
  131. static_assert(sizeof(TTMStorage) == 16, "TTMStorage size must be equal to TUnboxedValuePod size");
  132. bool DoAddMonths(TTMStorage& storage, i64 months, const NUdf::IDateBuilder& builder);
  133. bool DoAddYears(TTMStorage& storage, i64 years, const NUdf::IDateBuilder& builder);
  134. TInstant DoAddMonths(TInstant current, i64 months, const NUdf::IDateBuilder& builder);
  135. TInstant DoAddYears(TInstant current, i64 years, const NUdf::IDateBuilder& builder);
  136. }