|
27 | 27 | #include "velox/functions/prestosql/tests/utils/FunctionBaseTest.h" |
28 | 28 | #include "velox/type/Type.h" |
29 | 29 | #include "velox/type/tests/utils/CustomTypesForTesting.h" |
| 30 | +#include "velox/type/tz/TimeZoneMap.h" |
30 | 31 | #include "velox/vector/BaseVector.h" |
31 | 32 | #include "velox/vector/TypeAliases.h" |
32 | 33 |
|
@@ -2975,5 +2976,195 @@ TEST_F(CastExprTest, skipUnnecessaryChildrenOfComplexTypes) { |
2975 | 2976 | testCast(mapVector, expectedMapVector); |
2976 | 2977 | } |
2977 | 2978 | } |
| 2979 | + |
| 2980 | +TEST_F(CastExprTest, timeToVarcharCast) { |
| 2981 | + { |
| 2982 | + // Test casting TIME to VARCHAR |
| 2983 | + |
| 2984 | + // Test various TIME values (milliseconds since midnight) |
| 2985 | + // 0 = 00:00:00.000 |
| 2986 | + // 3661000 = 01:01:01.000 |
| 2987 | + // 43200000 = 12:00:00.000 (noon) |
| 2988 | + // 86399999 = 23:59:59.999 |
| 2989 | + auto timeVector = |
| 2990 | + makeFlatVector<int64_t>({0, 3661000, 43200000, 86399999}, TIME()); |
| 2991 | + |
| 2992 | + auto result = evaluate<FlatVector<StringView>>( |
| 2993 | + "cast(c0 as varchar)", makeRowVector({timeVector})); |
| 2994 | + |
| 2995 | + auto expected = makeFlatVector<StringView>( |
| 2996 | + {"00:00:00.000", "01:01:01.000", "12:00:00.000", "23:59:59.999"}); |
| 2997 | + |
| 2998 | + assertEqualVectors(expected, result); |
| 2999 | + } |
| 3000 | + |
| 3001 | + { |
| 3002 | + // Test casting TIME to VARCHAR with nulls |
| 3003 | + auto timeVector = makeNullableFlatVector<int64_t>( |
| 3004 | + {0, std::nullopt, 43200000, std::nullopt}, TIME()); |
| 3005 | + |
| 3006 | + auto result = evaluate<FlatVector<StringView>>( |
| 3007 | + "cast(c0 as varchar)", makeRowVector({timeVector})); |
| 3008 | + |
| 3009 | + auto expected = makeNullableFlatVector<StringView>( |
| 3010 | + {"00:00:00.000", std::nullopt, "12:00:00.000", std::nullopt}); |
| 3011 | + |
| 3012 | + assertEqualVectors(expected, result); |
| 3013 | + } |
| 3014 | + |
| 3015 | + { |
| 3016 | + // Test try_cast for TIME to VARCHAR |
| 3017 | + auto timeVector = makeFlatVector<int64_t>({0, 43200000}, TIME()); |
| 3018 | + |
| 3019 | + auto result = evaluate<FlatVector<StringView>>( |
| 3020 | + "try_cast(c0 as varchar)", makeRowVector({timeVector})); |
| 3021 | + |
| 3022 | + auto expected = |
| 3023 | + makeFlatVector<StringView>({"00:00:00.000", "12:00:00.000"}); |
| 3024 | + |
| 3025 | + assertEqualVectors(expected, result); |
| 3026 | + } |
| 3027 | + |
| 3028 | + { |
| 3029 | + // Test across different time zones with America/Los_Angeles timezone |
| 3030 | + |
| 3031 | + // Test various TIME values (milliseconds since midnight) |
| 3032 | + // Los Angeles is UTC-8 (standard time) or UTC-7 (daylight saving time) |
| 3033 | + auto timeVector = makeFlatVector<int64_t>( |
| 3034 | + { |
| 3035 | + 0, // 00:00:00.000 UTC -> should adjust for timezone |
| 3036 | + 3661000, // 01:01:01.000 UTC -> should adjust for timezone |
| 3037 | + 43200000, // 12:00:00.000 UTC -> should adjust for timezone |
| 3038 | + 86399999, // 23:59:59.999 UTC -> should adjust for timezone |
| 3039 | + 25200000, // 07:00:00.000 UTC -> should adjust for timezone |
| 3040 | + 72000000 // 20:00:00.000 UTC -> should adjust for timezone |
| 3041 | + }, |
| 3042 | + TIME()); |
| 3043 | + |
| 3044 | + // With timezone displacement, the times should be adjusted |
| 3045 | + // Note: The exact expected values depend on the timezone implementation |
| 3046 | + // This test verifies that timezone-aware casting is working |
| 3047 | + |
| 3048 | + { |
| 3049 | + // In Daylight savings time at session start time below. |
| 3050 | + setSessionStartTimeAndTimeZone( |
| 3051 | + 1756710000000, "America/Los_Angeles"); // 2025-09-01T00:00:00.000 |
| 3052 | + |
| 3053 | + auto result = evaluate<FlatVector<StringView>>( |
| 3054 | + "cast(c0 as varchar)", makeRowVector({timeVector})); |
| 3055 | + |
| 3056 | + auto expected = makeFlatVector<StringView>({ |
| 3057 | + "17:00:00.000", // 00:00:00.000 - 7 hours = 17:00:00.000 (previous |
| 3058 | + // day) |
| 3059 | + "18:01:01.000", // 01:01:01.000 - 7 hours = 18:01:01.000 (previous |
| 3060 | + // day) |
| 3061 | + "05:00:00.000", // 12:00:00.000 - 7 hours = 05:00:00.000 |
| 3062 | + "16:59:59.999", // 23:59:59.999 - 7 hours = 16:59:59.999 |
| 3063 | + "00:00:00.000", // 07:00:00.000 - 7 hours = 00:00:00.000 (mid night) |
| 3064 | + "13:00:00.000" // 20:00:00.000 - 7 hours = 12:00:00.000 |
| 3065 | + }); |
| 3066 | + |
| 3067 | + assertEqualVectors(expected, result); |
| 3068 | + } |
| 3069 | + |
| 3070 | + { |
| 3071 | + // Not In Daylight savings time at session start time below. |
| 3072 | + setSessionStartTimeAndTimeZone( |
| 3073 | + 1762761600000, "America/Los_Angeles"); // 025-11-10T00:00:00.000 |
| 3074 | + |
| 3075 | + auto result = evaluate<FlatVector<StringView>>( |
| 3076 | + "cast(c0 as varchar)", makeRowVector({timeVector})); |
| 3077 | + |
| 3078 | + auto expected = makeFlatVector<StringView>({ |
| 3079 | + "16:00:00.000", // 00:00:00.000 - 8 hours = 16:00:00.000 (previous |
| 3080 | + // day) |
| 3081 | + "17:01:01.000", // 01:01:01.000 - 8 hours = 17:01:01.000 (previous |
| 3082 | + // day) |
| 3083 | + "04:00:00.000", // 12:00:00.000 - 8 hours = 04:00:00.000 |
| 3084 | + "15:59:59.999", // 23:59:59.999 - 8 hours = 15:59:59.999 |
| 3085 | + "23:00:00.000", // 07:00:00.000 - 8 hours = 23:00:00.000 (previous |
| 3086 | + // day) |
| 3087 | + "12:00:00.000" // 20:00:00.000 - 8 hours = 12:00:00.000 |
| 3088 | + }); |
| 3089 | + |
| 3090 | + assertEqualVectors(expected, result); |
| 3091 | + } |
| 3092 | + |
| 3093 | + { |
| 3094 | + // Try this again with a different timezone |
| 3095 | + setTimezone("Australia/Perth"); |
| 3096 | + |
| 3097 | + auto result = evaluate<FlatVector<StringView>>( |
| 3098 | + "cast(c0 as varchar)", makeRowVector({timeVector})); |
| 3099 | + |
| 3100 | + // Perth is always UTC+8 (no daylight saving time) |
| 3101 | + auto expected = makeFlatVector<StringView>({ |
| 3102 | + "08:00:00.000", // 00:00:00.000 + 8 hours |
| 3103 | + "09:01:01.000", // 01:01:01.000 + 8 hours |
| 3104 | + "20:00:00.000", // 12:00:00.000 + 8 hours |
| 3105 | + "07:59:59.999", // 23:59:59.999 + 8 hours (wraps around) |
| 3106 | + "15:00:00.000", // 07:00:00.000 + 8 hours |
| 3107 | + "04:00:00.000" // 20:00:00.000 + 8 hours (wraps around) |
| 3108 | + }); |
| 3109 | + |
| 3110 | + assertEqualVectors(expected, result); |
| 3111 | + } |
| 3112 | + } |
| 3113 | + |
| 3114 | + { |
| 3115 | + // Test during daylight saving time , March 10, 2024 09:00:00 AM UTC |
| 3116 | + // Spring forward. The clock jumps forward 1 hour, from 2:00 AM to 3:00 AM. |
| 3117 | + setSessionStartTimeAndTimeZone(1710061200000, "America/Los_Angeles"); |
| 3118 | + |
| 3119 | + auto timeVector = makeFlatVector<int64_t>( |
| 3120 | + { |
| 3121 | + 0, // 00:00:00.000 UTC -> should adjust for timezone |
| 3122 | + 3661000, // 01:01:01.000 UTC -> should adjust for timezone |
| 3123 | + 43200000, // 12:00:00.000 UTC -> should adjust for timezone |
| 3124 | + 86399999, // 23:59:59.999 UTC -> should adjust for timezone |
| 3125 | + 25200000, // 07:00:00.000 UTC -> should adjust for timezone |
| 3126 | + 72000000 // 20:00:00.000 UTC -> should adjust for timezone |
| 3127 | + }, |
| 3128 | + TIME()); |
| 3129 | + |
| 3130 | + auto result = evaluate<FlatVector<StringView>>( |
| 3131 | + "cast(c0 as varchar)", makeRowVector({timeVector})); |
| 3132 | + |
| 3133 | + auto expected = makeFlatVector<StringView>({ |
| 3134 | + "16:00:00.000", // 00:00:00.000 - 8 hours = 16:00:00.000 (previous |
| 3135 | + // day) |
| 3136 | + "17:01:01.000", // 01:01:01.000 - 8 hours = 17:01:01.000 (previous |
| 3137 | + // day) |
| 3138 | + "05:00:00.000", // 12:00:00.000 - 7 hours = 05:00:00.000 |
| 3139 | + "16:59:59.999", // 23:59:59.999 - 7 hours = 16:59:59.999 |
| 3140 | + "23:00:00.000", // 07:00:00.000 - 8 hours = 23:00:00.000 (previous |
| 3141 | + // day) |
| 3142 | + "13:00:00.000" // 20:00:00.000 - 7 hours = 13:00:00.000 |
| 3143 | + }); |
| 3144 | + |
| 3145 | + assertEqualVectors(expected, result); |
| 3146 | + |
| 3147 | + // Fall Back. The clock jumps back 1 hour, from 2:00 AM to 1:00 AM. |
| 3148 | + setSessionStartTimeAndTimeZone(1730620800000, "America/Los_Angeles"); |
| 3149 | + |
| 3150 | + result = evaluate<FlatVector<StringView>>( |
| 3151 | + "cast(c0 as varchar)", makeRowVector({timeVector})); |
| 3152 | + |
| 3153 | + expected = makeFlatVector<StringView>({ |
| 3154 | + "17:00:00.000", // 00:00:00.000 - 7 hours = 17:00:00.000 (previous |
| 3155 | + // day) |
| 3156 | + "18:01:01.000", // 01:01:01.000 - 7 hours = 18:01:01.000 (previous |
| 3157 | + // day) |
| 3158 | + "04:00:00.000", // 12:00:00.000 - 8 hours = 04:00:00.000 |
| 3159 | + "15:59:59.999", // 23:59:59.999 - 8 hours = 15:59:59.999 |
| 3160 | + "00:00:00.000", // 07:00:00.000 - 7 hours = 00:00:00.000 (previous |
| 3161 | + // day) |
| 3162 | + "12:00:00.000" // 20:00:00.000 - 8 hours = 12:00:00.000 |
| 3163 | + }); |
| 3164 | + |
| 3165 | + assertEqualVectors(expected, result); |
| 3166 | + } |
| 3167 | +} |
| 3168 | + |
2978 | 3169 | } // namespace |
2979 | 3170 | } // namespace facebook::velox::test |
0 commit comments