From b87380621aade81a6bf6ef2fbe2198ab5d65989e Mon Sep 17 00:00:00 2001 From: huynhloc-1110 <101441531+huynhloc-1110@users.noreply.github.com> Date: Tue, 13 Aug 2024 00:31:27 +0700 Subject: [PATCH] Fix CultureInfo being overridden by user settings `new CultureInfo(string name)` by default sets `useUserOverride` to true, which uses Windows user customized settings. This results in tests failed on some machines with customized date time format. Use `CultureInfo.GetCultureInfo(string name)` instead which gets the cached instance or create a new instance with `useUserOverride` set to false. --- .../.meta/Exemplar.cs | 2 +- .../BeautySalonGoesGlobalTests.cs | 2 +- .../BookingUpForBeautyTests.cs | 2 +- exercises/practice/ledger/.meta/Example.cs | 4 +- exercises/practice/ledger/Ledger.cs | 314 +++++++++--------- 5 files changed, 162 insertions(+), 162 deletions(-) diff --git a/exercises/concept/beauty-salon-goes-global/.meta/Exemplar.cs b/exercises/concept/beauty-salon-goes-global/.meta/Exemplar.cs index 338a2ef3fd..aef3d51db8 100644 --- a/exercises/concept/beauty-salon-goes-global/.meta/Exemplar.cs +++ b/exercises/concept/beauty-salon-goes-global/.meta/Exemplar.cs @@ -86,7 +86,7 @@ private static CultureInfo LocationToCulture(Location location) cultureId = "fr-FR"; break; } - return new CultureInfo(cultureId); + return CultureInfo.GetCultureInfo(cultureId); } private static string GetTimeZoneId(Location location) diff --git a/exercises/concept/beauty-salon-goes-global/BeautySalonGoesGlobalTests.cs b/exercises/concept/beauty-salon-goes-global/BeautySalonGoesGlobalTests.cs index bd8f76a4ec..3a3499bb60 100644 --- a/exercises/concept/beauty-salon-goes-global/BeautySalonGoesGlobalTests.cs +++ b/exercises/concept/beauty-salon-goes-global/BeautySalonGoesGlobalTests.cs @@ -10,7 +10,7 @@ public class BeautySalonGoesGlobalTests { public BeautySalonGoesGlobalTests() { - Thread.CurrentThread.CurrentCulture = new CultureInfo("en-US"); + Thread.CurrentThread.CurrentCulture = CultureInfo.GetCultureInfo("en-US"); } [Fact] diff --git a/exercises/concept/booking-up-for-beauty/BookingUpForBeautyTests.cs b/exercises/concept/booking-up-for-beauty/BookingUpForBeautyTests.cs index af7e44f660..eb959a4c72 100644 --- a/exercises/concept/booking-up-for-beauty/BookingUpForBeautyTests.cs +++ b/exercises/concept/booking-up-for-beauty/BookingUpForBeautyTests.cs @@ -8,7 +8,7 @@ public class BookingUpForBeautyTests { public BookingUpForBeautyTests() { - var enUsCulture = new CultureInfo("en-US"); + var enUsCulture = CultureInfo.GetCultureInfo("en-US"); Thread.CurrentThread.CurrentCulture = enUsCulture; Thread.CurrentThread.CurrentUICulture = enUsCulture; } diff --git a/exercises/practice/ledger/.meta/Example.cs b/exercises/practice/ledger/.meta/Example.cs index e4f5b3fcb1..05f6ffaee7 100644 --- a/exercises/practice/ledger/.meta/Example.cs +++ b/exercises/practice/ledger/.meta/Example.cs @@ -33,8 +33,8 @@ private static CultureInfo CultureInfo(string locale) { switch (locale) { - case "en-US": return new CultureInfo("en-US"); - case "nl-NL": return new CultureInfo("nl-NL"); + case "en-US": return CultureInfo.GetCultureInfo("en-US"); + case "nl-NL": return CultureInfo.GetCultureInfo("nl-NL"); default: throw new ArgumentException("Invalid locale"); } } diff --git a/exercises/practice/ledger/Ledger.cs b/exercises/practice/ledger/Ledger.cs index 1094a831a6..792f277e28 100644 --- a/exercises/practice/ledger/Ledger.cs +++ b/exercises/practice/ledger/Ledger.cs @@ -5,165 +5,165 @@ public class LedgerEntry { - public LedgerEntry(DateTime date, string desc, decimal chg) - { - Date = date; - Desc = desc; - Chg = chg; - } - - public DateTime Date { get; } - public string Desc { get; } - public decimal Chg { get; } + public LedgerEntry(DateTime date, string desc, decimal chg) + { + Date = date; + Desc = desc; + Chg = chg; + } + + public DateTime Date { get; } + public string Desc { get; } + public decimal Chg { get; } } public static class Ledger { - public static LedgerEntry CreateEntry(string date, string desc, int chng) - { - return new LedgerEntry(DateTime.Parse(date, CultureInfo.InvariantCulture), desc, chng / 100.0m); - } - - private static CultureInfo CreateCulture(string cur, string loc) - { - string curSymb = null; - int curNeg = 0; - string datPat = null; - - if (cur != "USD" && cur != "EUR") - { - throw new ArgumentException("Invalid currency"); - } - else - { - if (loc != "nl-NL" && loc != "en-US") - { - throw new ArgumentException("Invalid currency"); - } - - if (cur == "USD") - { - if (loc == "en-US") - { - curSymb = "$"; - datPat = "MM/dd/yyyy"; - } - else if (loc == "nl-NL") - { - curSymb = "$"; - curNeg = 12; - datPat = "dd/MM/yyyy"; - } - } - - if (cur == "EUR") - { - if (loc == "en-US") - { - curSymb = "€"; - datPat = "MM/dd/yyyy"; - } - else if (loc == "nl-NL") - { - curSymb = "€"; - curNeg = 12; - datPat = "dd/MM/yyyy"; - } - } - } - - var culture = new CultureInfo(loc); - culture.NumberFormat.CurrencySymbol = curSymb; - culture.NumberFormat.CurrencyNegativePattern = curNeg; - culture.DateTimeFormat.ShortDatePattern = datPat; - return culture; - } - - private static string PrintHead(string loc) - { - if (loc == "en-US") - { - return "Date | Description | Change "; - } - - else - { - if (loc == "nl-NL") - { - return "Datum | Omschrijving | Verandering "; - } - else - { - throw new ArgumentException("Invalid locale"); - } - } - } - - private static string Date(IFormatProvider culture, DateTime date) => date.ToString("d", culture); - - private static string Description(string desc) - { - if (desc.Length > 25) - { - var trunc = desc.Substring(0, 22); - trunc += "..."; - return trunc; - } - - return desc; - } - - private static string Change(IFormatProvider culture, decimal cgh) - { - return cgh < 0.0m ? cgh.ToString("C", culture) : cgh.ToString("C", culture) + " "; - } - - private static string PrintEntry(IFormatProvider culture, LedgerEntry entry) - { - var formatted = ""; - var date = Date(culture, entry.Date); - var description = Description(entry.Desc); - var change = Change(culture, entry.Chg); - - formatted += date; - formatted += " | "; - formatted += string.Format("{0,-25}", description); - formatted += " | "; - formatted += string.Format("{0,13}", change); - - return formatted; - } - - - private static IEnumerable sort(LedgerEntry[] entries) - { - var neg = entries.Where(e => e.Chg < 0).OrderBy(x => x.Date + "@" + x.Desc + "@" + x.Chg); - var post = entries.Where(e => e.Chg >= 0).OrderBy(x => x.Date + "@" + x.Desc + "@" + x.Chg); - - var result = new List(); - result.AddRange(neg); - result.AddRange(post); - - return result; - } - - public static string Format(string currency, string locale, LedgerEntry[] entries) - { - var formatted = ""; - formatted += PrintHead(locale); - - var culture = CreateCulture(currency, locale); - - if (entries.Length > 0) - { - var entriesForOutput = sort(entries); - - for (var i = 0; i < entriesForOutput.Count(); i++) - { - formatted += "\n" + PrintEntry(culture, entriesForOutput.Skip(i).First()); - } - } - - return formatted; - } + public static LedgerEntry CreateEntry(string date, string desc, int chng) + { + return new LedgerEntry(DateTime.Parse(date, CultureInfo.InvariantCulture), desc, chng / 100.0m); + } + + private static CultureInfo CreateCulture(string cur, string loc) + { + string curSymb = null; + int curNeg = 0; + string datPat = null; + + if (cur != "USD" && cur != "EUR") + { + throw new ArgumentException("Invalid currency"); + } + else + { + if (loc != "nl-NL" && loc != "en-US") + { + throw new ArgumentException("Invalid currency"); + } + + if (cur == "USD") + { + if (loc == "en-US") + { + curSymb = "$"; + datPat = "MM/dd/yyyy"; + } + else if (loc == "nl-NL") + { + curSymb = "$"; + curNeg = 12; + datPat = "dd/MM/yyyy"; + } + } + + if (cur == "EUR") + { + if (loc == "en-US") + { + curSymb = "€"; + datPat = "MM/dd/yyyy"; + } + else if (loc == "nl-NL") + { + curSymb = "€"; + curNeg = 12; + datPat = "dd/MM/yyyy"; + } + } + } + + var culture = CultureInfo.GetCultureInfo(loc); + culture.NumberFormat.CurrencySymbol = curSymb; + culture.NumberFormat.CurrencyNegativePattern = curNeg; + culture.DateTimeFormat.ShortDatePattern = datPat; + return culture; + } + + private static string PrintHead(string loc) + { + if (loc == "en-US") + { + return "Date | Description | Change "; + } + + else + { + if (loc == "nl-NL") + { + return "Datum | Omschrijving | Verandering "; + } + else + { + throw new ArgumentException("Invalid locale"); + } + } + } + + private static string Date(IFormatProvider culture, DateTime date) => date.ToString("d", culture); + + private static string Description(string desc) + { + if (desc.Length > 25) + { + var trunc = desc.Substring(0, 22); + trunc += "..."; + return trunc; + } + + return desc; + } + + private static string Change(IFormatProvider culture, decimal cgh) + { + return cgh < 0.0m ? cgh.ToString("C", culture) : cgh.ToString("C", culture) + " "; + } + + private static string PrintEntry(IFormatProvider culture, LedgerEntry entry) + { + var formatted = ""; + var date = Date(culture, entry.Date); + var description = Description(entry.Desc); + var change = Change(culture, entry.Chg); + + formatted += date; + formatted += " | "; + formatted += string.Format("{0,-25}", description); + formatted += " | "; + formatted += string.Format("{0,13}", change); + + return formatted; + } + + + private static IEnumerable sort(LedgerEntry[] entries) + { + var neg = entries.Where(e => e.Chg < 0).OrderBy(x => x.Date + "@" + x.Desc + "@" + x.Chg); + var post = entries.Where(e => e.Chg >= 0).OrderBy(x => x.Date + "@" + x.Desc + "@" + x.Chg); + + var result = new List(); + result.AddRange(neg); + result.AddRange(post); + + return result; + } + + public static string Format(string currency, string locale, LedgerEntry[] entries) + { + var formatted = ""; + formatted += PrintHead(locale); + + var culture = CreateCulture(currency, locale); + + if (entries.Length > 0) + { + var entriesForOutput = sort(entries); + + for (var i = 0; i < entriesForOutput.Count(); i++) + { + formatted += "\n" + PrintEntry(culture, entriesForOutput.Skip(i).First()); + } + } + + return formatted; + } }