From 7f4c1c6099343e076c91a4a30dfd018584815770 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Pawe=C5=82=20Pepli=C5=84ski?=
Date: Sun, 12 Jul 2026 20:06:01 +0200
Subject: [PATCH] feat: use DateOnly
---
src/Parquet.Data.Analysis/Extensions.cs | 3 +++
src/Parquet.Test/ParquetReaderOnTestFilesTest.cs | 12 ++++++------
src/Parquet.Test/StatisticsTest.cs | 1 -
src/Parquet.Test/Types/EndToEndTypeTest.cs | 3 +--
src/Parquet/Encodings/SchemaEncoder.cs | 2 +-
src/Parquet/ParquetOptions.cs | 8 +-------
6 files changed, 12 insertions(+), 17 deletions(-)
diff --git a/src/Parquet.Data.Analysis/Extensions.cs b/src/Parquet.Data.Analysis/Extensions.cs
index ed0c648e..3f5f7a3f 100644
--- a/src/Parquet.Data.Analysis/Extensions.cs
+++ b/src/Parquet.Data.Analysis/Extensions.cs
@@ -79,6 +79,7 @@ private static async Task CreateColumnAsync(
if(t == typeof(float)) return new SingleDataFrameColumn(name, await ReadAsync(rgr, field, rowCount, ct));
if(t == typeof(double)) return new DoubleDataFrameColumn(name, await ReadAsync(rgr, field, rowCount, ct));
if(t == typeof(decimal)) return new DecimalDataFrameColumn(name, await ReadAsync(rgr, field, rowCount, ct));
+ if(t == typeof(DateOnly)) return new PrimitiveDataFrameColumn(name, await ReadAsync(rgr, field, rowCount, ct));
if(t == typeof(DateTime)) return new DateTimeDataFrameColumn(name, await ReadAsync(rgr, field, rowCount, ct));
if(t == typeof(TimeSpan)) return new PrimitiveDataFrameColumn(name, await ReadAsync(rgr, field, rowCount, ct));
if(t == typeof(string)) return new StringDataFrameColumn(name, await ReadStringsAsync(rgr, field, rowCount, ct));
@@ -103,6 +104,7 @@ private static async Task AppendToColumnAsync(
if(t == typeof(float)) { Append((PrimitiveDataFrameColumn)col, await ReadAsync(rgr, field, rowCount, ct)); return; }
if(t == typeof(double)) { Append((PrimitiveDataFrameColumn)col, await ReadAsync(rgr, field, rowCount, ct)); return; }
if(t == typeof(decimal)) { Append((PrimitiveDataFrameColumn)col, await ReadAsync(rgr, field, rowCount, ct)); return; }
+ if(t == typeof(DateOnly)) { Append((PrimitiveDataFrameColumn)col, await ReadAsync(rgr, field, rowCount, ct)); return; }
if(t == typeof(DateTime)) { Append((PrimitiveDataFrameColumn)col, await ReadAsync(rgr, field, rowCount, ct)); return; }
if(t == typeof(TimeSpan)) { Append((PrimitiveDataFrameColumn)col, await ReadAsync(rgr, field, rowCount, ct)); return; }
if(t == typeof(string)) { Append((StringDataFrameColumn)col, await ReadStringsAsync(rgr, field, rowCount, ct)); return; }
@@ -153,6 +155,7 @@ private static async Task WriteColumnAsync(DataField field, DataFrameColumn col,
if(t == typeof(float)) { await rgw.WriteAsync(field, ((PrimitiveDataFrameColumn)col).ToArray().AsMemory()); return; }
if(t == typeof(double)) { await rgw.WriteAsync(field, ((PrimitiveDataFrameColumn)col).ToArray().AsMemory()); return; }
if(t == typeof(decimal)) { await rgw.WriteAsync(field, ((PrimitiveDataFrameColumn)col).ToArray().AsMemory()); return; }
+ if(t == typeof(DateOnly)) { await rgw.WriteAsync(field, ((PrimitiveDataFrameColumn)col).ToArray().AsMemory()); return; }
if(t == typeof(DateTime)) { await rgw.WriteAsync(field, ((PrimitiveDataFrameColumn)col).ToArray().AsMemory()); return; }
if(t == typeof(TimeSpan)) { await rgw.WriteAsync(field, ((PrimitiveDataFrameColumn)col).ToArray().AsMemory()); return; }
if(t == typeof(string)) {
diff --git a/src/Parquet.Test/ParquetReaderOnTestFilesTest.cs b/src/Parquet.Test/ParquetReaderOnTestFilesTest.cs
index 74d2bdd0..a0f83f4c 100644
--- a/src/Parquet.Test/ParquetReaderOnTestFilesTest.cs
+++ b/src/Parquet.Test/ParquetReaderOnTestFilesTest.cs
@@ -37,16 +37,16 @@ public async Task Datetypes_all(string parquetFile) {
await using ParquetReader r = await ParquetReader.CreateAsync(s);
using ParquetRowGroupReader rgr = r.OpenRowGroupReader(0);
- var col0 = new DateTime?[rgr.RowGroup.NumRows];
+ var col0 = new DateOnly?[rgr.RowGroup.NumRows];
var col1 = new DateTime?[rgr.RowGroup.NumRows];
- await rgr.ReadAsync(r.Schema.DataFields[0], col0);
+ await rgr.ReadAsync(r.Schema.DataFields[0], col0);
await rgr.ReadAsync(r.Schema.DataFields[1], col1);
- DateTime? o0 = col0[0];
- DateTime? o1 = col0[1];
+ DateOnly? o0 = col0[0];
+ DateOnly? o1 = col0[1];
- Assert.Equal(new DateTime(2017, 1, 1), o0);
- Assert.Equal(new DateTime(2017, 2, 1), o1);
+ Assert.Equal(new DateOnly(2017, 1, 1), o0);
+ Assert.Equal(new DateOnly(2017, 2, 1), o1);
}
[Theory]
diff --git a/src/Parquet.Test/StatisticsTest.cs b/src/Parquet.Test/StatisticsTest.cs
index 3d67dd6b..b6a93057 100644
--- a/src/Parquet.Test/StatisticsTest.cs
+++ b/src/Parquet.Test/StatisticsTest.cs
@@ -69,7 +69,6 @@ public async Task Issue735() {
var parquetOptions = new ParquetOptions {
UseBigDecimal = false,
- UseDateOnlyTypeForDates = true,
UseTimeOnlyTypeForTimeMillis = true,
MaximumSmallPoolFreeBytes = 32 * 1024 * 1024,
MaximumLargePoolFreeBytes = 64 * 1024 * 1024,
diff --git a/src/Parquet.Test/Types/EndToEndTypeTest.cs b/src/Parquet.Test/Types/EndToEndTypeTest.cs
index 25deedc6..7019ed25 100644
--- a/src/Parquet.Test/Types/EndToEndTypeTest.cs
+++ b/src/Parquet.Test/Types/EndToEndTypeTest.cs
@@ -405,8 +405,7 @@ public async Task Type_date_writes_and_reads() {
public async Task Type_dateonly_writes_and_reads() {
var field = new DataField("dateOnly");
DateOnly expected = DateOnly.FromDateTime(DateTime.UtcNow);
- var options = new ParquetOptions { UseDateOnlyTypeForDates = true };
- DateOnly actual = await WriteReadSingleAsync(field, expected, options);
+ DateOnly actual = await WriteReadSingleAsync(field, expected);
Assert.Equal(expected, actual);
}
diff --git a/src/Parquet/Encodings/SchemaEncoder.cs b/src/Parquet/Encodings/SchemaEncoder.cs
index 703f9584..9de331f3 100644
--- a/src/Parquet/Encodings/SchemaEncoder.cs
+++ b/src/Parquet/Encodings/SchemaEncoder.cs
@@ -268,7 +268,7 @@ static bool TryBuildStruct(List schema,
// date
if(se.LogicalType?.DATE != null || se.ConvertedType == ConvertedType.DATE) {
- return options.UseDateOnlyTypeForDates ? typeof(DateOnly) : typeof(DateTime);
+ return typeof(DateOnly);
}
// time
diff --git a/src/Parquet/ParquetOptions.cs b/src/Parquet/ParquetOptions.cs
index 101dc12e..362e11f7 100644
--- a/src/Parquet/ParquetOptions.cs
+++ b/src/Parquet/ParquetOptions.cs
@@ -32,13 +32,7 @@ public class ParquetOptions {
/// When true, big integers are always treated as dates when reading files.
///
public bool TreatBigIntegersAsDates { get; set; } = true;
-
- ///
- /// When set to true, parquet dates will be deserialized as , otherwise as
- /// with missing time part.
- ///
- public bool UseDateOnlyTypeForDates { get; set; } = false;
-
+
///
/// When set to true, parquet times with millisecond precision will be deserialized as ,
/// otherwise as with missing time part.