diff --git a/.gitignore b/.gitignore
new file mode 100644
index 00000000..36ebf9e4
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,12 @@
+################################################################################
+# This .gitignore file was automatically created by Microsoft(R) Visual Studio.
+################################################################################
+
+/C#/TollCalculatorTests/TollCalculatorTests/TollCalculatorTests/obj/Debug/netcoreapp3.1
+/C#/TollCalculator/TollCalculator/obj
+/C#/TollCalculator/.vs/TollCalculator/v16
+/C#/TollCalculator/App/obj
+/C#/TollCalculator/App/bin/Debug/netcoreapp3.1
+/C#/TollCalculator/.vs/TollCalculator/DesignTimeBuild
+/C#/TollCalculator/TollCalculatorTests/bin/Debug/netcoreapp3.1
+/C#/TollCalculator/TollCalculatorTests/obj
diff --git a/C#/Car.cs b/C#/Car.cs
deleted file mode 100644
index 6015da69..00000000
--- a/C#/Car.cs
+++ /dev/null
@@ -1,16 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-
-namespace TollFeeCalculator
-{
- public class Car : Vehicle
- {
- public String GetVehicleType()
- {
- return "Car";
- }
- }
-}
\ No newline at end of file
diff --git a/C#/Motorbike.cs b/C#/Motorbike.cs
deleted file mode 100644
index 8258109f..00000000
--- a/C#/Motorbike.cs
+++ /dev/null
@@ -1,16 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-
-namespace TollFeeCalculator
-{
- public class Motorbike : Vehicle
- {
- public string GetVehicleType()
- {
- return "Motorbike";
- }
- }
-}
diff --git a/C#/TollCalculator.cs b/C#/TollCalculator.cs
deleted file mode 100644
index b24c794d..00000000
--- a/C#/TollCalculator.cs
+++ /dev/null
@@ -1,108 +0,0 @@
-using System;
-using System.Globalization;
-using TollFeeCalculator;
-
-public class TollCalculator
-{
-
- /**
- * Calculate the total toll fee for one day
- *
- * @param vehicle - the vehicle
- * @param dates - date and time of all passes on one day
- * @return - the total toll fee for that day
- */
-
- public int GetTollFee(Vehicle vehicle, DateTime[] dates)
- {
- DateTime intervalStart = dates[0];
- int totalFee = 0;
- foreach (DateTime date in dates)
- {
- int nextFee = GetTollFee(date, vehicle);
- int tempFee = GetTollFee(intervalStart, vehicle);
-
- long diffInMillies = date.Millisecond - intervalStart.Millisecond;
- long minutes = diffInMillies/1000/60;
-
- if (minutes <= 60)
- {
- if (totalFee > 0) totalFee -= tempFee;
- if (nextFee >= tempFee) tempFee = nextFee;
- totalFee += tempFee;
- }
- else
- {
- totalFee += nextFee;
- }
- }
- if (totalFee > 60) totalFee = 60;
- return totalFee;
- }
-
- private bool IsTollFreeVehicle(Vehicle vehicle)
- {
- if (vehicle == null) return false;
- String vehicleType = vehicle.GetVehicleType();
- return vehicleType.Equals(TollFreeVehicles.Motorbike.ToString()) ||
- vehicleType.Equals(TollFreeVehicles.Tractor.ToString()) ||
- vehicleType.Equals(TollFreeVehicles.Emergency.ToString()) ||
- vehicleType.Equals(TollFreeVehicles.Diplomat.ToString()) ||
- vehicleType.Equals(TollFreeVehicles.Foreign.ToString()) ||
- vehicleType.Equals(TollFreeVehicles.Military.ToString());
- }
-
- public int GetTollFee(DateTime date, Vehicle vehicle)
- {
- if (IsTollFreeDate(date) || IsTollFreeVehicle(vehicle)) return 0;
-
- int hour = date.Hour;
- int minute = date.Minute;
-
- if (hour == 6 && minute >= 0 && minute <= 29) return 8;
- else if (hour == 6 && minute >= 30 && minute <= 59) return 13;
- else if (hour == 7 && minute >= 0 && minute <= 59) return 18;
- else if (hour == 8 && minute >= 0 && minute <= 29) return 13;
- else if (hour >= 8 && hour <= 14 && minute >= 30 && minute <= 59) return 8;
- else if (hour == 15 && minute >= 0 && minute <= 29) return 13;
- else if (hour == 15 && minute >= 0 || hour == 16 && minute <= 59) return 18;
- else if (hour == 17 && minute >= 0 && minute <= 59) return 13;
- else if (hour == 18 && minute >= 0 && minute <= 29) return 8;
- else return 0;
- }
-
- private Boolean IsTollFreeDate(DateTime date)
- {
- int year = date.Year;
- int month = date.Month;
- int day = date.Day;
-
- if (date.DayOfWeek == DayOfWeek.Saturday || date.DayOfWeek == DayOfWeek.Sunday) return true;
-
- if (year == 2013)
- {
- if (month == 1 && day == 1 ||
- month == 3 && (day == 28 || day == 29) ||
- month == 4 && (day == 1 || day == 30) ||
- month == 5 && (day == 1 || day == 8 || day == 9) ||
- month == 6 && (day == 5 || day == 6 || day == 21) ||
- month == 7 ||
- month == 11 && day == 1 ||
- month == 12 && (day == 24 || day == 25 || day == 26 || day == 31))
- {
- return true;
- }
- }
- return false;
- }
-
- private enum TollFreeVehicles
- {
- Motorbike = 0,
- Tractor = 1,
- Emergency = 2,
- Diplomat = 3,
- Foreign = 4,
- Military = 5
- }
-}
\ No newline at end of file
diff --git a/C#/TollCalculator/App/Car.cs b/C#/TollCalculator/App/Car.cs
new file mode 100644
index 00000000..cf98ab13
--- /dev/null
+++ b/C#/TollCalculator/App/Car.cs
@@ -0,0 +1,12 @@
+using TollCalculatorApp;
+
+namespace TollFeeCalculator
+{
+ public class Car : IVehicle
+ {
+ public VehicleType GetVehicleType()
+ {
+ return VehicleType.Car;
+ }
+ }
+}
\ No newline at end of file
diff --git a/C#/TollCalculator/App/Extensions/DateTimeExtension.cs b/C#/TollCalculator/App/Extensions/DateTimeExtension.cs
new file mode 100644
index 00000000..38d5bea9
--- /dev/null
+++ b/C#/TollCalculator/App/Extensions/DateTimeExtension.cs
@@ -0,0 +1,34 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace TollCalculatorApp
+{
+ public static class DateTimeExtension
+ {
+
+ ///
+ /// Determines if date is between two Timespans representing time of day
+ ///
+ public static bool IsBetweenTimes(this DateTime date, TimeSpan start, TimeSpan end)
+ {
+ if(start <= end)
+ return date.TimeOfDay >= start && date.TimeOfDay < end;
+ else
+ throw new ArgumentException("End must be later than start");
+ }
+
+ ///
+ /// This method returns wether a datetime is a weekend day or not
+ ///
+ public static bool IsWeekend(this DateTime date)
+ {
+ if (date.DayOfWeek == DayOfWeek.Saturday || date.DayOfWeek == DayOfWeek.Sunday)
+ return true;
+
+ return false;
+ }
+ }
+}
+
diff --git a/C#/TollCalculator/App/IVehicle.cs b/C#/TollCalculator/App/IVehicle.cs
new file mode 100644
index 00000000..a4232455
--- /dev/null
+++ b/C#/TollCalculator/App/IVehicle.cs
@@ -0,0 +1,9 @@
+using TollCalculatorApp;
+
+namespace TollFeeCalculator
+{
+ public interface IVehicle
+ {
+ VehicleType GetVehicleType();
+ }
+}
diff --git a/C#/TollCalculator/App/Motorbike.cs b/C#/TollCalculator/App/Motorbike.cs
new file mode 100644
index 00000000..98460948
--- /dev/null
+++ b/C#/TollCalculator/App/Motorbike.cs
@@ -0,0 +1,13 @@
+
+using TollCalculatorApp;
+
+namespace TollFeeCalculator
+{
+ public class Motorbike : IVehicle
+ {
+ public VehicleType GetVehicleType()
+ {
+ return VehicleType.Motorbike;
+ }
+ }
+}
diff --git a/C#/TollCalculator/App/Program.cs b/C#/TollCalculator/App/Program.cs
new file mode 100644
index 00000000..a3de7ee2
--- /dev/null
+++ b/C#/TollCalculator/App/Program.cs
@@ -0,0 +1,13 @@
+using System;
+
+namespace TollFeeCalculator
+{
+ class Program
+ {
+ static void Main(string[] args)
+ {
+ Console.WriteLine("Hello World!");
+
+ }
+ }
+}
diff --git a/C#/TollCalculator/App/Services/Interfaces/IHolidayService.cs b/C#/TollCalculator/App/Services/Interfaces/IHolidayService.cs
new file mode 100644
index 00000000..0903a7c0
--- /dev/null
+++ b/C#/TollCalculator/App/Services/Interfaces/IHolidayService.cs
@@ -0,0 +1,11 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace TollCalculatorApp.Services.Interfaces
+{
+ public interface IHolidayService
+ {
+ bool IsHoliday(DateTime date);
+ }
+}
diff --git a/C#/TollCalculator/App/Services/SwedishHolidayService.cs b/C#/TollCalculator/App/Services/SwedishHolidayService.cs
new file mode 100644
index 00000000..013480a8
--- /dev/null
+++ b/C#/TollCalculator/App/Services/SwedishHolidayService.cs
@@ -0,0 +1,139 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using TollCalculatorApp.Services.Interfaces;
+
+namespace TollCalculatorApp.Services
+{
+
+ public class SwedishHolidayService : IHolidayService
+ {
+
+ ///
+ /// Determines if date is the same day as any of the swedish bank-holidays
+ ///
+ public bool IsHoliday(DateTime date)
+ {
+ var holidays = GetSwedishHolidays(date.Year);
+
+ if (holidays.Any(holiday => holiday.Month == date.Month && holiday.Day == date.Day))
+ return true;
+
+ return false;
+ }
+
+ ///
+ /// This method returns the swedish bank holidays
+ ///
+ /// The year you want days to be generated for
+ /// List of DateTimes where swedish holidays occur
+ ///
+ /// *I assumed that the "holidays" in the description in this repository meant bank-holidays
+ /// Used the following list of holidays https://www.riksbank.se/en-gb/press-and-published/calendar/bank-holidays-2021/
+ private List GetSwedishHolidays(int year)
+ {
+ //Holidays that are in terms of date of month - they occur at the same date of a month each year.
+ var Holidays = new List() {
+ new DateTime(year, 1, 1), //New years day
+ new DateTime(year, 1, 6), //Epiphany
+ new DateTime(year, 5,1), //First of May
+ new DateTime(year, 6,6), //Swedish national day
+ new DateTime(year, 12,24), //Christmas eve
+ new DateTime(year, 12,25), //Chirstmas day
+ new DateTime(year, 12,26), //Boxing day
+ new DateTime(year, 12,31) //New years eve
+ };
+
+ //Holidays that are not the same date of month each year
+ var calculatedHolidays = new List();
+ calculatedHolidays.Add(GetEasterDay(year).AddDays(-2)); //Good Friday
+ calculatedHolidays.Add(GetEasterDay(year).AddDays(-1)); //Easter Eve
+ calculatedHolidays.Add(GetEasterDay(year)); // Easter Sunday
+ calculatedHolidays.Add(GetEasterDay(year).AddDays(1)); // Easter Monday
+ calculatedHolidays.Add(GetMidsummerDay(year).AddDays(-1)); //Midsummers eve
+ calculatedHolidays.Add(GetMidsummerDay(year));
+ calculatedHolidays.Add(GetAllSaintsDay(year));
+ calculatedHolidays.Add(GetAscensionDay(year));
+ calculatedHolidays.Add(GetPentecostDay(year));
+ calculatedHolidays.Add(GetPentecostDay(year).AddDays(-1)); //Whitsun
+
+ var swedishHolidays = new List();
+ swedishHolidays.AddRange(Holidays);
+ swedishHolidays.AddRange(calculatedHolidays);
+
+ return swedishHolidays;
+ }
+
+
+
+ //This method uses Gauss algorithm to calculate easter day
+ //The algorithm used here was copied from following stack-exchange article: https://codereview.stackexchange.com/q/193847
+ ///
+ /// This method calculates the day that Easter day occur on
+ ///
+ /// The year you want to get the date of Easter day for
+ /// DateTime that Easter day occur on
+ private DateTime GetEasterDay(int year)
+ {
+ int a = year % 19;
+ int b = year / 100;
+ int c = (b - (b / 4) - ((8 * b + 13) / 25) + (19 * a) + 15) % 30;
+ int d = c - (c / 28) * (1 - (c / 28) * (29 / (c + 1)) * ((21 - a) / 11));
+ int e = d - ((year + (year / 4) + d + 2 - b + (b / 4)) % 7);
+ int month = 3 + ((e + 40) / 44);
+ int day = e + 28 - (31 * (month / 4));
+ return new DateTime(year, month, day);
+ }
+
+ ///
+ /// This method calculates the day that All saints day occur on
+ ///
+ /// The year you want to get the date of all saints day for
+ /// DateTime that all saints day occur on
+ private DateTime GetAllSaintsDay(int year)
+ {
+ var date = new DateTime(year, 10, 31);
+ while (date.DayOfWeek != DayOfWeek.Saturday)
+ {
+ date = date.AddDays(1);
+ }
+ return date;
+ }
+
+ ///
+ /// This method calculates the day that All saints day occur on
+ ///
+ /// The year you want to get the date of All saints day for
+ /// DateTime that ascension day occur on
+ private DateTime GetAscensionDay(int year)
+ {
+ return GetEasterDay(year).AddDays(39);
+ }
+
+ ///
+ /// This method calculates the day that Pentecost occur on
+ ///
+ /// The year you want to get the date of Pentecost for
+ /// DateTime that Pentecost occur on
+ private DateTime GetPentecostDay(int year)
+ {
+ return GetEasterDay(year).AddDays(49);
+ }
+
+ ///
+ /// This method calculates the day that Midsummer day occur on
+ ///
+ /// The year you want to get the date of Midsummer day for
+ /// DateTime that Midsummer day occur on
+ private DateTime GetMidsummerDay(int year)
+ {
+ var date = new DateTime(year, 6, 20);
+ while (date.DayOfWeek != DayOfWeek.Saturday)
+ {
+ date = date.AddDays(1);
+ }
+
+ return date;
+ }
+ }
+}
diff --git a/C#/TollCalculator/App/TollCalculator.cs b/C#/TollCalculator/App/TollCalculator.cs
new file mode 100644
index 00000000..0a9fa182
--- /dev/null
+++ b/C#/TollCalculator/App/TollCalculator.cs
@@ -0,0 +1,108 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using TollCalculatorApp;
+using TollCalculatorApp.Services.Interfaces;
+
+namespace TollFeeCalculator
+{
+ public class TollCalculator
+ {
+
+ private readonly IHolidayService _holidayService;
+
+ public TollCalculator(IHolidayService holidayService)
+ {
+ _holidayService = holidayService;
+ }
+ const int MaxTollFee = 60;
+ private readonly List _tollFreeVehicles = new List
+ {
+ VehicleType.Motorbike,
+ VehicleType.Tractor,
+ VehicleType.Emergency,
+ VehicleType.Diplomat,
+ VehicleType.Foreign,
+ VehicleType.Military
+ };
+
+ /**
+ * Calculate the total toll fee for one day
+ *
+ * @param vehicle - the vehicle
+ * @param dates - date and time of all passes on one day
+ * @return - the total toll fee for that day
+ */
+ public int GetTollFee(IVehicle vehicle, DateTime[] dates)
+ {
+ var sortedDate = dates.OrderBy(date => date.Ticks).ToList();
+ DateTime intervalStart = sortedDate[0];
+ int totalFee = 0;
+ foreach (DateTime date in sortedDate)
+ {
+ int nextFee = GetTollFee(date, vehicle);
+ int tempFee = GetTollFee(intervalStart, vehicle);
+
+ TimeSpan diffBetweenDates = date - intervalStart;
+ if (diffBetweenDates.TotalMinutes <= 60)
+ {
+ if (totalFee > 0) totalFee -= tempFee;
+ if (nextFee >= tempFee) tempFee = nextFee;
+ totalFee += tempFee;
+ }
+ else
+ {
+ totalFee += nextFee;
+ }
+ }
+ if (totalFee > MaxTollFee)
+ return MaxTollFee;
+
+ return totalFee;
+ }
+ public int GetTollFee(DateTime date, IVehicle vehicle)
+ {
+ if (IsTollFreeVehicle(vehicle) || IsTollFreeDate(date))
+ return 0;
+
+
+ if (date.IsBetweenTimes(TimeSpan.Parse("06:00"), TimeSpan.Parse("06:30"))) return 8;
+ if (date.IsBetweenTimes(TimeSpan.Parse("06:30"), TimeSpan.Parse("07:00"))) return 13;
+ if (date.IsBetweenTimes(TimeSpan.Parse("07:00"), TimeSpan.Parse("08:00"))) return 18;
+ if (date.IsBetweenTimes(TimeSpan.Parse("08:00"), TimeSpan.Parse("08:30"))) return 13;
+
+ //The following condition was translated from previous code - I think it might have contained an error
+ // else if (hour >= 8 && hour <= 14 && minute >= 30 && minute <= 59) return 8;
+ // would have been translated to x:30 - x:59 where x would be the hours 8 to 14
+ // leaving x:00 - x.29 toll free for each of the hours between 8-14.
+ if (date.IsBetweenTimes(TimeSpan.Parse("08:30"), TimeSpan.Parse("15:00"))) return 8;
+
+ if (date.IsBetweenTimes(TimeSpan.Parse("15:00"), TimeSpan.Parse("15:30"))) return 13;
+ if (date.IsBetweenTimes(TimeSpan.Parse("15:30"), TimeSpan.Parse("17:00"))) return 18;
+ if (date.IsBetweenTimes(TimeSpan.Parse("17:00"), TimeSpan.Parse("18:00"))) return 13;
+ if (date.IsBetweenTimes(TimeSpan.Parse("18:00"), TimeSpan.Parse("18:30"))) return 8;
+
+ return 0;
+ }
+ private bool IsTollFreeVehicle(IVehicle vehicle)
+ {
+ if (vehicle == null) return false;
+
+ if (_tollFreeVehicles.Any(tollFreeVehicle => tollFreeVehicle == vehicle.GetVehicleType()))
+ return true;
+ else
+ {
+ return false;
+ }
+ }
+ private bool IsTollFreeDate(DateTime date)
+ {
+ if (date.IsWeekend() || _holidayService.IsHoliday(date))
+ {
+ return true;
+ }
+
+ return false;
+ }
+ }
+}
diff --git a/C#/TollCalculator/App/TollFeeCalculator.csproj b/C#/TollCalculator/App/TollFeeCalculator.csproj
new file mode 100644
index 00000000..783b01e7
--- /dev/null
+++ b/C#/TollCalculator/App/TollFeeCalculator.csproj
@@ -0,0 +1,10 @@
+
+
+
+ Exe
+ netcoreapp3.1
+ TollCalculatorApp
+ TollCalculatorApp
+
+
+
diff --git a/C#/TollCalculator/App/VehicleType.cs b/C#/TollCalculator/App/VehicleType.cs
new file mode 100644
index 00000000..4c675b5f
--- /dev/null
+++ b/C#/TollCalculator/App/VehicleType.cs
@@ -0,0 +1,13 @@
+namespace TollCalculatorApp
+{
+ public enum VehicleType
+ {
+ Car = 0,
+ Motorbike = 1,
+ Tractor = 2,
+ Emergency = 3,
+ Diplomat = 4,
+ Foreign = 5,
+ Military = 6
+ }
+}
diff --git a/C#/TollCalculator/TollCalculator.sln b/C#/TollCalculator/TollCalculator.sln
new file mode 100644
index 00000000..58051d6f
--- /dev/null
+++ b/C#/TollCalculator/TollCalculator.sln
@@ -0,0 +1,31 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 16
+VisualStudioVersion = 16.0.31702.278
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TollCalculatorTests", "TollCalculatorTests\TollCalculatorTests.csproj", "{F39C7F86-39BB-4DEF-9173-B29CE4505CC7}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TollFeeCalculator", "App\TollFeeCalculator.csproj", "{FA02706B-6499-4B92-96B0-8ED66B852982}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Release|Any CPU = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {F39C7F86-39BB-4DEF-9173-B29CE4505CC7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {F39C7F86-39BB-4DEF-9173-B29CE4505CC7}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {F39C7F86-39BB-4DEF-9173-B29CE4505CC7}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {F39C7F86-39BB-4DEF-9173-B29CE4505CC7}.Release|Any CPU.Build.0 = Release|Any CPU
+ {FA02706B-6499-4B92-96B0-8ED66B852982}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {FA02706B-6499-4B92-96B0-8ED66B852982}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {FA02706B-6499-4B92-96B0-8ED66B852982}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {FA02706B-6499-4B92-96B0-8ED66B852982}.Release|Any CPU.Build.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {B2FD73E7-0D65-4896-B94F-9788D8030169}
+ EndGlobalSection
+EndGlobal
diff --git a/C#/TollCalculator/TollCalculatorTests/Extensions/DateTimeExtensionTests.cs b/C#/TollCalculator/TollCalculatorTests/Extensions/DateTimeExtensionTests.cs
new file mode 100644
index 00000000..6c8c5f76
--- /dev/null
+++ b/C#/TollCalculator/TollCalculatorTests/Extensions/DateTimeExtensionTests.cs
@@ -0,0 +1,62 @@
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using System;
+using System.Collections.Generic;
+using System.Text;
+using TollCalculatorApp;
+
+namespace TollFeeCalculatorTests
+{
+ [TestClass]
+ public class DateTimeExtensionTests
+ {
+ #region IsBetweenTimes
+ [TestMethod]
+ public void IsBetweenTimes_Simple_DateTime_Comparison()
+ {
+ var testDate = new DateTime(2020, 01, 01, 10, 0, 0);
+ var isBetween = testDate.IsBetweenTimes(TimeSpan.Parse("09:00"), TimeSpan.Parse("10:30"));
+
+ Assert.IsTrue(isBetween);
+ }
+ [TestMethod]
+ public void IsBetweenTimes_Start_Same_As_Date_Being_Compared()
+ {
+ var testDate = new DateTime(2020, 01, 01, 9, 0, 0);
+ var isBetween = testDate.IsBetweenTimes(TimeSpan.Parse("09:00"), TimeSpan.Parse("10:30"));
+
+ Assert.IsTrue(isBetween);
+ }
+ [TestMethod]
+ public void IsBetweenTimes_End_Same_As_Date_Being_Compared()
+ {
+ var testDate = new DateTime(2020, 01, 01, 10, 0, 0);
+ var isBetween = testDate.IsBetweenTimes(TimeSpan.Parse("09:00"), TimeSpan.Parse("10:00"));
+
+ Assert.IsFalse(isBetween);
+ }
+
+
+ #endregion
+
+ #region IsWeekend
+ [TestMethod]
+ public void IsWeekend_Saturday()
+ {
+ var testDate = new DateTime(2021, 01, 02, 10, 0, 0);
+ Assert.IsTrue(testDate.IsWeekend());
+ }
+ [TestMethod]
+ public void IsWeekend_Sunday()
+ {
+ var testDate = new DateTime(2021, 01, 03, 10, 0, 0);
+ Assert.IsTrue(testDate.IsWeekend());
+ }
+ [TestMethod]
+ public void IsWeekend_Weekday()
+ {
+ var testDate = new DateTime(2021, 01, 04, 10, 0, 0);
+ Assert.IsFalse(testDate.IsWeekend());
+ }
+ #endregion
+ }
+}
diff --git a/C#/TollCalculator/TollCalculatorTests/Services/SwedishHolidayServiceTest.cs b/C#/TollCalculator/TollCalculatorTests/Services/SwedishHolidayServiceTest.cs
new file mode 100644
index 00000000..016a56f3
--- /dev/null
+++ b/C#/TollCalculator/TollCalculatorTests/Services/SwedishHolidayServiceTest.cs
@@ -0,0 +1,130 @@
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using System;
+using TollCalculatorApp.Services;
+using TollCalculatorApp.Services.Interfaces;
+
+namespace TollFeeCalculatorTests
+{
+ [TestClass]
+ public class SwedishHolidayServiceTest
+ {
+ private IHolidayService _holidayService;
+
+ [TestInitialize]
+ public void TestInitialize()
+ {
+ _holidayService = new SwedishHolidayService();
+ }
+
+ #region IsSwedishHoliday Tests
+ [TestMethod]
+ public void NewYearsDayTest()
+ {
+ var date = new DateTime(2021, 1, 1);
+ Assert.IsTrue(_holidayService.IsHoliday(date), "Expected New Years day to be in list of holidays");
+ }
+ [TestMethod]
+ public void EpiphanyTest()
+ {
+ var date = new DateTime(2021, 1, 6);
+ Assert.IsTrue(_holidayService.IsHoliday(date), "Expected Epiphany to be holiday");
+ }
+ [TestMethod]
+ public void GoodFridayTest()
+ {
+ var date = new DateTime(2021, 4, 2);
+ Assert.IsTrue(_holidayService.IsHoliday(date), "Expected Good friday to be holiday");
+ }
+ [TestMethod]
+ public void EasterEveTest()
+ {
+ var date = new DateTime(2021, 4, 3);
+ Assert.IsTrue(_holidayService.IsHoliday(date), "Expected Easter Eve to be holiday");
+ }
+ [TestMethod]
+ public void EasterSundayTest()
+ {
+ var date = new DateTime(2021, 4, 4);
+ Assert.IsTrue(_holidayService.IsHoliday(date), "Expected Easter Sunday to be holiday");
+ }
+ [TestMethod]
+ public void EasterMondayTest()
+ {
+ var date = new DateTime(2021, 4, 5);
+ Assert.IsTrue(_holidayService.IsHoliday(date), "Expected Easter Monday to be holiday");
+ }
+ [TestMethod]
+ public void LabourDayTest()
+ {
+ var date = new DateTime(2021, 5, 1);
+ Assert.IsTrue(_holidayService.IsHoliday(date), "Expected Labour Day to be holiday");
+ }
+ [TestMethod]
+ public void AcensionDayTest()
+ {
+ var date = new DateTime(2021, 5, 13);
+ Assert.IsTrue(_holidayService.IsHoliday(date), "Expected Acension Day to be holiday");
+ }
+ [TestMethod]
+ public void WhitsunTest()
+ {
+ var date = new DateTime(2021, 5, 22);
+ Assert.IsTrue(_holidayService.IsHoliday(date), "Expected Whitsun to be holiday");
+ }
+ [TestMethod]
+ public void PentecostTest()
+ {
+ var date = new DateTime(2021, 5, 23);
+ Assert.IsTrue(_holidayService.IsHoliday(date), "Expected Pentecost to be holiday");
+ }
+ [TestMethod]
+ public void NationalDayTest()
+ {
+ var date = new DateTime(2021, 6, 6);
+ Assert.IsTrue(_holidayService.IsHoliday(date), "Expected National Day to be holiday");
+ }
+ [TestMethod]
+ public void MidsummerEveTest()
+ {
+ var date = new DateTime(2021, 6, 25);
+ Assert.IsTrue(_holidayService.IsHoliday(date), "Expected Midsummer Eve to be holiday");
+ }
+ [TestMethod]
+ public void MidsummerDayTest()
+ {
+ var date = new DateTime(2021, 6, 26);
+ Assert.IsTrue(_holidayService.IsHoliday(date), "Expected Midsummer Day to be holiday");
+ }
+ [TestMethod]
+ public void AllSaintsDayTest()
+ {
+ var date = new DateTime(2021, 11, 6);
+ Assert.IsTrue(_holidayService.IsHoliday(date), "Expected All saints Day to be holiday");
+ }
+ [TestMethod]
+ public void ChristmasEveTest()
+ {
+ var date = new DateTime(2021, 12, 24);
+ Assert.IsTrue(_holidayService.IsHoliday(date), "Expected Christmas Eve to be holiday");
+ }
+ [TestMethod]
+ public void ChristmasDayTest()
+ {
+ var date = new DateTime(2021, 12, 25);
+ Assert.IsTrue(_holidayService.IsHoliday(date), "Expected Christmas Day to be holiday");
+ }
+ [TestMethod]
+ public void BoxingDayTest()
+ {
+ var date = new DateTime(2021, 12, 26);
+ Assert.IsTrue(_holidayService.IsHoliday(date), "Expected Boxing to be holiday");
+ }
+ [TestMethod]
+ public void NewYearsEveTest()
+ {
+ var date = new DateTime(2021, 12, 31);
+ Assert.IsTrue(_holidayService.IsHoliday(date), "Expected New Year's Eve to be holiday");
+ }
+ #endregion
+ }
+}
diff --git a/C#/TollCalculator/TollCalculatorTests/TollCalculatorTests.cs b/C#/TollCalculator/TollCalculatorTests/TollCalculatorTests.cs
new file mode 100644
index 00000000..2d470fa1
--- /dev/null
+++ b/C#/TollCalculator/TollCalculatorTests/TollCalculatorTests.cs
@@ -0,0 +1,121 @@
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using System;
+using TollCalculatorApp.Services;
+using TollFeeCalculator;
+
+namespace TollFeeCalculatorTests
+{
+ [TestClass]
+ public class TollCalculatorTests
+ {
+ private TollCalculator _tollCalculator;
+
+ [TestInitialize]
+ public void TestInitialize()
+ {
+ var holidayService = new SwedishHolidayService();
+ _tollCalculator = new TollCalculator(holidayService);
+ }
+
+ [TestMethod]
+ public void Maximum_Fee_Per_Day()
+ {
+ //Arrange
+ var vehicle = new Car();
+
+ var dates = new DateTime[] {
+ new DateTime(2021, 10, 6, 7, 0, 0),
+ new DateTime(2021, 10, 6, 9, 0, 0),
+ new DateTime(2021, 10, 6, 11, 0, 0),
+ new DateTime(2021, 10, 6, 13, 0, 0),
+ new DateTime(2021, 10, 6, 15, 0, 0),
+ new DateTime(2021, 10, 6, 17, 0, 0)
+ };
+
+ //Act
+ var tollFee = _tollCalculator.GetTollFee(vehicle, dates);
+
+ //Assert
+ Assert.AreEqual(60, tollFee, "Expected max fee for a day to be 60");
+ }
+
+ [TestMethod]
+ public void Fee_Free_Vehicle_Returns_No_Fee()
+ {
+ //Arrange
+ var vehicle = new Motorbike();
+ var dates = new DateTime[] { new DateTime(2021, 01, 01, 10, 0, 0) };
+
+ //Act
+ var tollFee = _tollCalculator.GetTollFee(vehicle, dates);
+
+ //Assert
+ Assert.AreEqual(0, tollFee, "Expected motorbike to be tollfree vehicle");
+ }
+
+ [TestMethod]
+ public void Fee_Free_Holiday_Returns_No_Fee()
+ {
+ //Arrange
+ var vehicle = new Car();
+ var dates = new DateTime[] { new DateTime(2021, 01, 01, 10, 0, 0) };
+
+ //Act
+ var tollFee = _tollCalculator.GetTollFee(vehicle, dates);
+
+ //Assert
+ Assert.AreEqual(0, tollFee, "Expected no tax on holiday");
+ }
+
+ [TestMethod]
+ public void Highest_Fee_Is_Applied_For_Fees_Within_60_Minutes()
+ {
+ //Arrange
+ var vehicle = new Car();
+ var dates = new DateTime[] {
+ new DateTime(2021, 02, 01, 15, 0, 0),
+ new DateTime(2021, 02, 01, 15, 35, 0)
+ };
+
+ //Act
+ var tollFee = _tollCalculator.GetTollFee(vehicle, dates);
+
+ //Assert
+ Assert.AreEqual(18, tollFee, "Expected highest fee to be returned");
+ }
+
+ [TestMethod]
+ public void One_TollStation_Pass_Returns_Correct_Fee()
+ {
+ //Arrange
+ var vehicle = new Car();
+ var dates = new DateTime[] {
+ new DateTime(2021, 02, 01, 15, 0, 0)
+ };
+
+ //Act
+ var tollFee = _tollCalculator.GetTollFee(vehicle, dates);
+
+ //Assert
+ Assert.AreEqual(13, tollFee);
+ }
+ [TestMethod]
+ public void Large_Amount_of_TollStation_Passes_Returns_Correct_Fee()
+ {
+ //Arrange
+ var vehicle = new Car();
+ var dates = new DateTime[] {
+ new DateTime(2021, 02, 01, 6, 0, 0),
+ new DateTime(2021, 02, 01, 10, 0, 0),
+ new DateTime(2021, 02, 01, 15, 0, 0),
+ new DateTime(2021, 02, 01, 18, 0, 0),
+ };
+
+ //Act
+ var tollFee = _tollCalculator.GetTollFee(vehicle, dates);
+
+ //Assert
+ Assert.AreEqual(37, tollFee);
+ }
+ }
+}
diff --git a/C#/TollCalculator/TollCalculatorTests/TollCalculatorTests.csproj b/C#/TollCalculator/TollCalculatorTests/TollCalculatorTests.csproj
new file mode 100644
index 00000000..2c5f18f5
--- /dev/null
+++ b/C#/TollCalculator/TollCalculatorTests/TollCalculatorTests.csproj
@@ -0,0 +1,24 @@
+
+
+
+ netcoreapp3.1
+
+ false
+
+ TollFeeCalculator
+
+ TollFeeCalculator
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/C#/Vehicle.cs b/C#/Vehicle.cs
deleted file mode 100644
index 19fe04e4..00000000
--- a/C#/Vehicle.cs
+++ /dev/null
@@ -1,13 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-
-namespace TollFeeCalculator
-{
- public interface Vehicle
- {
- String GetVehicleType();
- }
-}
\ No newline at end of file