Code Monkey home page Code Monkey logo

meta's Introduction

meta

Organization meta. Find all implementations on personnummer.dev.

Package meta

Every package should have .meta.yaml file containing information about the name, maintainer, specification version and which workflow file to show the build badge from. The values of the meta file will be used for the implementations table on personnummer.dev

Example of .meta.yaml

name: "JavaScript"
maintainer: "@frozzare"
spec: 3.1
workflow: "nodejs.yml"

License Specification

We use the MIT license for all packages and the copyright row should look like this:

Copyright (c) Personnummer and Contributors

Package Specification (v1)

The personnummer package should have a valid method that can take both a number and a string as input.

personnummer.valid(string)
personnummer.valid(number)

Package Specification (v2)

The personnummer package should have a valid method that can take both a number and a string as input.

The second argument should be a optional boolean that exclude coordination number (Samordningsnummer) from validation.

personnummer.valid(string, [bool includeCoordinationNumber = true])
personnummer.valid(number, [bool includeCoordinationNumber = true])

The package should include a format method that can format the input value (string or number) as a short or long personnumer.

The second argument should be a optional boolean and true should format the input value as a long personnummer.

personnummer.format(number, [bool longFormat = false])
personnummer.format(string, [bool longFormat = false])

The package should include a getAge method that returns the age from a personnummer. For coordination number (Samordningsnummer) we should remove 60 to get the right age.

The second argument should be a optional boolean that exclude coordination number (Samordningsnummer) from validation.

personnummer.getAge(number, [bool includeCoordinationNumber = true])
personnummer.getAge(string, [bool includeCoordinationNumber = true])

Input value format

Dash or plus should be optional.

YYMMDD-XXXX
YYMMDD+XXXX
YYMMDDXXXX

YYYYMMDD-XXXX
YYYYMMDD+XXXX
YYYYMMDDXXXX

Coordination number (Samordningsnummer) should also be a valid personnummer.

Short format

Output for format method

YYMMDD-XXXX

Long format

Output for format method

YYYYMMDDXXXX

Package Specification (v2.1)

This specification adds new features and includes all parts from 2.0.

The package should include isMale and isFemale methods that can check if the personnummer or coordination number is a female or male.

personnummer.isMale(number|string, [bool includeCoordinationNumber = true])
personnummer.isFemale(number|string, [bool includeCoordinationNumber = true])

This methods should throw errors when input value is not a valid personnummer or coordination number.

Package Specification (v3)

Version 3 will contain breaking changes and will not be compatible with version 1 or 2.

Breaking changes

These functions will be moved into the class:

  • format
  • getAge
  • isFemale
  • isMale

Valid

The valid function can be a function or a static method on the class depending on language. The valid version that supports number arguments will be removed.

Class

The package should include a class that which should be the return value of parse

class Personnummer {
    public function __construct(string, array|object|languageSpecific)
}

Parse

The package should include a parse method that creates a new instance of the new class.

The parse and the class constructor should contain a second argument with options for the feature.

personnummer.parse(string, array|object|languageSpecific = []) => new class instance

The class should contain a static parse method that returns the class instance.

const pnr = Personnummer::parse(string, array|object|languageSpecific = [])

Coordination numbers

The coordination number option will be removed for all methods and be replaced with isCoordinationNumber method or property instead.

const pnr = personnummer.parse(string)

if (pnr.isCoordinationNumber()) {
    return
}

Error handling

All methods except for valid should throw an exception or return an error as a second return value. Error handling may be different depending on language. The exception/error class should be prefixed with Personnummer

Options

Options may be different depending on language.

Pseudo-interface

interface Personnummer {
    string century;
    string fullYear;
    string year;
    string month;
    string day;
    string sep;
    string num;
    string check;

    public function __construct(string ssn, array|object|languageSpecific options = []);

    public static function parse(string ssn);

    public function format(boolean longFormat) : string;
    public function getAge() : int;
    public function isFemale() : boolean;
    public function isMale() : boolean;
    public function isCoordinationNumber() : boolean;
}

function valid(string ssn) {
    try {
       parse(ssn)
       return true
    } catch (PersonnummerParseException) {
        return false
    }
}

function parse(string ssn, array|object|languageSpecific options = []) {
    return new Personnummer(ssn, options)
}

Package Specification (v3.1)

This specification adds new features and includes all parts from 3.0.

Get date

