From d2f021bb5ef0db82b102bacced919dd4e84c0b76 Mon Sep 17 00:00:00 2001 From: Kristina M Date: Fri, 24 Jan 2025 11:28:37 +0100 Subject: [PATCH] Added Czech culture Added Czech (cs-CZ) holiday strategy and natural time strategy, including tests. --- .../CS_CZNaturalTimeStrategy.cs | 92 +++++++++ .../CultureStrategies/CS_CZHolidayStrategy.cs | 187 ++++++++++++++++++ .../CsCzHolidaysTests.cs | 57 ++++++ .../CzechNaturalTimeTests.cs | 151 ++++++++++++++ 4 files changed, 487 insertions(+) create mode 100644 src/DateTimeExtensions/NaturalText/CultureStrategies/CS_CZNaturalTimeStrategy.cs create mode 100644 src/DateTimeExtensions/WorkingDays/CultureStrategies/CS_CZHolidayStrategy.cs create mode 100644 tests/DateTimeExtensions.Tests/CsCzHolidaysTests.cs create mode 100644 tests/DateTimeExtensions.Tests/CzechNaturalTimeTests.cs diff --git a/src/DateTimeExtensions/NaturalText/CultureStrategies/CS_CZNaturalTimeStrategy.cs b/src/DateTimeExtensions/NaturalText/CultureStrategies/CS_CZNaturalTimeStrategy.cs new file mode 100644 index 00000000..5a5cfa50 --- /dev/null +++ b/src/DateTimeExtensions/NaturalText/CultureStrategies/CS_CZNaturalTimeStrategy.cs @@ -0,0 +1,92 @@ +using DateTimeExtensions.Common; +using System; + +namespace DateTimeExtensions.NaturalText.CultureStrategies +{ + [Locale("cs-CZ")] + public class CS_CZNaturalTimeStrategy : NaturalTimeStrategyBase + { + protected override string YearText + { + get { return "rok"; } + } + + protected override string MonthText + { + get { return "měsíc"; } + } + + protected override string DayText + { + get { return "den"; } + } + + protected override string HourText + { + get { return "hodina"; } + } + + protected override string MinuteText + { + get { return "minuta"; } + } + + protected override string SecondText + { + get { return "vteřina"; } + } + + protected override string Pluralize(string text, int value) + { + if (text.Equals("rok", StringComparison.OrdinalIgnoreCase)) + { + if (value < 5) + { + return "roky"; + } + return "let"; + } + if (text.Equals("měsíc", StringComparison.OrdinalIgnoreCase)) + { + if (value < 5) + { + return "měsíce"; + } + return "měsíců"; + } + if (text.Equals("den", StringComparison.OrdinalIgnoreCase)) + { + if (value < 5) + { + return "dny"; + } + return "dnů"; + } + if (text.Equals("hodina", StringComparison.OrdinalIgnoreCase)) + { + if (value < 5) + { + return "hodiny"; + } + return "hodin"; + } + if (text.Equals("minuta", StringComparison.OrdinalIgnoreCase)) + { + if (value < 5) + { + return "minuty"; + } + return "minut"; + } + if (text.Equals("vteřina", StringComparison.OrdinalIgnoreCase)) + { + if (value < 5) + { + return "vteřiny"; + } + return "vteřin"; + } + return text; + } + } +} diff --git a/src/DateTimeExtensions/WorkingDays/CultureStrategies/CS_CZHolidayStrategy.cs b/src/DateTimeExtensions/WorkingDays/CultureStrategies/CS_CZHolidayStrategy.cs new file mode 100644 index 00000000..110537d9 --- /dev/null +++ b/src/DateTimeExtensions/WorkingDays/CultureStrategies/CS_CZHolidayStrategy.cs @@ -0,0 +1,187 @@ +using DateTimeExtensions.Common; + +namespace DateTimeExtensions.WorkingDays.CultureStrategies +{ + [Locale("cs-CZ")] + public class CS_CZHolidayStrategy : HolidayStrategyBase, IHolidayStrategy + { + public CS_CZHolidayStrategy() + { + // January 1 has two holidays + this.InnerHolidays.Add(NewYearAndRestorationOfIndependence); + // Good Friday has been a holiday since 2016. + this.InnerHolidays.Add(GoodFridayCzechia); + this.InnerHolidays.Add(ChristianHolidays.EasterMonday); + this.InnerHolidays.Add(LabourDay); + this.InnerHolidays.Add(VictoryDay); + this.InnerHolidays.Add(CyrilAndMethodiusDay); + this.InnerHolidays.Add(JanHusDay); + this.InnerHolidays.Add(StatehoodDay); + this.InnerHolidays.Add(CzechoslovakIndependenceDay); + this.InnerHolidays.Add(FreedomAndDemocracyAndStudentsDay); + // The main Christmas holiday is on December 24 while the 25 and 26 are also bank holidays. + this.InnerHolidays.Add(ChristmasEve); + this.InnerHolidays.Add(FirstChristmasDay); + this.InnerHolidays.Add(SecondChristmasDay); + } + + private static Holiday restorationOfIndependenceDay; + public static Holiday NewYearAndRestorationOfIndependence + { + get + { + if (restorationOfIndependenceDay == null) + { + restorationOfIndependenceDay = new FixedHoliday( + "New Year's Day, Restoration Day of the Independent Czech State", 1, 1); + } + return restorationOfIndependenceDay; + } + } + + private static Holiday goodFridayYearDependant; + public static Holiday GoodFridayCzechia + { + get + { + if (goodFridayYearDependant == null) + { + goodFridayYearDependant = new YearDependantHoliday( + year => year > 2015, ChristianHolidays.GoodFriday); + } + return goodFridayYearDependant; + } + } + + private static Holiday labourDay; + public static Holiday LabourDay + { + get + { + if (labourDay == null) + { + labourDay = new FixedHoliday("Labour Day", 5, 1); + } + return labourDay; + } + } + + private static Holiday victoryDay; + public static Holiday VictoryDay + { + get + { + if (victoryDay == null) + { + victoryDay = new FixedHoliday("Victory Day", 5, 8); + } + return victoryDay; + } + } + + private static Holiday cyrilAndMethodiusDay; + public static Holiday CyrilAndMethodiusDay + { + get + { + if (cyrilAndMethodiusDay == null) + { + cyrilAndMethodiusDay = new FixedHoliday("Saints Cyril and Methodius Day", 7, 5); + } + return cyrilAndMethodiusDay; + } + } + + private static Holiday janHusDay; + public static Holiday JanHusDay + { + get + { + if (janHusDay == null) + { + janHusDay = new FixedHoliday("Jan Hus Day", 7, 6); + } + return janHusDay; + } + } + + private static Holiday statehoodDay; + public static Holiday StatehoodDay + { + get + { + if (statehoodDay == null) + { + statehoodDay = new FixedHoliday("Czech Statehood Day", 9, 28); + } + return statehoodDay; + } + } + + private static Holiday czechoslovakIndependenceDay; + public static Holiday CzechoslovakIndependenceDay + { + get + { + if (czechoslovakIndependenceDay == null) + { + czechoslovakIndependenceDay = new FixedHoliday("Independent Czechoslovak State Day", 10, 28); + } + return czechoslovakIndependenceDay; + } + } + + private static Holiday freedomAndDemocracyDay; + public static Holiday FreedomAndDemocracyAndStudentsDay + { + get + { + if (freedomAndDemocracyDay == null) + { + freedomAndDemocracyDay = new FixedHoliday( + "Struggle for Freedom and Democracy Day and International Students' Day", 11, 17); + } + return freedomAndDemocracyDay; + } + } + + private static Holiday christmasEve; + public static Holiday ChristmasEve + { + get + { + if (christmasEve == null) + { + christmasEve = new FixedHoliday("Christmas Eve", 12, 24); + } + return christmasEve; + } + } + + private static Holiday firstChristmasDay; + public static Holiday FirstChristmasDay + { + get + { + if (firstChristmasDay == null) + { + firstChristmasDay = new FixedHoliday("1st Christmas Day", 12, 25); + } + return firstChristmasDay; + } + } + + private static Holiday secondChristmasDay; + public static Holiday SecondChristmasDay + { + get + { + if (secondChristmasDay == null) + { + secondChristmasDay = new FixedHoliday("2nd Christmas Day", 12, 26); + } + return secondChristmasDay; + } + } + } +} diff --git a/tests/DateTimeExtensions.Tests/CsCzHolidaysTests.cs b/tests/DateTimeExtensions.Tests/CsCzHolidaysTests.cs new file mode 100644 index 00000000..48a79a5f --- /dev/null +++ b/tests/DateTimeExtensions.Tests/CsCzHolidaysTests.cs @@ -0,0 +1,57 @@ +using DateTimeExtensions.WorkingDays; +using NUnit.Framework; +using System; +using System.Linq; + +namespace DateTimeExtensions.Tests +{ + [TestFixture] + public class CsCzHolidaysTests + { + private WorkingDayCultureInfo dateTimeCulture = new WorkingDayCultureInfo("cs-CZ"); + + [Test] + public void Czechia_Has_13_HolidayDays() + { + Assert.That(dateTimeCulture.Holidays.Count(), Is.EqualTo(13)); + } + + [Test] + [TestCase(2016)] + [TestCase(2025)] + [TestCase(2031)] + public void Good_Friday_Is_A_Holiday_From_2016(int year) + { + DateTime goodFriday = ChristianHolidays.GoodFriday.GetInstance(year).Value; + Assert.That(goodFriday.IsHoliday(), Is.True); + } + + [Test] + [TestCase(2015)] + [TestCase(2003)] + [TestCase(1996)] + public void Good_Friday_Is_Not_A_Holiday_Before_2016(int year) + { + DateTime goodFriday = ChristianHolidays.GoodFriday.GetInstance(year).Value; + Assert.That(goodFriday.IsWorkingDay(), Is.True); + } + + [Test] + [TestCase(2015, 1, 1)] + [TestCase(2003, 5, 1)] + [TestCase(1996, 5, 8)] + [TestCase(1998, 7, 5)] + [TestCase(1994, 7, 6)] + [TestCase(1996, 9, 28)] + [TestCase(2005, 10, 28)] + [TestCase(2028, 11, 17)] + [TestCase(2001, 12, 24)] + [TestCase(2011, 12, 25)] + [TestCase(2025, 12, 26)] + public void Dates_Are_Correctly_Identified_As_Specific_Czech_Holidays(int year, int month, int day) + { + DateTime holiday = new(year, month, day); + Assert.That(holiday.IsHoliday(), Is.True); + } + } +} diff --git a/tests/DateTimeExtensions.Tests/CzechNaturalTimeTests.cs b/tests/DateTimeExtensions.Tests/CzechNaturalTimeTests.cs new file mode 100644 index 00000000..a9e97453 --- /dev/null +++ b/tests/DateTimeExtensions.Tests/CzechNaturalTimeTests.cs @@ -0,0 +1,151 @@ +using DateTimeExtensions.NaturalText; +using NUnit.Framework; +using System; + +namespace DateTimeExtensions.Tests +{ + [TestFixture] + public class CzechNaturalTimeTests + { + private NaturalTextCultureInfo czechTextCulture = new NaturalTextCultureInfo("cs-CZ"); + private DateTime fromTime = new DateTime(2025, 1, 23, 5, 21, 10); + + [Test] + public void Can_Tranlate_To_Natural_Text_Czech() + { + var toTime = fromTime.AddHours(2).AddMinutes(45); + + var actualText = fromTime.ToNaturalText(toTime, false, czechTextCulture); + + Assert.IsNotNull(actualText); + Assert.IsNotEmpty(actualText); + Assert.That(actualText, Is.EqualTo("2 hodiny")); + } + + [Test] + public void Can_Tranlate_To_Natural_Text_Rounded_Czech() + { + var toTime = fromTime.AddHours(2).AddMinutes(45); + + var actualText = fromTime.ToNaturalText(toTime, true, czechTextCulture); + + Assert.IsNotNull(actualText); + Assert.IsNotEmpty(actualText); + Assert.That(actualText, Is.EqualTo("3 hodiny")); + } + + + [Test] + public void Can_Tranlate_To_Exact_Natural_Text_Czech() + { + var toTime = fromTime.AddHours(2).AddMinutes(30); + + var actualText = fromTime.ToExactNaturalText(toTime, czechTextCulture); + + Assert.IsNotNull(actualText); + Assert.IsNotEmpty(actualText); + Assert.That(actualText, Is.EqualTo("2 hodiny, 30 minut")); + } + + [Test] + [TestCase(1, "1 rok")] + [TestCase(2, "2 roky")] + [TestCase(3, "3 roky")] + [TestCase(4, "4 roky")] + [TestCase(5, "5 let")] + [TestCase(12, "12 let")] + [TestCase(7, "7 let")] + public void Correct_Form_Of_Year_In_Czech(int years, string expectedText) + { + var toTime = fromTime.AddYears(years); + var actualText = fromTime.ToExactNaturalText(toTime, czechTextCulture); + Assert.That(actualText, Is.EqualTo(expectedText)); + } + + [Test] + [TestCase(1, "1 měsíc")] + [TestCase(2, "2 měsíce")] + [TestCase(3, "3 měsíce")] + [TestCase(4, "4 měsíce")] + [TestCase(5, "5 měsíců")] + [TestCase(11, "11 měsíců")] + [TestCase(7, "7 měsíců")] + public void Correct_Form_Of_Month_In_Czech(int months, string expectedText) + { + var toTime = fromTime.AddMonths(months); + var actualText = fromTime.ToExactNaturalText(toTime, czechTextCulture); + Assert.That(actualText, Is.EqualTo(expectedText)); + } + + [Test] + [TestCase(1, "1 den")] + [TestCase(2, "2 dny")] + [TestCase(3, "3 dny")] + [TestCase(4, "4 dny")] + [TestCase(5, "5 dnů")] + [TestCase(12, "12 dnů")] + [TestCase(7, "7 dnů")] + public void Correct_Form_Of_Day_In_Czech(int days, string expectedText) + { + var toTime = fromTime.AddDays(days); + var actualText = fromTime.ToExactNaturalText(toTime, czechTextCulture); + Assert.That(actualText, Is.EqualTo(expectedText)); + } + + [Test] + [TestCase(1, "1 hodina")] + [TestCase(2, "2 hodiny")] + [TestCase(3, "3 hodiny")] + [TestCase(4, "4 hodiny")] + [TestCase(5, "5 hodin")] + [TestCase(12, "12 hodin")] + [TestCase(7, "7 hodin")] + public void Correct_Form_Of_Hour_In_Czech(int hours, string expectedText) + { + var toTime = fromTime.AddHours(hours); + var actualText = fromTime.ToExactNaturalText(toTime, czechTextCulture); + Assert.That(actualText, Is.EqualTo(expectedText)); + } + + [Test] + [TestCase(1, "1 minuta")] + [TestCase(2, "2 minuty")] + [TestCase(3, "3 minuty")] + [TestCase(4, "4 minuty")] + [TestCase(5, "5 minut")] + [TestCase(12, "12 minut")] + [TestCase(7, "7 minut")] + public void Correct_Form_Of_Minute_In_Czech(int minutes, string expectedText) + { + var toTime = fromTime.AddMinutes(minutes); + var actualText = fromTime.ToExactNaturalText(toTime, czechTextCulture); + Assert.That(actualText, Is.EqualTo(expectedText)); + } + + [Test] + [TestCase(1, "1 vteřina")] + [TestCase(2, "2 vteřiny")] + [TestCase(3, "3 vteřiny")] + [TestCase(4, "4 vteřiny")] + [TestCase(5, "5 vteřin")] + [TestCase(12, "12 vteřin")] + [TestCase(7, "7 vteřin")] + public void Correct_Form_Of_Second_In_Czech(int seconds, string expectedText) + { + var toTime = fromTime.AddSeconds(seconds); + var actualText = fromTime.ToExactNaturalText(toTime, czechTextCulture); + Assert.That(actualText, Is.EqualTo(expectedText)); + } + + [Test] + [TestCase(1, "1 rok, 1 měsíc, 1 den, 1 hodina, 1 minuta, 1 vteřina")] + [TestCase(3, "3 roky, 3 měsíce, 3 dny, 3 hodiny, 3 minuty, 3 vteřiny")] + [TestCase(6, "6 let, 6 měsíců, 6 dnů, 6 hodin, 6 minut, 6 vteřin")] + public void Can_Translate_To_Czech_Full(int addedTime, string expectedText) + { + var toTime = fromTime.AddYears(addedTime).AddMonths(addedTime).AddDays(addedTime).AddHours(addedTime).AddMinutes(addedTime).AddSeconds(addedTime); + var actualText = fromTime.ToExactNaturalText(toTime, czechTextCulture); + Assert.That(actualText, Is.EqualTo(expectedText)); + } + } +}