|
18 | 18 | #include "velox/expression/CastExpr.h" |
19 | 19 | #include "velox/external/tzdb/time_zone.h" |
20 | 20 | #include "velox/functions/prestosql/types/TimeWithTimezoneType.h" |
21 | | -#include "velox/functions/prestosql/types/fuzzer_utils/TimeWithTimezoneInputGenerator.h" |
| 21 | +#include "velox/functions/prestosql/types/TimestampWithTimeZoneType.h" |
22 | 22 | #include "velox/type/Time.h" |
23 | 23 | #include "velox/type/Type.h" |
24 | 24 | #include "velox/type/tz/TimeZoneMap.h" |
25 | 25 | #include "velox/vector/DecodedVector.h" |
26 | 26 |
|
27 | 27 | namespace facebook::velox { |
28 | 28 |
|
| 29 | +folly::dynamic TimeWithTimezoneType::serialize() const { |
| 30 | + folly::dynamic obj = folly::dynamic::object; |
| 31 | + obj["name"] = "Type"; |
| 32 | + obj["type"] = name(); |
| 33 | + return obj; |
| 34 | +} |
| 35 | + |
| 36 | +StringView TimeWithTimezoneType::valueToString( |
| 37 | + int64_t value, |
| 38 | + char* const startPos) const { |
| 39 | + // TIME WITH TIME ZONE is encoded similarly to TIMESTAMP WITH TIME ZONE |
| 40 | + // with the most significnat 52 bits representing the time component and the |
| 41 | + // least 12 bits representing the timezone minutes. This is different from |
| 42 | + // TIMESTAMP WITH TIMEZONE where the last 12 bits represent the timezone |
| 43 | + // offset. The timezone offset minutes are stored by value, encoded in the |
| 44 | + // type itself. This allows the type to be used in a timezone-agnostic manner. |
| 45 | + // |
| 46 | + // The time component is a 52 bit value representing the number of |
| 47 | + // milliseconds since midnight in UTC. |
| 48 | + |
| 49 | + int64_t millisUtc = util::unpackMillisUtc(value); |
| 50 | + |
| 51 | + // Ensure time component is within valid range |
| 52 | + VELOX_CHECK_GE(millisUtc, 0, "Time component is negative"); |
| 53 | + VELOX_CHECK_LE(millisUtc, util::kMillisInDay, "Time component is too large"); |
| 54 | + |
| 55 | + // TimeZone's are encoded as a 12 bit value. |
| 56 | + // This represents a range of -14:00 to +14:00, with 0 representing UTC. |
| 57 | + // The range is from -840 to 840 minutes, we thus encode by doing bias |
| 58 | + // encoding and taking 840 as the bias. |
| 59 | + auto timezoneMinutes = util::unpackZoneKeyId(value); |
| 60 | + |
| 61 | + VELOX_CHECK_GE(timezoneMinutes, 0, "Timezone offset is less than -14:00"); |
| 62 | + VELOX_CHECK_LE( |
| 63 | + timezoneMinutes, 1680, "Timezone offset is greater than +14:00"); |
| 64 | + |
| 65 | + // Decode timezone offset from bias-encoded value |
| 66 | + int16_t offsetMinutes = util::decodeTimezoneOffset(timezoneMinutes); |
| 67 | + auto decodedMinutes = std::abs(offsetMinutes); |
| 68 | + |
| 69 | + const auto isBehindUTCString = (offsetMinutes >= 0) ? "+" : "-"; |
| 70 | + |
| 71 | + // Convert UTC time to local time using utility function |
| 72 | + // Example: If UTC time is 06:30:00 and timezone is +05:30, |
| 73 | + // the local time is 12:00:00 |
| 74 | + int64_t millisLocal = util::utcToLocalTime(millisUtc, offsetMinutes); |
| 75 | + |
| 76 | + int64_t hours = millisLocal / util::kMillisInHour; |
| 77 | + int64_t remainingMs = millisLocal % util::kMillisInHour; |
| 78 | + int64_t minutes = remainingMs / util::kMillisInMinute; |
| 79 | + remainingMs = remainingMs % util::kMillisInMinute; |
| 80 | + int64_t seconds = remainingMs / util::kMillisInSecond; |
| 81 | + int64_t millis = remainingMs % util::kMillisInSecond; |
| 82 | + |
| 83 | + int16_t offsetHours = decodedMinutes / util::kMinutesInHour; |
| 84 | + int16_t remainingOffsetMinutes = decodedMinutes % util::kMinutesInHour; |
| 85 | + |
| 86 | + fmt::format_to_n( |
| 87 | + startPos, |
| 88 | + kTimeWithTimezoneToVarcharRowSize, |
| 89 | + "{:02d}:{:02d}:{:02d}.{:03d}{}{:02d}:{:02d}", |
| 90 | + hours, |
| 91 | + minutes, |
| 92 | + seconds, |
| 93 | + millis, |
| 94 | + isBehindUTCString, |
| 95 | + offsetHours, |
| 96 | + remainingOffsetMinutes); |
| 97 | + return StringView{startPos, kTimeWithTimezoneToVarcharRowSize}; |
| 98 | +} |
| 99 | + |
29 | 100 | namespace { |
30 | 101 | void castToTime( |
31 | 102 | const BaseVector& input, |
@@ -279,8 +350,7 @@ class TimeWithTimezoneTypeFactory : public CustomTypeFactory { |
279 | 350 |
|
280 | 351 | AbstractInputGeneratorPtr getInputGenerator( |
281 | 352 | const InputGeneratorConfig& config) const override { |
282 | | - return std::make_shared<fuzzer::TimeWithTimezoneInputGenerator>( |
283 | | - config.seed_, config.nullRatio_); |
| 353 | + return nullptr; |
284 | 354 | } |
285 | 355 | }; |
286 | 356 |
|
|
0 commit comments