@@ -246,7 +246,7 @@ struct ICUStrptime : public ICUDateFunc {
246246 TailPatch (name, db, types);
247247 }
248248
249- static bool CastFromVarchar (Vector &source, Vector &result, idx_t count, CastParameters ¶meters) {
249+ static bool VarcharToTimestampTZ (Vector &source, Vector &result, idx_t count, CastParameters ¶meters) {
250250 auto &cast_data = parameters.cast_data ->Cast <CastData>();
251251 auto &info = cast_data.info ->Cast <BindData>();
252252 CalendarPtr cal (info.calendar ->clone ());
@@ -260,7 +260,7 @@ struct ICUStrptime : public ICUDateFunc {
260260 bool has_offset = false ;
261261 if (!Timestamp::TryConvertTimestampTZ (str, len, result, has_offset, tz)) {
262262 auto msg = Timestamp::ConversionError (string (str, len));
263- HandleCastError::AssignError (msg, parameters. error_message );
263+ HandleCastError::AssignError (msg, parameters);
264264 mask.SetInvalid (idx);
265265 } else if (!has_offset) {
266266 // Convert parts to a TZ (default or parsed) if no offset was provided
@@ -280,22 +280,64 @@ struct ICUStrptime : public ICUDateFunc {
280280 return true ;
281281 }
282282
283+ static bool VarcharToTimeTZ (Vector &source, Vector &result, idx_t count, CastParameters ¶meters) {
284+ auto &cast_data = parameters.cast_data ->Cast <CastData>();
285+ auto &info = cast_data.info ->Cast <BindData>();
286+ CalendarPtr cal (info.calendar ->clone ());
287+
288+ UnaryExecutor::ExecuteWithNulls<string_t , dtime_tz_t >(
289+ source, result, count, [&](string_t input, ValidityMask &mask, idx_t idx) {
290+ dtime_tz_t result;
291+ const auto str = input.GetData ();
292+ const auto len = input.GetSize ();
293+ bool has_offset = false ;
294+ idx_t pos = 0 ;
295+ if (!Time::TryConvertTimeTZ (str, len, pos, result, has_offset, false )) {
296+ auto msg = Time::ConversionError (string (str, len));
297+ HandleCastError::AssignError (msg, parameters);
298+ mask.SetInvalid (idx);
299+ } else if (!has_offset) {
300+ // Convert parts to a TZ (default or parsed) if no offset was provided
301+ auto calendar = cal.get ();
302+
303+ // Extract the offset from the calendar
304+ auto offset = ExtractField (calendar, UCAL_ZONE_OFFSET);
305+ offset += ExtractField (calendar, UCAL_DST_OFFSET);
306+ offset /= Interval::MSECS_PER_SEC;
307+
308+ // Apply it to the offset +00 time we parsed.
309+ result = dtime_tz_t (result.time (), offset);
310+ }
311+
312+ return result;
313+ });
314+ return true ;
315+ }
316+
283317 static BoundCastInfo BindCastFromVarchar (BindCastInput &input, const LogicalType &source,
284318 const LogicalType &target) {
285319 if (!input.context ) {
286- throw InternalException (" Missing context for VARCHAR to TIMESTAMPTZ cast." );
320+ throw InternalException (" Missing context for VARCHAR to TIME/ TIMESTAMPTZ cast." );
287321 }
288322
289323 auto cast_data = make_uniq<CastData>(make_uniq<BindData>(*input.context ));
290324
291- return BoundCastInfo (CastFromVarchar, std::move (cast_data));
325+ switch (target.id ()) {
326+ case LogicalTypeId::TIMESTAMP_TZ:
327+ return BoundCastInfo (VarcharToTimestampTZ, std::move (cast_data));
328+ case LogicalTypeId::TIME_TZ:
329+ return BoundCastInfo (VarcharToTimeTZ, std::move (cast_data));
330+ default :
331+ throw InternalException (" Unsupported type for VARCHAR to TIME/TIMESTAMPTZ cast." );
332+ }
292333 }
293334
294335 static void AddCasts (DatabaseInstance &db) {
295336 auto &config = DBConfig::GetConfig (db);
296337 auto &casts = config.GetCastFunctions ();
297338
298339 casts.RegisterCastFunction (LogicalType::VARCHAR, LogicalType::TIMESTAMP_TZ, BindCastFromVarchar);
340+ casts.RegisterCastFunction (LogicalType::VARCHAR, LogicalType::TIME_TZ, BindCastFromVarchar);
299341 }
300342};
301343
0 commit comments