Skip to content

Commit

Permalink
Added mappings for DateOnly and TimeOnly for net 6+ (#1168)
Browse files Browse the repository at this point in the history
  • Loading branch information
david-driscoll authored Jun 28, 2022
1 parent 1527e68 commit 01507c3
Show file tree
Hide file tree
Showing 5 changed files with 75 additions and 42 deletions.
1 change: 1 addition & 0 deletions .nuke/build.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
"AppVeyor",
"AzurePipelines",
"Bamboo",
"Bitbucket",
"Bitrise",
"GitHubActions",
"GitLab",
Expand Down
24 changes: 15 additions & 9 deletions src/Mapping/Profiles/NodaTimeProfile.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using AutoMapper;
using NodaTime;
using NodaTime.Extensions;
using NodaTime.Text;

namespace Rocket.Surgery.LaunchPad.Mapping.Profiles;
Expand Down Expand Up @@ -93,28 +94,33 @@ private void CreateMappingsForInstantConvertor()

private void CreateMappingsForLocalDateConverter()
{
CreateMap<DateTime, LocalDate>().ConvertUsing(source => LocalDateTime.FromDateTime(source).Date);
CreateMap<DateTime?, LocalDate?>().ConvertUsing(source => source.HasValue ? LocalDateTime.FromDateTime(source.Value).Date : default(LocalDate?));
CreateMap<DateTime, LocalDate>().ConvertUsing(source => LocalDate.FromDateTime(source));
CreateMap<DateTime?, LocalDate?>().ConvertUsing(source => source.HasValue ? LocalDate.FromDateTime(source.Value) : default(LocalDate?));
CreateMap<LocalDate, DateTime>().ConvertUsing(source => source.AtMidnight().ToDateTimeUnspecified());
CreateMap<LocalDate?, DateTime?>().ConvertUsing(source => source.HasValue ? source.Value.AtMidnight().ToDateTimeUnspecified() : default(DateTime?));
#if NET6_0_OR_GREATER
CreateMap<DateOnly, LocalDate>().ConvertUsing(source => LocalDate.FromDateOnly(source));
CreateMap<DateOnly?, LocalDate?>().ConvertUsing(source => source.HasValue ? LocalDate.FromDateOnly(source.Value) : default(LocalDate?));
CreateMap<LocalDate, DateOnly>().ConvertUsing(source => source.ToDateOnly());
CreateMap<LocalDate?, DateOnly?>().ConvertUsing(source => source.HasValue ? source.Value.ToDateOnly() : default(DateOnly?));
#endif
}

private void CreateMappingsForLocalDateTimeConverter()
{
CreateMap<DateTime, LocalDateTime>().ConvertUsing(source => LocalDateTime.FromDateTime(source));
CreateMap<DateTime?, LocalDateTime?>().ConvertUsing(source => source.HasValue ? LocalDateTime.FromDateTime(source.Value) : default(LocalDateTime?));
CreateMap<LocalDateTime, DateTime>().ConvertUsing(source => source.ToDateTimeUnspecified());
CreateMap<LocalDateTime?, DateTime?>().ConvertUsing(source => source.HasValue ? source.Value.ToDateTimeUnspecified() : default(DateTime?));
}

private void CreateMappingsForLocalTimeConverter()
{
CreateMap<DateTime, LocalTime>().ConvertUsing(source => LocalDateTime.FromDateTime(source).TimeOfDay);
CreateMap<DateTime?, LocalTime?>().ConvertUsing(source => source.HasValue ? LocalDateTime.FromDateTime(source.Value).TimeOfDay : default(LocalTime?));
CreateMap<LocalTime, DateTime>().ConvertUsing(source => source.On(new LocalDate(1, 1, 1)).ToDateTimeUnspecified());
#if NET6_0_OR_GREATER
CreateMap<TimeOnly, LocalTime>().ConvertUsing(source => LocalTime.FromTimeOnly(source));
CreateMap<TimeOnly?, LocalTime?>().ConvertUsing(source => source.HasValue ? LocalTime.FromTimeOnly(source.Value) : default(LocalTime?));
CreateMap<LocalTime, TimeOnly>().ConvertUsing(source => source.ToTimeOnly());
CreateMap<LocalTime?, TimeOnly?>().ConvertUsing(source => source.HasValue ? source.Value.ToTimeOnly() : default(TimeOnly?));
#endif
CreateMap<LocalTime, TimeSpan>().ConvertUsing(source => new TimeSpan(source.TickOfDay));
CreateMap<LocalTime?, DateTime?>()
.ConvertUsing(source => source.HasValue ? source.Value.On(new LocalDate(1, 1, 1)).ToDateTimeUnspecified() : default(DateTime?));
CreateMap<LocalTime?, TimeSpan?>().ConvertUsing(source => source.HasValue ? new TimeSpan(source.Value.TickOfDay) : default(TimeSpan?));
CreateMap<TimeSpan, LocalTime>().ConvertUsing(source => LocalTime.FromTicksSinceMidnight(source.Ticks));
CreateMap<TimeSpan?, LocalTime?>().ConvertUsing(source => source.HasValue ? LocalTime.FromTicksSinceMidnight(source.Value.Ticks) : default(LocalTime?));
Expand Down
6 changes: 6 additions & 0 deletions test/Extensions.Tests/Mapping/LocalDateTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,12 @@ public override IEnumerable<Type> GetTypeConverters()
yield return typeof(ITypeConverter<LocalDate?, DateTime?>);
yield return typeof(ITypeConverter<DateTime, LocalDate>);
yield return typeof(ITypeConverter<DateTime?, LocalDate?>);
#if NET6_0_OR_GREATER
yield return typeof(ITypeConverter<LocalDate, DateOnly>);
yield return typeof(ITypeConverter<LocalDate?, DateOnly?>);
yield return typeof(ITypeConverter<DateOnly, LocalDate>);
yield return typeof(ITypeConverter<DateOnly?, LocalDate?>);
#endif
}
}
}
75 changes: 42 additions & 33 deletions test/Extensions.Tests/Mapping/LocalTimeTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
using AutoMapper;
using FluentAssertions;
using NodaTime;
using NodaTime.Extensions;
using Xunit;
using Xunit.Abstractions;

