• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

Giorgi / DuckDB.NET / 42177946008

06 Nov 2026 06:59AM UTC coverage: 93.611% (+0.8%) from 92.811%
42177946008

push

github

Giorgi
Merge develop into nightly-builds

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01F9b3CGWkCMzmhoxge1QiZ8

2771 of 3009 branches covered (92.09%)

Branch coverage included in aggregate %.

181 of 188 new or added lines in 31 files covered. (96.28%)

2 existing lines in 2 files now uncovered.

4335 of 4582 relevant lines covered (94.61%)

1056169.78 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

90.48
/DuckDB.NET.Data/DataChunk/Reader/TimeVectorDataReader.cs
1
using System.Runtime.CompilerServices;
2

3
namespace DuckDB.NET.Data.DataChunk.Reader;
4

5
// A TIME column (DuckDBTime: microseconds from midnight) or a TIME_NS column (DuckDBTimeNs: nanoseconds). One closed
6
// type per column type, as NumericVectorDataReader: the unit is a constant for the JIT, so a read has no test of the
7
// column type and no divisor kept in a field. The units differ only in GetTicks and GetDuckDBTimeOnly; every rule
8
// below is the same for both. StorageType is not set: the stored structs are not types a value is read as.
9
// TemporalConversionTests compares the .NET types with what DuckDB splits.
10
internal sealed class TimeVectorDataReader<TStorage> : VectorDataReaderBase where TStorage : unmanaged
11
{
12
    internal unsafe TimeVectorDataReader(void* dataPointer, ulong* validityMaskPointer, DuckDBType columnType, string columnName) : base(dataPointer, validityMaskPointer, columnType, columnName)
3,729 ✔
13
    {
14
    }
3,729 ✔
15

16
    internal override DateTime ReadDateTime(ulong offset) => GetValidValue<DateTime>(offset);
777,612 ✔
17
    internal override TimeOnly ReadTimeOnly(ulong offset) => GetValidValue<TimeOnly>(offset);
655,406 ✔
18

19
    protected override T GetValidValue<T>(ulong offset)
20
    {
21
        if (typeof(T) == typeof(TimeOnly))
2,601,868 ✔
22
        {
23
            return (T)(object)new TimeOnly(GetTicks(offset));
655,406 ✔
24
        }
25

26
        if (typeof(T) == typeof(DateTime))
1,946,462 ✔
27
        {
28
            return (T)(object)new DateTime(GetTicks(offset));
777,612 ✔
29
        }
30

31
        if (typeof(T) == typeof(TimeSpan))
1,168,850 ✔
32
        {
33
            return (T)(object)new TimeSpan(GetTicks(offset));
644,433 ✔
34
        }
35

36
        // DuckDBTimeOnly, and any other type, which the cast refuses.
37
        return (T)(object)GetDuckDBTimeOnly(offset);
524,417 ✔
38
    }
39

40
    internal override object GetValueCore(ulong offset, Type targetType)
41
    {
42
        if (targetType == typeof(TimeOnly))
259,338 ✔
43
        {
44
            return new TimeOnly(GetTicks(offset));
259,323 ✔
45
        }
46

47
        if (targetType == typeof(DateTime))
15 !
48
        {
NEW
49
            return new DateTime(GetTicks(offset));
×
50
        }
51

52
        if (targetType == typeof(TimeSpan))
15 !
53
        {
NEW
54
            return new TimeSpan(GetTicks(offset));
×
55
        }
56

57
        return GetDuckDBTimeOnly(offset);
15 ✔
58
    }
59

60
    // The ticks from midnight; what a TIME_NS has below a tick is dropped. DuckDB has 24:00:00 as a time; a TimeOnly
61
    // refuses it, a DateTime takes it as the start of the next day, and a TimeSpan as one day.
62
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
63
    private long GetTicks(ulong offset)
64
    {
65
        var value = GetFieldData<TStorage>(offset);
2,336,774 ✔
66

67
        if (typeof(TStorage) == typeof(DuckDBTimeNs))
2,336,774 ✔
68
        {
69
            return Unsafe.As<TStorage, DuckDBTimeNs>(ref value).Ticks;
48 ✔
70
        }
71

72
        return Unsafe.As<TStorage, DuckDBTime>(ref value).Micros * TimeSpan.TicksPerMicrosecond;
2,336,726 ✔
73
    }
74

75
    // DuckDB splits the microseconds into hour, minute, second and microsecond; what a TIME_NS has below a
76
    // microsecond is dropped, as a TIMESTAMP_NS read as DuckDBTimestamp drops it.
77
    private DuckDBTimeOnly GetDuckDBTimeOnly(ulong offset)
78
    {
79
        var value = GetFieldData<TStorage>(offset);
524,432 ✔
80

81
        if (typeof(TStorage) == typeof(DuckDBTimeNs))
524,432 ✔
82
        {
83
            return Unsafe.As<TStorage, DuckDBTimeNs>(ref value).ToDuckDBTimeOnly();
21 ✔
84
        }
85

86
        return NativeMethods.DateTimeHelpers.DuckDBFromTime(Unsafe.As<TStorage, DuckDBTime>(ref value));
524,411 ✔
87
    }
88
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE TRIAL · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc