Skip to content

Commit

Permalink
Fix CultureInfo being overridden by user settings (#2296)
Browse files Browse the repository at this point in the history
* 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.

* Fix GetCultureInfo breaking Ledger exercise

Ledger exercise originally wants a mutable CultureInfo instance to edit
its format. `CultureInfo.GetCultureInfo`` instead return a read-only
instance. Thus, we just call `new CultureInfo(loc, false)` to not use
windows setting.
  • Loading branch information
huynhloc-1110 authored Aug 13, 2024
1 parent 7f09e41 commit 505166a
Show file tree
Hide file tree
Showing 5 changed files with 162 additions and 162 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ public class BeautySalonGoesGlobalTests
{
public BeautySalonGoesGlobalTests()
{
Thread.CurrentThread.CurrentCulture = new CultureInfo("en-US");
Thread.CurrentThread.CurrentCulture = CultureInfo.GetCultureInfo("en-US");
}

[Fact]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down
4 changes: 2 additions & 2 deletions exercises/practice/ledger/.meta/Example.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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 new CultureInfo("en-US", false);
case "nl-NL": return new CultureInfo("nl-NL", false);
default: throw new ArgumentException("Invalid locale");
}
}
Expand Down
314 changes: 157 additions & 157 deletions exercises/practice/ledger/Ledger.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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<LedgerEntry> 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<LedgerEntry>();
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 = new CultureInfo(loc, false);
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<LedgerEntry> 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<LedgerEntry>();
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;
}
}

0 comments on commit 505166a

Please sign in to comment.