Expand Down Expand Up @@ -43,34 +44,6 @@ public void MapsTo_DateTime()
result.Should().Be(new LocalTime(502 / 60, 502 % 60));
}

[Fact]
public void MapsFrom_DateTimeOffset()
{
var mapper = Config.CreateMapper();

var foo = new Foo1
{
Bar = LocalTime.FromTicksSinceMidnight(10000)
};

var result = mapper.Map<Foo5>(foo).Bar;
result.Should().Be(foo.Bar.On(new LocalDate(1, 1, 1)).ToDateTimeUnspecified());
}

[Fact]
public void MapsTo_DateTimeOffset()
{
var mapper = Config.CreateMapper();

var foo = new Foo5
{
Bar = DateTime.Now
};

var result = mapper.Map<Foo1>(foo).Bar;
result.Should().Be(LocalDateTime.FromDateTime(foo.Bar).TimeOfDay);
}

public LocalTimeTests(ITestOutputHelper testOutputHelper) : base(testOutputHelper)
{
}
Expand Down Expand Up @@ -105,7 +78,9 @@ protected override void Configure(IMapperConfigurationExpression expression)
}

expression.CreateMap<Foo1, Foo3>().ReverseMap();
#if NET6_0_OR_GREATER
expression.CreateMap<Foo1, Foo5>().ReverseMap();
#endif
}

private class Foo1
Expand All @@ -118,10 +93,12 @@ private class Foo3
public TimeSpan Bar { get; set; }
}

#if NET6_0_OR_GREATER
private class Foo5
{
public DateTime Bar { get; set; }
public TimeOnly Bar { get; set; }
}
#endif

public class Converters : TypeConverterFactory
{
Expand All @@ -131,10 +108,42 @@ public override IEnumerable<Type> GetTypeConverters()
yield return typeof(ITypeConverter<LocalTime?, TimeSpan?>);
yield return typeof(ITypeConverter<TimeSpan, LocalTime>);
yield return typeof(ITypeConverter<TimeSpan?, LocalTime?>);
yield return typeof(ITypeConverter<LocalTime, DateTime>);
yield return typeof(ITypeConverter<LocalTime?, DateTime?>);
yield return typeof(ITypeConverter<DateTime, LocalTime>);
yield return typeof(ITypeConverter<DateTime?, LocalTime?>);
#if NET6_0_OR_GREATER
yield return typeof(ITypeConverter<LocalTime, TimeOnly>);
yield return typeof(ITypeConverter<LocalTime?, TimeOnly?>);
yield return typeof(ITypeConverter<TimeOnly, LocalTime>);
yield return typeof(ITypeConverter<TimeOnly?, LocalTime?>);
#endif
}
}

#if NET6_0_OR_GREATER
[Fact]
public void MapsFrom_DateTimeOffset()
{
var mapper = Config.CreateMapper();

var foo = new Foo1
{
Bar = LocalTime.FromTicksSinceMidnight(10000)
};

var result = mapper.Map<Foo5>(foo).Bar;
result.Should().Be(foo.Bar.ToTimeOnly());
}

[Fact]
public void MapsTo_DateTimeOffset()
{
var mapper = Config.CreateMapper();

var foo = new Foo5
{
Bar = TimeOnly.FromDateTime(DateTime.Now)
};

var result = mapper.Map<Foo1>(foo).Bar;
result.Should().Be(foo.Bar.ToLocalTime());
}
#endif
}
11 changes: 11 additions & 0 deletions test/Extensions.Tests/Mapping/TypeConverterTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,17 @@ private static object GetRandomValue(Type type)
{
return Faker.Date.RecentOffset();
}
#if NET6_0_OR_GREATER
if (type == typeof(DateOnly))
{
return Faker.Date.RecentDateOnly();
}

if (type == typeof(TimeOnly))
{
return Faker.Date.RecentTimeOnly();
}
#endif

throw new NotSupportedException($"type {type.FullName} is not supported");
}
Expand Down

0 comments on commit 01507c3

Please sign in to comment.