Skip to content
Merged
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
Original file line number Diff line number Diff line change
@@ -0,0 +1,148 @@
#region License

//
// Copyright (c) 2011-2012, João Matos Silva <kappy@acydburne.com.pt>
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//

#endregion

using System;
using System.Collections.Generic;
using DateTimeExtensions.Common;

namespace DateTimeExtensions.WorkingDays.CultureStrategies
{
[Locale("en-GH")]
public class EN_GHHolidayStrategy : HolidayStrategyBase, IHolidayStrategy
{
public EN_GHHolidayStrategy()
{
InnerHolidays.Add(GlobalHolidays.NewYear);

InnerHolidays.Add(ChristianHolidays.GoodFriday);
InnerHolidays.Add(ChristianHolidays.EasterMonday);
InnerHolidays.Add(ChristianHolidays.Christmas);

InnerHolidays.Add(IndependenceDay);
InnerHolidays.Add(LabourDay);
InnerHolidays.Add(RepublicDay);
InnerHolidays.Add(AfricaDay);
InnerHolidays.Add(KwameNkrumahMemorialDay);

InnerHolidays.Add(GlobalHolidays.InternationalWorkersDay);
InnerHolidays.Add(GlobalHolidays.BoxingDay);
}

protected override IDictionary<DateTime, Holiday> BuildObservancesMap(int year)
{
IDictionary<DateTime, Holiday> holidayMap = new Dictionary<DateTime, Holiday>();
foreach (var innerHoliday in InnerHolidays)
{
var date = innerHoliday.GetInstance(year);
if (date.HasValue)
{
if (holidayMap.ContainsKey(date.Value))
{
// Check to see if holiday falling on the Sunday then moves to the monday, and there is another holiday scheduled for the monday
// Update the Holiday Name of the Monday
holidayMap[date.Value] = innerHoliday;
}

else
{
holidayMap.Add(date.Value, innerHoliday);
}

//if the holiday is a sunday, the holiday is observed on next monday
if (date.Value.DayOfWeek == DayOfWeek.Sunday)
{
holidayMap.AddIfInexistent(date.Value.AddDays(1), innerHoliday);
}
}
}
return holidayMap;
}

// 6th March - Independence Day
private static Holiday independenceDay;
public static Holiday IndependenceDay
{
get
{
if (independenceDay == null)
{
independenceDay = new FixedHoliday("Independence Day", 3, 6);
}
return independenceDay;
}
}

// 1 May - Labour Day
private static Holiday labourDay;
public static Holiday LabourDay
{
get
{
if (labourDay == null)
{
labourDay = new FixedHoliday("Labour Day", 5, 1);
}
return labourDay;
}
}

// 25 May - Africa Day
private static Holiday africaDay;
public static Holiday AfricaDay
{
get
{
if (africaDay == null)
{
africaDay = new FixedHoliday("Africa Day", 5, 25);
}
return africaDay;
}
}

// 1 July - Republic Day
private static Holiday republicDay;
public static Holiday RepublicDay
{
get
{
if (republicDay == null)
{
republicDay = new FixedHoliday("Republic Day", 7, 1);
}
return republicDay;
}
}

// 21 September - Kwame Nkrumah Memorial Day
private static Holiday kwameNkrumahMemorialDay;
public static Holiday KwameNkrumahMemorialDay
{
get
{
if (kwameNkrumahMemorialDay == null)
{
kwameNkrumahMemorialDay = new FixedHoliday("Kwame Nkrumah Memorial Day", 9, 21);
}
return kwameNkrumahMemorialDay;
}
}
}
}
118 changes: 118 additions & 0 deletions tests/DateTimeExtensions.Tests/enGHHolidaysTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
using System;
using System.Linq;
using DateTimeExtensions.WorkingDays;
using DateTimeExtensions.WorkingDays.CultureStrategies;
using NUnit.Framework;

