Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 6 additions & 8 deletions Personnummer.Tests/CoordinationNumberTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -122,13 +122,12 @@ public void TestParseInvalidCn(PersonnummerData ssn)
}));
}

#if NET8_0_OR_GREATER
[Theory]
[ClassData(typeof(ValidCnDataProvider))]
public void TestAgeCn(PersonnummerData ssn)
{
var timeProvider = new TestTimeProvider();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we want to keep the TimeProvider, seeing its a dotnet implementation of what the Clock does and made for making code easier to test :)

Its a bit messy due to the Pragmas for DOTNET_8, but its a minor diff between netstandard/net8+ versions. And it's only really there to allow support for dotnet framework.

var localNow = timeProvider.GetLocalNow();
var clock = new TestClock();
var localNow = clock.GetNow();

int day = int.Parse(ssn.LongFormat.Substring(ssn.LongFormat.Length - 6, 2)) - 60;
string strDay = day < 10 ? $"0{day}" : day.ToString();
Expand All @@ -140,13 +139,12 @@ public void TestAgeCn(PersonnummerData ssn)
years--;
}

Assert.Equal(years, Personnummer.Parse(ssn.SeparatedLong, new Personnummer.Options { AllowCoordinationNumber = true, TimeProvider = timeProvider }).Age);
Assert.Equal(years, Personnummer.Parse(ssn.SeparatedFormat, new Personnummer.Options { AllowCoordinationNumber = true, TimeProvider = timeProvider }).Age);
Assert.Equal(years, Personnummer.Parse(ssn.LongFormat, new Personnummer.Options { AllowCoordinationNumber = true, TimeProvider = timeProvider }).Age);
Assert.Equal(years, Personnummer.Parse(ssn.SeparatedLong, new Personnummer.Options { AllowCoordinationNumber = true, Now = clock.GetNow }).Age);
Assert.Equal(years, Personnummer.Parse(ssn.SeparatedFormat, new Personnummer.Options { AllowCoordinationNumber = true, Now = clock.GetNow }).Age);
Assert.Equal(years, Personnummer.Parse(ssn.LongFormat, new Personnummer.Options { AllowCoordinationNumber = true, Now = clock.GetNow }).Age);
// Du to age not being possible to fetch from >100 year short format without separator, we aught to check this here.
Assert.Equal(years > 99 ? years - 100 : years, Personnummer.Parse(ssn.ShortFormat, new Personnummer.Options { AllowCoordinationNumber = true, TimeProvider = timeProvider }).Age);
Assert.Equal(years > 99 ? years - 100 : years, Personnummer.Parse(ssn.ShortFormat, new Personnummer.Options { AllowCoordinationNumber = true, Now = clock.GetNow }).Age);
}
#endif

[Theory]
[ClassData(typeof(ValidCnDataProvider))]
Expand Down
23 changes: 10 additions & 13 deletions Personnummer.Tests/PersonnummerTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -76,13 +76,12 @@ public void TestParseInvalid(PersonnummerData ssn)
}


#if NET8_0_OR_GREATER // Requires TimeProvider.
[Theory]
[ClassData(typeof(ValidSsnDataProvider))]
public void TestAge(PersonnummerData ssn)
{
var timeProvider = new TestTimeProvider();
var localNow = timeProvider.GetLocalNow();
var clock = new TestClock();
var localNow = clock.GetNow();
DateTime dt = DateTime.ParseExact(ssn.LongFormat.Substring(0, ssn.LongFormat.Length - 4), "yyyyMMdd", CultureInfo.InvariantCulture, DateTimeStyles.None);

var years = localNow.Year - dt.Year;
Expand All @@ -91,28 +90,26 @@ public void TestAge(PersonnummerData ssn)
years--;
}

Assert.Equal(years, Personnummer.Parse(ssn.SeparatedLong, new Personnummer.Options { AllowCoordinationNumber = false, TimeProvider = timeProvider }).Age);
Assert.Equal(years, Personnummer.Parse(ssn.SeparatedFormat, new Personnummer.Options { AllowCoordinationNumber = false, TimeProvider = timeProvider }).Age);
Assert.Equal(years, Personnummer.Parse(ssn.LongFormat, new Personnummer.Options { AllowCoordinationNumber = false, TimeProvider = timeProvider }).Age);
Assert.Equal(years, Personnummer.Parse(ssn.SeparatedLong, new Personnummer.Options { AllowCoordinationNumber = false, Now = clock.GetNow }).Age);
Assert.Equal(years, Personnummer.Parse(ssn.SeparatedFormat, new Personnummer.Options { AllowCoordinationNumber = false, Now = clock.GetNow }).Age);
Assert.Equal(years, Personnummer.Parse(ssn.LongFormat, new Personnummer.Options { AllowCoordinationNumber = false, Now = clock.GetNow }).Age);
// Du to age not being possible to fetch from >100 year short format without separator, we aught to check this here.
Assert.Equal(years > 99 ? years - 100 : years, Personnummer.Parse(ssn.ShortFormat, new Personnummer.Options { AllowCoordinationNumber = false, TimeProvider = timeProvider }).Age);
Assert.Equal(years > 99 ? years - 100 : years, Personnummer.Parse(ssn.ShortFormat, new Personnummer.Options { AllowCoordinationNumber = false, Now = clock.GetNow }).Age);
}