The package should include getDate function to expose the underlying date value. For coordination numbers the day should be removed with 60 days to get the correct day for a real date.

Interim-Number

Also called T-Number

The package should support Interim-numbers YYMMDD-Xnnn (where X is a letter rather than number) and include isInterimNumber function in the same way as isCoordinationNumber

The format function should respect Interim-number and format the number both in the long and short way with the letter at the first of the four in the 4-digit number.

Read more about interim-number at KTH and at sunet.

To make the package future-proof, we support all 11 interim letters: T, R, S, U, W, X, J, K, L, M, N where all are replaced with a 1 in the luhn calculation.

To not break the package for users whom do not want to make use of the interim-number implementation, the options object for the parse function and constructor have been re-added and should have two values:

{
  "allowCoordinationNumber": true,
  "allowInterimNumber": false
}

As seen, the coordination-number should be true by default (as it's true by default in the v3.0 api) while the interim-number is false by default (as it does not exist yet and is used a lot more rarely).

Updated pseudo-interface

interface Personnummer {
    public function getDate() : Date;
    public function isInterimNumber() : boolean;
}

meta's People

Contributors

buscedv avatar frozzare avatar johannestegner avatar johanrosenson avatar rasmusbe avatar voxsecundus avatar

Stargazers

 avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar

Forkers

johannestegner

meta's Issues

[feature] GetAge

A feature request was made in the php package ( personnummer/php#11 ) in which a function to get age from a personnummer is requested.

I think the idea is valid, but it makes it hard when it comes to coordination numbers due to it adding +60 to the day (although it would be easy enough to see if it is one or not and in that case subtract 60 i guess!).

So request: Add a GetAge(personnummer) method.

[FEATURE] - Descriptive exceptions.

The current implementations (might be exceptions! :) ) have quite generic error messages. We should go through the cases where we throw errors and create a list of actual error messages which could be used over the different solutions.

I'm alright with it differing slightly over the various packages, but the more "standard" the better.

Example:
Error thrown on parse returns (in some packages at the least) "Invalid personnummer".

This doesn't say much.

If it threw a PersonnummerException with the message "Month out of range", it would be a lot easier to see what went wrong.

Copyright row in license file

Right now we have different ways to write the copyright row in the license files:

go:

Copyright (c) 2014-2019

dart:

Copyright (c) Personnummer

php:

Copyright (c) 2014-2017

What way should we use? @Johannestegner

Spec v3.0

Let's add stuff that the 3.0 specification should include.

  • getAge and format should throw errors.

Improve format method

We should replace the separator if it's wrong. Those packages that contains a getParts method or something like that should do it in that method. Packages that don't have a getParts method should create one and add it there.

19130401-2931 => 19130401+2931

[FEATURE] - More ways to format a personnummer

Description

Currently this package only supports two ways to format a personnummer default: 830621-9299 and long: 198306219299. In my experience, there are generally four ways that a personnummer is usually structured:

short: 8306219299
long: 198306219299
separated short: 830621-9299
separated long: 19830621-9299

My proposal is to implement a way to format personnummer in more ways that two. But more importantly make the package able to support more that two formats without breaking.

Implementation

Instead of passing a boolean to the format function you pass a format type. This should ideally be created with a class which can be extended and make it possible to create more formats down the line.

Example implementation:

abstract class FormatType {
    abstract format(personnummer: Personnummer): string;
}

class FormatSmall extends FormatType {
    format(personnummer: Personnummer) {
        const { year, month, day, num, check } = personnummer;
        return `${year}${month}${day}${num}${check}`;
   }
}

class Personnummer {
   ...
    
    format(format: FormatType) {
        return format.format(this);
    }

    // We could also include functions for every format that is included in this library
    formatSmall() {
        return this.format(new FormatSmall());
    }

   ...
}

And alternative implementation is using enums / strings with different format types

enum FormatType {
    Small,
    Long
}

class Personnummer {
   ...
    
    format(format: FormatType) {
        switch(format) {
            case FormatType.Small:
                return "formatted personnummer";
        }
    }

   ...
}

This solution is less extendable and doesn't allow people to implement their own format functions. However this solution is simpler and is easier to implement in language such as Bash and Haskell (I don't have very much experience in any of those languages so I'm not if the first implementation is even possible in them).

Breaking changes

Depending on how this is implemented this could be breaking. Ideally the old boolean system should be removed completely. However the old function could still be accessible either trough overloads or joint types. I would advocate to remove the old system completely since this package is rather small and it shouldn't be to complicated to migrate to the new function if you decide to update to the newest version.

[Q] - Whitespace as the separator โ€“ acceptable?

Howdy! Writing some tests for a PHP-package I'm maintaining olssonm/swedish-entity that's built upon personnummer/php and I've encountered an oddity.

A whitespace as the separator seems to be accepted at the moment; i.e. 600411 8177 (or even with a tab instead of space) is returned as valid. This seems to be from the regex that's being used (I've only checked the PHP and JS-packages);

