Skip to content

Commit

Permalink
add ability to overwrite a currency with a combination of CultureInfo…
Browse files Browse the repository at this point in the history
… and RegionInfo
  • Loading branch information
dgg committed Jul 3, 2024
1 parent d3d4915 commit 60906d5
Show file tree
Hide file tree
Showing 2 changed files with 75 additions and 7 deletions.
39 changes: 39 additions & 0 deletions src/NMoneys/CurrencyConfiguration.cs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
using System.Globalization;

namespace NMoneys;

/// <summary>
Expand Down Expand Up @@ -52,4 +54,41 @@ public record CurrencyConfiguration()
/// Override <see cref="Currency.Entity"/>.
/// </summary>
public ValueTuple<ushort?, string?> Reference { get; init; } = (null, null);

/// <summary>
/// Creates a <see cref="Currency"/> configuration override with the data of the provided <paramref name="culture"/>
/// and its corresponding <see cref="RegionInfo"/>.
/// </summary>
/// <param name="culture">Instance with the overriding information (<see cref="CultureInfo.NumberFormat"/> "currency" properties).</param>
/// <param name="isObsolete">Whether the corresponding override is considered obsolete (<c>false</c> by default).</param>
/// <returns>An instance with the overriding data.</returns>
public static CurrencyConfiguration From(CultureInfo culture, bool isObsolete = false) =>
From(culture, new RegionInfo(culture.Name), isObsolete);

/// <summary>
/// Creates a <see cref="Currency"/> configuration override with the data of the provided <paramref name="culture"/>
/// and <paramref name="region"/>.
/// </summary>
/// <param name="culture">Instance with the overriding information (<see cref="CultureInfo.NumberFormat"/> "currency" properties).</param>
/// <param name="region">Instance with the overriding information (currency English and native names).</param>
/// <param name="isObsolete">Whether the corresponding override is considered obsolete (<c>false</c> by default).</param>
/// <returns>An instance with the overriding data.</returns>
public static CurrencyConfiguration From(CultureInfo culture, RegionInfo region, bool isObsolete = false)
{
NumberFormatInfo nf = culture.NumberFormat;
CurrencyConfiguration configuration = new()
{
NativeName = region.CurrencyNativeName,
EnglishName = region.CurrencyEnglishName,
Symbol = nf.CurrencySymbol,
SignificantDecimalDigits = (byte)nf.CurrencyDecimalDigits,
DecimalSeparator = nf.CurrencyDecimalSeparator,
GroupSeparator = nf.CurrencyGroupSeparator,
GroupSizes = nf.CurrencyGroupSizes.Select(s => (byte)s).ToArray(),
PositivePattern = (byte)nf.CurrencyPositivePattern,
NegativePattern = (byte)nf.CurrencyNegativePattern,
IsObsolete = isObsolete
};
return configuration;
}
}
43 changes: 36 additions & 7 deletions tests/NMoneys.Tests/CurrencyTester.Configuration.cs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
using System.Globalization;

namespace NMoneys.Tests;

public partial class CurrencyTester
Expand All @@ -6,20 +8,47 @@ public partial class CurrencyTester
public void Configure_Single_OverridesInformationSubset()
{
string englishName = "override";
Currency.Configure(CurrencyIsoCode.XXX, new CurrencyConfiguration{ EnglishName = englishName});
Currency.Configure(CurrencyIsoCode.XXX, new CurrencyConfiguration { EnglishName = englishName });
Currency overriden = Currency.Get(CurrencyIsoCode.XXX);
Assert.That(overriden.EnglishName, Is.EqualTo(englishName).And.Not.EqualTo(overriden.NativeName));
}

[Test, Explicit]
public void Configure_SingleCulture_OverridesInformationSubset()
{
CultureInfo paraguaySpanish = CultureInfo.GetCultureInfo("es-PY");

Currency.Configure(CurrencyIsoCode.PYG, CurrencyConfiguration.From(paraguaySpanish));
Currency overriden = Currency.Get(CurrencyIsoCode.PYG);
Assert.That(overriden.Symbol, Is.EqualTo(paraguaySpanish.NumberFormat.CurrencySymbol).And
.Not.EqualTo(@"₲"));
}

[Test, Explicit]
public void Configure_CultureAndRegion_OverridesInformationSubset()
{
CultureInfo somali = CultureInfo.GetCultureInfo("so-SO");
RegionInfo djibuti = new("so-DJ");

Currency.Configure(CurrencyIsoCode.SOS, CurrencyConfiguration.From(somali, djibuti));
Currency overriden = Currency.Get(CurrencyIsoCode.SOS);
// according to .NET, there are no decimals in shillings, but according to ISO there actually are
// (although inflation turns them useless and are not in the denominations)
Assert.That(overriden.SignificantDecimalDigits, Is.EqualTo(0).And
.Not.EqualTo(2));
// even though somali is spoken in Djibuti, they do not have "shillings", but "francs"
Assert.That(overriden.EnglishName, Does.Contain("Franc").And
.Not.Contains("Shilling"));
}

[Test, Explicit]
public void Configure_Multiple_OverridesInformationSubset()
{
string englishName = "override";
Currency.Configure(new []
{
(CurrencyIsoCode.XXX, new CurrencyConfiguration{ EnglishName = englishName}),
(CurrencyIsoCode.XTS, new CurrencyConfiguration{ EnglishName = englishName})
});
Currency.Configure([
(CurrencyIsoCode.XXX, new CurrencyConfiguration { EnglishName = englishName }),
(CurrencyIsoCode.XTS, new CurrencyConfiguration { EnglishName = englishName })
]);
Currency xxx = Currency.Get(CurrencyIsoCode.XXX);
Assert.That(xxx.EnglishName, Is.EqualTo(englishName).And.Not.EqualTo(xxx.NativeName));
Currency xts = Currency.Get(CurrencyIsoCode.XTS);
Expand All @@ -31,7 +60,7 @@ public void Configure_AfterInitialization_Exception()
{
Currency xxx = Currency.Get(CurrencyIsoCode.XXX); // initializes the currency

Assert.That(()=>Currency.Configure(CurrencyIsoCode.XXX, new CurrencyConfiguration()),
Assert.That(() => Currency.Configure(CurrencyIsoCode.XXX, new CurrencyConfiguration()),
Throws.InstanceOf<InitializedCurrencyException>());
}
}

0 comments on commit 60906d5

Please sign in to comment.