Skip to content

Commit

Permalink
Support DateOnly (fixes #273)
Browse files Browse the repository at this point in the history
  • Loading branch information
Michael Ganss committed Aug 24, 2023
1 parent 793e9be commit 80ce481
Show file tree
Hide file tree
Showing 2 changed files with 52 additions and 8 deletions.
28 changes: 28 additions & 0 deletions ExcelMapper.Tests/Tests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3109,5 +3109,33 @@ public void ErrorTest()
new Customer(3, "10031"),
}, customers);
}

record DateOnlyProduct(DateOnly OfferEnd);

[Test]
public void DateOnlyTest()
{
var products = new ExcelMapper(@"../../../xlsx/Products.xlsx").Fetch<DateOnlyProduct>().ToList();

static void AssertProducts(IEnumerable<DateOnlyProduct> products)
{
CollectionAssert.AreEqual(new List<DateOnlyProduct>
{
new DateOnlyProduct(new DateOnly(1970, 01, 01)),
new DateOnlyProduct(new DateOnly(2015, 12, 31)),
new DateOnlyProduct(new DateOnly(1970, 01, 01)),
}, products);
}

AssertProducts(products);

var file = "DateOnlyProducts.xlsx";

new ExcelMapper().Save(file, products);

var savedProducts = new ExcelMapper(file).Fetch<DateOnlyProduct>().ToList();

AssertProducts(savedProducts);
}
}
}
32 changes: 24 additions & 8 deletions ExcelMapper/ColumnInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ internal void SetPropertyType(Type propertyType)
&& !PropertyType.IsEnum
&& PropertyType != typeof(decimal)
&& PropertyType != typeof(string)
&& !DateTypes.Contains(PropertyType)
&& !DateTypes.Contains(PropertyType.FullName)
&& PropertyType != typeof(Guid)
&& PropertyType != typeof(byte[]);
}
Expand Down Expand Up @@ -191,26 +191,39 @@ public bool IsSubType
/// <summary>
/// Types that map to a DateTime column.
/// </summary>
protected static readonly HashSet<Type> DateTypes = new()
protected static readonly HashSet<string> DateTypes = new()
{
typeof(DateTime),
typeof(DateTimeOffset),
typeof(DateTime).FullName,
typeof(DateTimeOffset).FullName,
"System.DateOnly"
};

static DateTime DateOnlyToDateTime(object date)
{
var dateOnly = date.GetType();
var day = (int)dateOnly.GetProperty("Day").GetValue(date);
var month = (int)dateOnly.GetProperty("Month").GetValue(date);
var year = (int)dateOnly.GetProperty("Year").GetValue(date);

return new DateTime(year, month, day);
}

/// <summary>
/// Generates the cell setter.
/// </summary>
/// <returns>The cell setter.</returns>
protected Action<ICell, object> GenerateCellSetter()
{
if (DateTypes.Contains(PropertyType))
if (DateTypes.Contains(PropertyType.FullName))
{
return (c, o) =>
{
if (o == null)
c.SetCellValue((string)null);
else if (o is DateTimeOffset dt)
c.SetCellValue(dt.DateTime);
else if (o.GetType().FullName == "System.DateOnly")
c.SetCellValue(DateOnlyToDateTime(o));
else
c.SetCellValue((DateTime)o);
};
Expand Down Expand Up @@ -318,6 +331,7 @@ private object ParseEnum(Type t, string s)
public virtual object GetPropertyValue(object o, object val, ICell cell)
{
object v;

if (SetProp != null)
v = SetProp(o, val, cell);
else if (IsNullable && val == null)
Expand All @@ -332,6 +346,8 @@ public virtual object GetPropertyValue(object o, object val, ICell cell)
v = System.Text.Encoding.UTF8.GetBytes(val as string);
else if (val is DateTime d && PropertyType == typeof(DateTimeOffset))
v = new DateTimeOffset(d);
else if (val is DateTime && PropertyType.FullName == "System.DateOnly")
v = PropertyType.GetMethod("FromDateTime").Invoke(null, new object[] { val });
else
v = Convert.ChangeType(val, PropertyType, CultureInfo.InvariantCulture);

Expand Down Expand Up @@ -457,7 +473,7 @@ public ColumnInfo(PropertyInfo propertyInfo, MappingDirections direction = Mappi
Property = propertyInfo;
Directions = direction;
defaultCellSetter = GenerateCellSetter();
if (DateTypes.Contains(PropertyType))
if (DateTypes.Contains(PropertyType.FullName))
BuiltinFormat = 0x16; // "m/d/yy h:mm"
}

Expand Down Expand Up @@ -486,7 +502,7 @@ internal void ChangeSetterType(Type newType)
{
SetPropertyType(newType);
defaultCellSetter = GenerateCellSetter();
if (DateTypes.Contains(PropertyType))
if (DateTypes.Contains(PropertyType.FullName))
BuiltinFormat = 0x16; // "m/d/yy h:mm"
else
{
Expand Down Expand Up @@ -527,7 +543,7 @@ public DynamicColumnInfo(string name, Type t)
Name = name;
SetPropertyType(t);
defaultCellSetter = GenerateCellSetter();
if (DateTypes.Contains(PropertyType))
if (DateTypes.Contains(PropertyType.FullName))
BuiltinFormat = 0x16; // "m/d/yy h:mm"
}

Expand Down

0 comments on commit 80ce481

Please sign in to comment.