[Fact]
public void TestEdgeCasesAroundBirthday()
{
var timeProvider = new TestTimeProvider
var clock = new TestClock
{
Now = DateTimeOffset.Parse("2090-01-09 12:00")
};

Assert.Equal(10, new Personnummer("20800108-6670", new Personnummer.Options() {TimeProvider = timeProvider} ).Age); // Had birthday yesterday
Assert.Equal(10, new Personnummer("20800109-8287", new Personnummer.Options() {TimeProvider = timeProvider} ).Age); // Birthday today
Assert.Equal(9, new Personnummer("20800110-8516", new Personnummer.Options() {TimeProvider = timeProvider} ).Age); // Upcoming Birthday tomorrow
Assert.Equal(10, new Personnummer("20800108-6670", new Personnummer.Options() {Now = clock.GetNow} ).Age); // Had birthday yesterday
Assert.Equal(10, new Personnummer("20800109-8287", new Personnummer.Options() {Now = clock.GetNow} ).Age); // Birthday today
Assert.Equal(9, new Personnummer("20800110-8516", new Personnummer.Options() {Now = clock.GetNow} ).Age); // Upcoming Birthday tomorrow
}

#endif

[Theory]
[ClassData(typeof(ValidSsnDataProvider))]
public void TestFormat(PersonnummerData ssn)
Expand Down
16 changes: 16 additions & 0 deletions Personnummer.Tests/TestClock.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
using System;

namespace Personnummer.Tests;

public sealed class TestClock
{
public DateTimeOffset Now { get; set; } = new(
new DateTime(2025, 1, 1, 0, 0, 1),
TimeSpan.Zero
);

public DateTimeOffset GetNow()
{
return Now;
}
}
26 changes: 0 additions & 26 deletions Personnummer.Tests/TestTimeProvider.cs

This file was deleted.

15 changes: 4 additions & 11 deletions Personnummer/Personnummer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ public Options()
{
AllowInterimNumber = false;
AllowCoordinationNumber = true;
Now = () => DateTimeOffset.Now;
}

/// <summary>
Expand All @@ -25,20 +26,12 @@ public Options()
/// </summary>
public bool AllowInterimNumber { get; set; } = false;

#if (NET8_0_OR_GREATER)
/// <summary>
/// TimeProvider to use in calculations which are time dependent.<br/>
/// Uses `GetLocalNow` method.
/// <remarks>
/// Defaults to System provider.
/// </remarks>
/// Function to get the current date and time.
/// </summary>
public TimeProvider TimeProvider { private get; init; } = TimeProvider.System;
public Func<DateTimeOffset> Now { get; set; }

internal DateTimeOffset DateTimeNow => TimeProvider.GetLocalNow();
#else
internal DateTimeOffset DateTimeNow => DateTimeOffset.Now;
#endif
internal DateTimeOffset DateTimeNow => Now();
}

#region Fields and Properties
Expand Down
2 changes: 1 addition & 1 deletion Personnummer/Personnummer.csproj
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFrameworks>netstandard2.1;net48;net10.0;net8.0;net9.0</TargetFrameworks>
<Company>Personnummer</Company>
<Authors>Johannes Tegnér, Personnummer Contributors</Authors>
<Description>Verify Swedish personal identity numbers.</Description>
Expand All @@ -19,6 +18,7 @@
<PackageIcon>icon.png</PackageIcon>
<PackageReadmeFile>Readme.md</PackageReadmeFile>
<IncludeDocumentationProjectOutputGroup>true</IncludeDocumentationProjectOutputGroup>
<TargetFramework>netstandard2.1</TargetFramework>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we might want to directly target some of the versions. Will have to think about this one and if there are issues with just targeting netstandard...

It would ofc make it easier code-wize, but unsure if its the best way.

</PropertyGroup>

<ItemGroup>
Expand Down
Loading