Skip to content

Commit

Permalink
Allow reading ntive DuckDBTimeTz type.
Browse files Browse the repository at this point in the history
  • Loading branch information
Giorgi committed Mar 5, 2024
1 parent 4ea5659 commit 7ac8604
Show file tree
Hide file tree
Showing 3 changed files with 41 additions and 13 deletions.
34 changes: 27 additions & 7 deletions DuckDB.NET.Data/Internal/Reader/DateTimeVectorDataReader.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@ internal class DateTimeVectorDataReader : VectorDataReaderBase
private static readonly Type DateTimeType = typeof(DateTime);
private static readonly Type DateTimeNullableType = typeof(DateTime?);

private static readonly Type DateTimeOffsetType = typeof(DateTimeOffset);
private static readonly Type DateTimeOffsetNullableType = typeof(DateTimeOffset?);

#if NET6_0_OR_GREATER
private static readonly Type DateOnlyType = typeof(DateOnly);
private static readonly Type DateOnlyNullableType = typeof(DateOnly?);
Expand Down Expand Up @@ -66,7 +69,15 @@ protected override T GetValidValue<T>(ulong offset, Type targetType)

if (DuckDBType == DuckDBType.TimeTz)
{
return (T)(object)GetDateTimeOffset(offset);
var timeTz = GetTimeTz(offset);

if (targetType == DateTimeOffsetType || targetType == DateTimeOffsetNullableType)
{
var dateTimeOffset = new DateTimeOffset(timeTz.Time.ToDateTime(), TimeSpan.FromSeconds(timeTz.Offset));
return (T)(object)dateTimeOffset;
}

return (T)(object)timeTz;
}

if (DuckDBType == DuckDBType.Timestamp || DuckDBType == DuckDBType.TimestampTz)
Expand Down Expand Up @@ -114,7 +125,7 @@ internal override object GetValue(ulong offset, Type targetType)
{
DuckDBType.Date => GetDate(offset, targetType),
DuckDBType.Time => GetTime(offset, targetType),
DuckDBType.TimeTz => GetDateTimeOffset(offset),
DuckDBType.TimeTz => GetDateTimeOffset(offset, targetType),
DuckDBType.Timestamp => GetDateTime(offset, targetType),
DuckDBType.TimestampTz => GetDateTime(offset, targetType),
DuckDBType.TimestampS => GetDateTime(offset, targetType, 1000000),
Expand All @@ -124,6 +135,13 @@ internal override object GetValue(ulong offset, Type targetType)
};
}

private DuckDBTimeTz GetTimeTz(ulong offset)
{
var data = GetFieldData<DuckDBTimeTzStruct>(offset);

return NativeMethods.DateTime.DuckDBFromTimeTz(data);
}

private DuckDBTimeOnly GetTimeOnly(ulong offset)
{
return NativeMethods.DateTime.DuckDBFromTime(GetFieldData<DuckDBTime>(offset));
Expand Down Expand Up @@ -184,13 +202,15 @@ private object GetDateTime(ulong offset, Type targetType, int factor = 1, int di
return NativeMethods.DateTime.DuckDBFromTimestamp(data);
}

private DateTimeOffset GetDateTimeOffset(ulong offset)
private object GetDateTimeOffset(ulong offset, Type targetType)
{
var data = GetFieldData<DuckDBTimeTzStruct>(offset);

var timeTz = NativeMethods.DateTime.DuckDBFromTimeTz(data);
var timeTz = GetTimeTz(offset);

if (targetType == typeof(DateTimeOffset))
{
return new DateTimeOffset(timeTz.Time.ToDateTime(), TimeSpan.FromSeconds(timeTz.Offset));
}

return new DateTimeOffset(timeTz.Time.ToDateTime(), TimeSpan.FromSeconds(timeTz.Offset));
return timeTz;
}
}
2 changes: 1 addition & 1 deletion DuckDB.NET.Data/Internal/Reader/VectorDataReaderBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,7 @@ protected virtual Type GetColumnProviderSpecificType()
DuckDBType.Interval => typeof(DuckDBInterval),
DuckDBType.Date => typeof(DuckDBDateOnly),
DuckDBType.Time => typeof(DuckDBTimeOnly),
DuckDBType.TimeTz => typeof(DateTimeOffset),
DuckDBType.TimeTz => typeof(DuckDBTimeTz),
DuckDBType.HugeInt => typeof(DuckDBHugeInt),
DuckDBType.UnsignedHugeInt => typeof(DuckDBUHugeInt),
DuckDBType.Varchar => typeof(string),
Expand Down
18 changes: 13 additions & 5 deletions DuckDB.NET.Test/DuckDBDataReaderTestAllTypes.cs
Original file line number Diff line number Diff line change
Expand Up @@ -231,14 +231,22 @@ public void ReadTimeStampNS()
}, typeof(DuckDBTimestamp));
}

[Fact(Skip = "These dates can't be expressed by DateTime or is unsupported by this library")]
[Fact]
public void ReadTimeTZ()
{
VerifyDataStruct("time_tz", 17, new List<DuckDBTimestamp>
VerifyDataStruct("time_tz", 17, new List<DuckDBTimeTz>
{
new(new(-290308, 12, 22), new(0,0,0)),
new(new(294247, 1, 10), new(4,0,54,775806))
});
new()
{
Offset = (int)new TimeSpan(15,59,59).TotalSeconds,
Time = new DuckDBTimeOnly()
},
new()
{
Offset = -(int)new TimeSpan(15,59,59).TotalSeconds,
Time = new DuckDBTimeOnly(24,0,0)
},
}, readProviderSpecificValue: true);
}

[Fact]
Expand Down

0 comments on commit 7ac8604

Please sign in to comment.