namespace DateTimeExtensions.Tests
{
[TestFixture]
public class EN_GHHolidayStrategyTests
{
private readonly WorkingDayCultureInfo _culture = new("en-GH");

[Test]
public void StrategyResolution_Returns_EN_GHHolidayStrategy()
{
var strategy = _culture.LocateHolidayStrategy(_culture.Name, null);
Assert.That(strategy, Is.TypeOf<EN_GHHolidayStrategy>());
}

[Test]
public void Holidays_Collection_Count_Is_11()
{
var holidays = _culture.Holidays;
Assert.That(holidays.Count(), Is.EqualTo(11));
}

[Test]
public void Christmas_On_Sunday_2022_And_BoxingDay_Collision_Behaviour()
{
var year = 2022;
var christmas = new DateTime(year, 12, 25);
var boxingDay = new DateTime(year, 12, 26);

var holidaysMap = new DateTime(year, 1, 1).AllYearHolidays(_culture);

Assert.Multiple(() =>
{
Assert.That(christmas.DayOfWeek, Is.EqualTo(DayOfWeek.Sunday));
Assert.That(holidaysMap.ContainsKey(christmas), Is.True, "Christmas (original date) should be present.");
Assert.That(holidaysMap.ContainsKey(boxingDay), Is.True, "Boxing Day / observed slot should be present.");
Assert.That(holidaysMap[christmas].Name, Is.EqualTo("Christmas"));
Assert.That(holidaysMap[boxingDay].Name, Is.EqualTo("Boxing Day"));
Assert.That(christmas.IsWorkingDay(_culture), Is.False);
Assert.That(boxingDay.IsWorkingDay(_culture), Is.False);
});
}

[Test]
public void Christmas_Sunday_2033_Is_Observed_On_Monday_2033()
{
var christmasSunday = new DateTime(2033, 12, 25);
var observed = christmasSunday.AddDays(1);

Assert.Multiple(() =>
{
Assert.That(christmasSunday.DayOfWeek, Is.EqualTo(DayOfWeek.Sunday));
Assert.That(observed.IsHoliday(_culture), Is.True, "Following Monday should be observed as a holiday.");
Assert.That(observed.IsWorkingDay(_culture), Is.False);
});
}

public void Assert_LabourDayHoliday_On_Sunday_Observed_On_Monday()
{
// 02-05-2033 Labour day on a Sunday
var mondayAfterLabourDay = new DateTime(2033, 05, 2);
Assert.Multiple(() =>
{
Assert.That(mondayAfterLabourDay.DayOfWeek, Is.EqualTo(DayOfWeek.Monday));
Assert.That(mondayAfterLabourDay.IsWorkingDay(_culture), Is.False);
});
}

[TestCase("2024-04-05", 1, "2024-04-08")]
[TestCase("2024-04-05", 0, "2024-04-05")]
public void AddWorkingDays_Respects_Holidays_And_Weekends(string startIso, int addDays, string expectedIso)
{
var start = DateTime.Parse(startIso).AddHours(13); // ensure time part exists
var expected = DateTime.Parse(expectedIso);
var result = start.AddWorkingDays(addDays, _culture);
Assert.That(result.Date, Is.EqualTo(expected.Date));
}

[Test]
public void GetWorkingDays_Counts_Properly_For_Range()
{
var from = new DateTime(2024, 12, 23); // Mon
var to = new DateTime(2024, 12, 27); // Fri (exclusive)
var count = from.GetWorkingDays(to, _culture);

// 2024-12-25 Christmas and 2024-12-26 Boxing Day are holidays -> working days are 23 and 24
Assert.That(count, Is.EqualTo(2));
}

[Test]
public void IsHoliday_Default_And_With_Culture()
{
var date = new DateTime(2024, 12, 25);
Assert.That(date.IsHoliday(_culture), Is.True);
// exercise idempotency / caching
Assert.That(date.IsHoliday(_culture), Is.True);
}

[Test]
public void AllYearHolidays_Returns_Mapping_With_Observed_Entries()
{
var year = 2022;
var map = new DateTime(year, 1, 1).AllYearHolidays(_culture);

Assert.Multiple(() =>
{
Assert.That(map.ContainsKey(new DateTime(year, 1, 1)), Is.True, "New Year should be present");
Assert.That(map.ContainsKey(new DateTime(year, 12, 25)), Is.True, "Christmas original should be present");
Assert.That(map.ContainsKey(new DateTime(year, 12, 26)), Is.True, "Observed Boxing Day slot should be present");
});
}
}
}
Loading