$reg = '/^(?\'century\'\d{2}){0,1}(?\'year\'\d{2})(?\'month\'\d{2})(?\'day\'\d{2})(?\'sep\'[\+\-\s]?)(?\'num\'(?!000)\d{3})(?\'check\'\d)$/';

There the separator, (?\'sep\'[\+\-\s]?), accepts +,- or whitespace.

The thing is though; I can't find any references that a whitespace should be valid for use in a personnummer or what the meaning would be.

Is this intended behaviour, or am I missing something? ๐Ÿ™ƒ

[FEATURE] - Get date of birth

Description

I have been using this api in other projects and found that as a consumer I end up doing things like this:

const pnr = Personnummer.parse(personalIdentityNumber);

const { fullYear: year, month, day: dayString } = pnr;

let day = parseInt(dayString, 10);
if (pnr.isCoordinationNumber()) {
  day = day - 60;
}

const birthDate = new Date(`${year}-${month}-${day}`);

With the goal of getting a date and then working with the date to get diffs in different units, such as months, days or years. With getAge that already exists I lose some granularity such as months.

It would be great to able to have a Date to work with to integrate nicely with other date libraries and getting difference in months or other units besides just year. And also avoiding having to know about coordination numbers in my consuming code. In my example I have to check if the personal identity number is a coordination number to figure out the date of birth.

Breaking changes

[feature] - Sex identifier.

If reading the wiki article about personal identiy numbers, the third digit in the last four numbers is used to identify sex/gender (male odd, female even). We could easily introduce a function to fetch this from a number if wanted, but I'm not really sure it's a needed functionallity... What do you thing @frozzare ?

A feature request have been added earlier in the PHP repository: personnummer/php#11

Ref wiki:

Among the four last digits, the three first are a serial number. For the last digit among these three, an odd number is assigned to males and an even number to females.

Personnummer object

I have been thinking a bit about the codebase and current implementation as a static class that takes a number or string as argument in all cases...

I personally feel that it could be an idea to introduce a parse method to the static class, which returns a object (personnumer) which could store the information (if it is a valid number). That way one could invoke the methods that are added to the lib directly on a stored instance instead of always using the static class.

This would not change the current API and I do think that all methods in the current implementations should stay as they are and any new also introduced to the static class, this would just open up for a more object oriented type of approach to it.

What do you think about this idea @frozzare ? Too much for the lib maybe? Or do we want to add aditional complexity to the packages?

Proposal: get real day method

Today we can get the day from a social security number by a class property $p->day but that's not always the real day, e.g for coordination numbers.

I propose that we add a new method that can return the real day for both social security numbers and coordination numbers. Not sure about what the best name for the method is.

// the provided day
$p->day

// the real day
$p->getDay()

You should abandon the isValid method in V3

I have some feedback regarding the V3 spec. I think you might need to reconsider a few decisions regarding errors and the isValid method.

According to the spec, an SSN should be validated with Personnummer(ssn, options)->isValid().

The issue with this approach is that the Personnumer object will be initialized in the constructor. So passing an invalid SSN should not allow the initialization to complete and should raise/throw during the initialization of the object.

The following code should fail and raise an error, so in theory, the isValid should always return true.

ssn = new Personnummer('not-a-valid-ssn')

So to verify an SSN, it should be like so (pseudo-code):

function valid(string ssn) {
    try {
       parse(ssn)
       return true
    } catch (ParseException) {
        return false
    }
}

function parse(string ssn, array|object|languageSpecific options = []) {
    return new Personnummer(ssn, options)
}

Coordination number difference

Hi!

I'm trying to create an Elixir package while using the csharp project as inspiration and it's going pretty well.
However I don't seem to be able to clear the co-ordination tests for some reason. I've used the exact same test data as the csharp project. Are there different rules of validation for co-ordination numbers?

If you want to check out the project here's a link.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.