I was looking at a coding exercise recently that consisted of source code that needed refactoring. Embedded in part of the code was a check to see if someone was 21 or over. I thought this was a great chance to use the Noda Time library created by Jon Skeet to create nicely understandable code. Noda Time is described in the following terms:
“Noda Time is an alternative date and time API for .NET. It helps you to think about your data more clearly, and express operations on that data more precisely.” [1]
So, here’s a quick piece of playful code using Noda Time to check a person’s age in years. Firstly, let’s create a service interface.
using System; namespace AgeService { public interface IAgeService { bool IsOfAgeAtDate(DateTime dateOfTest, DateTime dateOfBirth, int expectedAgeInYears); } }
Now let’s implement the interface.
using System; using NodaTime; namespace AgeService { public class AgeService : IAgeService { public bool IsOfAgeAtDate(DateTime dateOfTest, DateTime dateOfBirth, int expectedAgeInYears) { var localDateOfTest = new LocalDate(dateOfTest.Year, dateOfTest.Month, dateOfTest.Day); var localDateOfBirth = new LocalDate(dateOfBirth.Year, dateOfBirth.Month, dateOfBirth.Day); Period age = Period.Between(localDateOfBirth, localDateOfTest, PeriodUnits.Years); return age.Years >= expectedAgeInYears; } } }
A LocalDate is the date portion of a Noda Time LocalDateTime that has no concept of the time of day; it's just a date. A Period described as follows:
“A Period is a number of years, months, weeks, days, hours and so on, which can be added to (or subtracted from) a LocalDateTime, LocalDate or LocalTime. The amount of elapsed time represented by a Period isn't fixed: a period of "one month" is effectively longer when added to January 1st than when added to February 1st, because February is always shorter than January.” [2]
Finally here are a couple of simple tests to demonstrate it works.
using System; using NUnit.Framework; namespace AgeServiceTests { [TestFixture] public class AgeServiceTests { [Test] public void IsOfAgeAtDate_WhenOfCorrectAge_ReturnsTrue() { // Arrange var ageService = new AgeService.AgeService(); var dateOfTest = new DateTime(2014, 10, 23); var dateOfBirth = new DateTime(1993, 10, 23); // Act var result = ageService.IsOfAgeAtDate(dateOfTest, dateOfBirth, 21); // Assert Assert.That(result, Is.True); } [Test] public void IsOfAgeAtDate_WhenUnderAge_ReturnsFalse() { // Arrange var ageService = new AgeService.AgeService(); var dateOfTest = new DateTime(2014, 10, 23); var dateOfBirth = new DateTime(1993, 10, 24); // Act var result = ageService.IsOfAgeAtDate(dateOfTest, dateOfBirth, 21); // Assert Assert.That(result, Is.False); } } }
There’s lots more to Noda Time than that but it’s a start! Happy coding.