Skip to content

Commit

Permalink
close #34 and #58 to support DateTimeOffset
Browse files Browse the repository at this point in the history
  • Loading branch information
Donny Tian committed Jun 1, 2022
1 parent ce9204e commit 0e3ed14
Show file tree
Hide file tree
Showing 6 changed files with 178 additions and 21 deletions.
94 changes: 78 additions & 16 deletions Npoi.Mapper/src/Npoi.Mapper/MapHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,11 @@ public class MapHelper
/// </summary>
public static readonly Type DateTimeType = typeof(DateTime);

/// <summary>
/// Caches for type of DateTimeOffset during parsing.
/// </summary>
public static readonly Type DateTimeOffsetType = typeof(DateTimeOffset);

/// <summary>
/// Caches for type of object.
/// </summary>
Expand Down Expand Up @@ -312,6 +317,7 @@ public static CellType GetCellType(ICell cell)
/// </summary>
/// <param name="cell">The cell to retrieve value.</param>
/// <param name="targetType">Type of target property.</param>
/// <param name="trimSpacesType">Type of whitespace trim if the cell is a string.</param>
/// <param name="value">The returned value for cell.</param>
/// <returns><c>true</c> if get value successfully; otherwise false.</returns>
public static bool TryGetCellValue(ICell cell, Type targetType, TrimSpacesType trimSpacesType, out object value)
Expand Down Expand Up @@ -347,7 +353,7 @@ public static bool TryGetCellValue(ICell cell, Type targetType, TrimSpacesType t

case CellType.Numeric:

if (DateUtil.IsCellDateFormatted(cell) || targetType == typeof(DateTime)) // DateTime type.
if (DateUtil.IsCellDateFormatted(cell) || targetType == DateTimeType || targetType == DateTimeOffsetType)
{
value = cell.DateCellValue;
}
Expand Down Expand Up @@ -551,41 +557,32 @@ internal static bool TryConvertType(object value, IColumnInfo column, bool useDe
if (column.Attribute.DefaultValue != null)
{
result = column.Attribute.DefaultValue;
return true;
}
else if (useDefaultValueAttr && column.Attribute.DefaultValueAttribute != null)
{
result = column.Attribute.DefaultValueAttribute.Value;
return true;
}

return true;
}

var stringValue = value as string;
var targetType = column.Attribute.Property.PropertyType;
var underlyingType = column.Attribute.PropertyUnderlyingType;
targetType = underlyingType ?? targetType;

if (stringValue != null)
if (targetType == DateTimeType || targetType == DateTimeOffsetType)
{
return TryConvertToDateTime(value, targetType == DateTimeOffsetType, column.Attribute.CustomFormat, ref result);
}

if (value is string stringValue)
{
if (targetType == StringType)
{
result = stringValue;
return true;
}

if (targetType == DateTimeType)
{
if (DateTime.TryParseExact(stringValue, column.Attribute.CustomFormat, CultureInfo.CurrentCulture,
DateTimeStyles.AllowWhiteSpaces, out DateTime dateTime)
)
{
result = dateTime;
return true;
}
}

if (targetType.IsNumeric() && double.TryParse(stringValue, NumberStyles.Any, null, out double doubleResult))
{
result = Convert.ChangeType(doubleResult, targetType);
Expand Down Expand Up @@ -633,6 +630,71 @@ internal static bool TryConvertType(object value, IColumnInfo column, bool useDe
return true;
}

private static bool TryConvertToDateTime(object value, bool isDateTimeOffset, string format, ref object result)
{
if (value is string stringValue)
{
// string to DateTimeOffset
if (isDateTimeOffset)
{
if (!string.IsNullOrWhiteSpace(format))
{
if (DateTimeOffset.TryParseExact(stringValue, format,
CultureInfo.CurrentCulture, DateTimeStyles.AllowWhiteSpaces, out var dateTimeOffset2))
{
result = dateTimeOffset2;
return true;
}
}

if (DateTimeOffset.TryParse(stringValue,
CultureInfo.CurrentCulture, DateTimeStyles.AllowWhiteSpaces, out var dateTimeOffset))
{
result = dateTimeOffset;
return true;
}

return false;
}

// string to DateTime
if (!string.IsNullOrWhiteSpace(format))
{
if (DateTime.TryParseExact(stringValue, format, CultureInfo.CurrentCulture, DateTimeStyles.AllowWhiteSpaces, out var dateTime2))
{
result = dateTime2;
return true;
}
}

if (DateTime.TryParse(stringValue, CultureInfo.CurrentCulture, DateTimeStyles.AllowWhiteSpaces, out var dateTime))
{
result = dateTime;
return true;
}

return false;
}

if (value is DateTime dateTimeValue)
{
// ReSharper disable once ConvertIfStatementToConditionalTernaryExpression
// Ternary expression will implicitly convert result as a DateTimeOffset.
if (isDateTimeOffset)
{
result = new DateTimeOffset(dateTimeValue);
}
else
{
result = dateTimeValue;
}

return true;
}

return false;
}

// Gets the concrete type instead of the type of object.
internal static Type GetConcreteType<T>(T[] objects)
{
Expand Down
2 changes: 1 addition & 1 deletion Npoi.Mapper/src/Npoi.Mapper/Mapper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -848,7 +848,7 @@ void ColumnFailed(IColumnInfo column, string message)
else if (propertyType != null)
{
// Change types between IConvertible objects, such as double, float, int and etc.
if (MapHelper.TryConvertType(valueObj, column, this.UseDefaultValueAttribute, out object result))
if (MapHelper.TryConvertType(valueObj, column, UseDefaultValueAttribute, out object result))
{
column.Attribute.Property.SetValue(target, result, null);
}
Expand Down
18 changes: 18 additions & 0 deletions Npoi.Mapper/test/Extensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
using System;
using NUnit.Framework;

namespace test
{
public static class Extensions
{
public static DateTime Truncate(this DateTime d)
{
return new DateTime(d.Year, d.Month, d.Day, d.Hour, d.Minute, d.Second, d.Kind);
}

public static DateTimeOffset Truncate(this DateTimeOffset d)
{
return new DateTimeOffset(d.Year, d.Month, d.Day, d.Hour, d.Minute, d.Second, d.Offset);
}
}
}
78 changes: 78 additions & 0 deletions Npoi.Mapper/test/ImportGeneralTests.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System;
using System.ComponentModel;
using System.Globalization;
using System.IO;
using System.Linq;

Expand All @@ -20,12 +21,14 @@ private class TestClass
public string String { get; set; }
public DateTime DateTime { get; set; }
public double Double { get; set; }
public DateTimeOffset DateTimeOffsetProperty { get; set; }
}

private class NullableClass
{
public DateTime? NullableDateTime { get; set; }
public string NormalString { get; set; }
public DateTimeOffset? NullableDateTimeOffset { get; set; }
}

private class TestDefaultClass
Expand Down Expand Up @@ -603,5 +606,80 @@ public void Take_ColumnName_CaseInsensitive()
// Assert
Assert.AreEqual(value, items[0].Value.String);
}

[Test]
public void Take_DateTime_And_DateTimeOffice()
{
// Arrange
var value = DateTimeOffset.Now.Truncate();
var workbook = GetBlankWorkbook();
var sheet = workbook.GetSheetAt(0);

var header = sheet.CreateRow(0);
header.CreateCell(0).SetCellValue(nameof(TestClass.DateTime));
header.CreateCell(1).SetCellValue(nameof(TestClass.DateTimeOffsetProperty));

var row1 = sheet.CreateRow(1);
row1.CreateCell(0).SetCellValue(value.ToString(CultureInfo.InvariantCulture));
row1.CreateCell(1).SetCellValue(value.ToString(CultureInfo.InvariantCulture));

var row2 = sheet.CreateRow(2);
row2.CreateCell(0).SetCellValue(value.DateTime);
row2.CreateCell(1).SetCellValue(value.DateTime);

var mapper = new Mapper(workbook);

// Act
var items = mapper.Take<TestClass>().ToList();

// Assert
Assert.AreEqual(value.DateTime, items[0].Value.DateTime);
Assert.AreEqual(value, items[0].Value.DateTimeOffsetProperty);
Assert.AreEqual(value.DateTime, items[1].Value.DateTime);
Assert.AreEqual(value, items[1].Value.DateTimeOffsetProperty);
}

[Test]
public void Take_Nullable_DateTime_And_DateTimeOffice()
{
// Arrange
var value = DateTimeOffset.Now.Truncate();
var workbook = GetBlankWorkbook();
var sheet = workbook.GetSheetAt(0);

var header = sheet.CreateRow(0);
header.CreateCell(0).SetCellValue(nameof(NullableClass.NormalString));
header.CreateCell(1).SetCellValue(nameof(NullableClass.NullableDateTime));
header.CreateCell(2).SetCellValue(nameof(NullableClass.NullableDateTimeOffset));

var row1 = sheet.CreateRow(1);
row1.CreateCell(0).SetCellValue(value.ToString(CultureInfo.InvariantCulture));
row1.CreateCell(1).SetCellValue(value.ToString(CultureInfo.InvariantCulture));
row1.CreateCell(2).SetCellValue(value.ToString(CultureInfo.InvariantCulture));

var row2 = sheet.CreateRow(2);
row2.CreateCell(0).SetCellValue(value.ToString(CultureInfo.InvariantCulture));
row2.CreateCell(1).SetCellValue(value.DateTime);
row2.CreateCell(2).SetCellValue(value.DateTime);

var row3 = sheet.CreateRow(3);
row3.CreateCell(0).SetCellValue(value.ToString(CultureInfo.InvariantCulture));
row3.CreateCell(1).SetCellValue(default(string));
row3.CreateCell(2).SetCellValue(default(string));

var mapper = new Mapper(workbook);

// Act
var items = mapper.Take<NullableClass>().ToList();

// Assert
Assert.AreEqual(value.DateTime, items[0].Value.NullableDateTime);
Assert.AreEqual(value, items[0].Value.NullableDateTimeOffset);
Assert.AreEqual(value.DateTime, items[1].Value.NullableDateTime);
Assert.AreEqual(value, items[1].Value.NullableDateTimeOffset);
Assert.AreEqual(value.ToString(CultureInfo.InvariantCulture), items[2].Value.NormalString);
Assert.IsNull(items[2].Value.NullableDateTime);
Assert.IsNull(items[2].Value.NullableDateTimeOffset);
}
}
}
4 changes: 0 additions & 4 deletions Npoi.Mapper/test/TestBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,6 @@ public abstract class TestBase

protected IWorkbook Workbook { get; set; }

#region Protected Methods

/// <summary>
/// Gets a workbook with 2 sheets("sheet1" and "sheet2") and with 2 rows in "sheet2":
/// <para>DateProperty StringProperty</para>
Expand Down Expand Up @@ -68,7 +66,5 @@ protected static IWorkbook WriteAndReadBack(IWorkbook workbook, string fileName

return WorkbookFactory.Create(fileName);
}

#endregion
}
}
3 changes: 3 additions & 0 deletions Npoi.Mapper/test/TestSetUp.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
using System;
using System.Diagnostics.CodeAnalysis;
using NUnit.Framework;

[assembly:ExcludeFromCodeCoverage]

namespace test
{
/// <summary>
Expand Down

0 comments on commit 0e3ed14

Please sign in to comment.