Posts with tag: UnitTest

While creating a unit tests I tried to find code to generate Swedish personnumbers but couldent really find any copy paste pieces of code. So to remedy that here is a method which will generate a valid Swedish "Personnummer"

I tried to get it down to a single line but this is as close as I got before realising I have better things to do. If someone can make this into a single line of code I'd love to see that in a comment ;)

public string GeneratePersonNumber()
{
    // Create first numbers
    var pNum = (
                        (DateTime.UtcNow.AddYears(-10 - (new Random()).Next(0, 50))).ToString("yyyyMMdd")
                        + (new Random()).Next(100, 999).ToString()
                    );

    // get the control value sum
    var total = string.Join(string.Empty,
                        pNum.Substring(2, pNum.Length - 2)
                            .Select((value, i) =>
                                ((int)(value - '0')) * (2 - (i % 2)))
                            ).Sum(c => c - '0');

    // add the control value to the number
    return (pNum += (Math.Ceiling(total / 10d) *10) - total);
}

 

Update: Ok so I coulden't let it go and spent a few more minutes trying golf the code down in size. This is the shortest I managed, it's 189 characters long. Not very readable but it does generate a valid personnummer of a person between the ages of 10 and 60. Still coulden't manage to make it in one line of code though.

public string GenereatePersonNumber()
{
    var p = DateTime.Now.AddDays(-3650-new Random().Next(18250)).ToString("yyyyMMddfff");
    return p + (10 - string.Join("", p.Select((v, i) => i > 1 ? (v - '0') * (2 - i % 2):0)).Sum(c => c - '0') % 10);
}

Here are 3 sample personnummer/social security numbers generated by the above code: 

  1. 199307242652
  2. 197512275202
  3. 197611112835

 

Update 2: As per the request in the comment here is a version of the code where you can set the age of the person whom you are want the personnumber to be generated for. Also included the unit test I used as this code is a little trickier.

public string GenereatePersonNumber(int age)
{
    var r = new Random(DateTime.Now.Millisecond);
    var p = (new DateTime(DateTime.Now.AddYears(-age).Year, 1, 1, 0, 0, 1, DateTime.Now.Millisecond, DateTimeKind.Local))
                   .AddDays(1 + r.Next(0, (int) (DateTime.Now - new DateTime(DateTime.Now.Year, 1, 1)).TotalDays)).ToString("yyyyMMddfff");
    var ctr = (10 - string.Join("", p.Select((v, i) => i > 1 ? (v - 48) * (2 - i % 2) : 0)).Sum(c => c - 48) % 10);
    ctr = ctr == 10 ? 0 : ctr;
    return (p + ctr);
}

Also including the unit test for this code if you want to validate that it actully produces propper values.

[TestMethod]
public void GeneratePersonNummerTest()
{
    var pn = new List<string>();
    Parallel.ForEach(Enumerable.Range(0, 1000), x =>
    {
        foreach (var r in Enumerable.Range(0, 80))
        {
            var number = GenereatePersonNumber(r);
   
            var birthdate = new DateTime(int.Parse(number.Substring(0, 4)), int.Parse(number.Substring(4, 2)), int.Parse(number.Substring(6, 2)));
            var today = DateTime.Now;
            var age = today.Year - birthdate.Year;
            if (birthdate > today.AddYears(-age)) age--;
   
            pn.Add(number);

            Assert.IsTrue(age == r);
        }
    });
}

Some tags (in Swedish) which might help people searching for this: Generera personnummer med C# kod. Personnummer, Generera, Svenskt personnummer, Skapa personnummer för test, fejka personnummer. Generera personnummer i C#.