Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>More solid implementation</p> <pre><code>/// &lt;summary&gt; /// Immutable value type for storing personal numbers /// &lt;/summary&gt; public struct PersonalNumber : IEquatable&lt;PersonalNumber&gt; { private const string YearHundredOpt = @"(19|20)?"; // 19 or 20 only (optional) private const string YearDecade = @"(\d{2})"; // any two digits private const string Month = @"(0[1-9]|10|11|12)"; // 01 to 12 private const string Day = @"(0[1-9]|1\d|2\d|30|31)"; // 01 to 31 private const string SeparatorAndLastFourOpt = @"([-\+]?)(\d{4})?"; // optional - or + followed by any four digits (optional) private const string RegExForValidation = "^" + YearHundredOpt + YearDecade + Month + Day + SeparatorAndLastFourOpt + "$"; private static readonly Regex personNoRegex = new Regex(RegExForValidation, RegexOptions.Compiled); private readonly string rawPersonalNumber; private readonly string personalNumber; private readonly bool isValid; private readonly bool isPlus100YearsOld; public PersonalNumber(string personalNumber) { rawPersonalNumber = personalNumber; var matches = personNoRegex.Matches(personalNumber); var normalizedYYMMDDXXXC = string.Empty; isPlus100YearsOld = false; foreach (Match match in matches) { if (match.Success) { normalizedYYMMDDXXXC = match.Groups[2].Value + match.Groups[3].Value + match.Groups[4].Value + match.Groups[6].Value; if (match.Groups[5].Success) { isPlus100YearsOld = match.Groups[5].Value == "+"; } break; } } if (normalizedYYMMDDXXXC.Length &gt; 6) { isValid = personNoRegex.IsMatch(personalNumber) &amp;&amp; LuhnAlgorithm.ValidateChecksum(normalizedYYMMDDXXXC); } else { isValid = personNoRegex.IsMatch(personalNumber); } this.personalNumber = string.IsNullOrEmpty(normalizedYYMMDDXXXC) ? rawPersonalNumber : normalizedYYMMDDXXXC; } public string Number { get { return personalNumber; } } public bool IsPlus100YearsOld { get { return isPlus100YearsOld; } } public bool IsValid { get { return isValid; } } public bool IsMale { get { return !IsFemale; } } public bool IsFemale { get { var genderCharacter = personalNumber.Substring(personalNumber.Length - 2, 1); // second to last character return int.Parse(genderCharacter) % 2 == 0; // even = female, odd = male } } public override string ToString() { return Number; } public bool Equals(PersonalNumber other) { return Equals(other.personalNumber, personalNumber); } public override bool Equals(object obj) { if (ReferenceEquals(null, obj)) return false; if (obj.GetType() != typeof (PersonalNumber)) return false; return Equals((PersonalNumber) obj); } public override int GetHashCode() { unchecked { int result = (rawPersonalNumber != null ? rawPersonalNumber.GetHashCode() : 0); result = (result*397) ^ (personalNumber != null ? personalNumber.GetHashCode() : 0); result = (result*397) ^ isValid.GetHashCode(); return result; } } public static bool operator ==(PersonalNumber left, PersonalNumber right) { return left.Equals(right); } public static bool operator !=(PersonalNumber left, PersonalNumber right) { return !left.Equals(right); } } </code></pre> <p>and some tests for it</p> <pre><code>[TestClass] public class PersonalNumberFixture { [TestMethod] public void Ctor_PersonalNumber_AsUnformatted() { AssertExpectedNumber("7102240475", "7102240475"); AssertExpectedNumber("197102240475", "7102240475"); AssertExpectedNumber("19710224-0475", "7102240475"); AssertExpectedNumber("710224-0475", "7102240475"); } private static void AssertExpectedNumber(string number, string expectedNumber) { Assert.AreEqual(expectedNumber, new PersonalNumber(number).Number); } [TestMethod] public void FiltersAndRemovesPlusAndMinusCharactersCorrectly() { Assert.AreEqual("7102240475", new PersonalNumber("710224-0475").Number); Assert.AreEqual("7102240475", new PersonalNumber("710224+0475").Number); Assert.AreEqual("7102240475", new PersonalNumber("19710224-0475").Number); Assert.AreEqual("7102240475", new PersonalNumber("19710224+0475").Number); } [TestMethod] public void PlusAndMinusCharactersOnlyAllowedInCertainPositions() { Assert.IsTrue(new PersonalNumber("710224-0475").IsValid); Assert.IsTrue(new PersonalNumber("710224+0475").IsValid); Assert.IsFalse(new PersonalNumber("71022404-75").IsValid); Assert.IsFalse(new PersonalNumber("71022404+75").IsValid); Assert.IsFalse(new PersonalNumber("710-224-0475").IsValid); Assert.IsFalse(new PersonalNumber("710224+04+75").IsValid); } [TestMethod] public void MaleAndFemale_CorrectlyIdentified() { // female Assert.IsFalse(new PersonalNumber("551213-7986").IsMale); Assert.IsTrue(new PersonalNumber("551213-7986").IsFemale); // male Assert.IsTrue(new PersonalNumber("710224-0475").IsMale); Assert.IsFalse(new PersonalNumber("710224-0475").IsFemale); Assert.IsTrue(new PersonalNumber("19710224-0475").IsMale); Assert.IsFalse(new PersonalNumber("19710224-0475").IsFemale); } [TestMethod] public void Ctor_ValidPersonalNumbers_ParsedAsValid() { TestLoop_ValidPersonalNumbers(new[] { "7102240475", "197102240475", "19710224-0475", "710224-0475", "801231+3535", "630215" }); } private static void TestLoop_ValidPersonalNumbers(IEnumerable&lt;string&gt; personalNumbers) { foreach (var personalNumber in personalNumbers) { var pn = new PersonalNumber(personalNumber); Assert.IsTrue(pn.IsValid, string.Format("Pno = '{0}'", personalNumber)); } } [TestMethod] public void ToString_EqualsNormalizedNumber() { Assert.AreEqual(new PersonalNumber("460126").ToString(), new PersonalNumber("460126").Number); } [TestMethod] public void Ctor_InvalidPersonalNumbers_ParsedAsNotValid() { TestLoop_InvalidPersonalNumbers(new[] { "127102240475", "19710XY40475", "19710224=0475", "1971", "14532436-45", "556194-7986", "262000-0113", "460531-12" }); } private static void TestLoop_InvalidPersonalNumbers(IEnumerable&lt;string&gt; personalNumbers) { foreach (var personalNumber in personalNumbers) { var pn = new PersonalNumber(personalNumber); Assert.IsFalse(pn.IsValid, string.Format("Pno = '{0}'", personalNumber)); } } [TestMethod] public void TwoNumbers_ConsideredEqual_IfNormalizedNumbersAreEqual() { new PersonalNumber("710224-0475"); Assert.IsTrue(new PersonalNumber("800212").Equals(new PersonalNumber("19800212"))); Assert.IsTrue(new PersonalNumber("800212").Equals(new PersonalNumber("800212"))); Assert.IsTrue(new PersonalNumber("8002121234").Equals(new PersonalNumber("19800212-1234"))); Assert.IsFalse(new PersonalNumber("800212").Equals(new PersonalNumber("900212"))); } [TestMethod] public void EqualsOperatorOverloaded_AsEquals() { Assert.IsTrue(new PersonalNumber("800212") == new PersonalNumber("19800212")); Assert.IsTrue(new PersonalNumber("800212") == new PersonalNumber("800212")); Assert.IsTrue(new PersonalNumber("8002121234") == new PersonalNumber("19800212-1234")); Assert.IsTrue(new PersonalNumber("800212") != new PersonalNumber("900212")); } [TestMethod] public void IsPlus100YearsOld() { Assert.IsFalse(new PersonalNumber("800213").IsPlus100YearsOld); Assert.IsFalse(new PersonalNumber("800213-0123").IsPlus100YearsOld); Assert.IsTrue(new PersonalNumber("800213+0123").IsPlus100YearsOld); } } </code></pre>
    singulars
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload