Как мне подтвердить номер австралийского Medicare? - PullRequest
14 голосов
/ 28 августа 2010

Я разрабатываю онлайн-форму, в которой необходимо будет подтвердить введенные пользователем номера Medicare.

(Моя конкретная проблема связана с номерами австралийской программы Medicare, но я рад получить ответы и на американские номера. Этот вопрос в целом касается номеров программы Medicare.)

Так как мне это сделать?

(Было бы хорошо, чтобы ответ был в Javascript или регулярном выражении.)

Ответы [ 10 ]

20 голосов
/ 05 апреля 2013

Регулярное выражение, предоставленное Джеффри Кемпом (11 марта), поможет проверить допустимые символы, но приведенного ниже алгоритма проверки должно быть достаточно для проверки того, что число соответствует правилам Medicare.

Номер карты Medicare содержит:

  • Восемь цифр;
  • Контрольная цифра (одна цифра);и
  • номер выпуска (одна цифра).

Примечание: первая цифра номера карты Medicare должна находиться в диапазоне от 2 до 6.

Расчет контрольной цифры номера карты Medicare

  1. Рассчитать сумму: ((цифра 1) + (цифра 2 * 3) + (цифра 3 * 7) + (цифра 4 * 9)) + (цифра 5) + (цифра 6 * 3) + (цифра 7 * 7) + (цифра 8 * 9))

, где цифра 1 - это наибольшая цифра значения карты Medicare.цифра и цифра 8 - это наименьшая цифра места в номере карты Medicare.

Пример: для номера карты Medicare '2123 45670 1', цифра 1 - 2, а цифра 8 - 7.

  1. Разделите рассчитанную сумму на 10.
  2. Контрольная цифра - это остаток.

Пример: Для номера карты Medicare2123 4567.

  1. (2) + (1 * 3) + (2 * 7) + (3 * 9) + (4) + (5 * 3) + (6 * 7) +(7 * 9) = 170
  2. Разделите 170 на 10. Остаток равен 0.
  3. Контрольная цифра для thномер Medicare равен 0.

Источник: «Использование идентификаторов здравоохранения в системах программного обеспечения для здравоохранения - требования к соответствию программного обеспечения, версия 1.4», NEHTA, 3/05/2011

4 голосов
/ 09 декабря 2016

Если вы ищете версию C #, попробуйте:

using System.Linq;

//...

public bool IsMedicareFormatValid(string medicareNumber)
{
    if (!(medicareNumber?.Length >= 10 && medicareNumber.Length <12) || !medicareNumber.All(char.IsDigit))
        return false;

    var digits = medicareNumber.Select(c => (int) char.GetNumericValue(c)).ToArray();
    return digits[8] == GetMedicareChecksum(digits.Take(8).ToArray());
}

private int GetMedicareChecksum(int[] digits)
{
    return digits.Zip(new[] { 1, 3, 7, 9, 1, 3, 7, 9 }, (m, d) => m*d).Sum() % 10;
}

Примечание: Это вернет false для нулевых значений, вы можете вызвать исключение.

Для уточнения:

  1. Первые 9 номеров в карточке медицинской помощи будут соответствовать фактическому номеру медицинской страховки (используется в чеке).
  2. 9-ая цифра является контрольной цифрой, рассчитанной по методу GetMedicareChecksum.
  3. 10-ая цифра обозначает номер карты, поэтому, если вы получили 3 карты (потому что вы их потеряли иликак бы то ни было), число будет 3
  4. 11-ая цифра будет обозначать члена семьи внутри группы.

Надеюсь, кто-то найдет это полезным.

2 голосов
/ 15 декабря 2015

Добавлена ​​версия Java

public static boolean isMedicareValid(String input, boolean validateWithIRN){
    int[] multipliers = new int[]{1, 3, 7, 9, 1, 3, 7, 9};
    String pattern = "^(\\d{8})(\\d)";
    String medicareNumber = input.replace(" " , "");
    int length = validateWithIRN ? 11 : 10;

    if (medicareNumber.length() != length) {return false;}

    Pattern medicatePattern = Pattern.compile(pattern);
    Matcher matcher = medicatePattern.matcher(medicareNumber);

    if (matcher.find()){

        String base = matcher.group(1);
        String checkDigit = matcher.group(2);

        int total = 0;
        for (int i = 0; i < multipliers.length; i++){
            total += base.charAt(i) * multipliers[i];
        }

        return ((total % 10) == Integer.parseInt(checkDigit));
    }

    return false;

}
1 голос
/ 11 декабря 2015

Добавлена ​​версия Swift

class func isMedicareValid(input : String, validateWithIrn : Bool) -> Bool {
    let multipliers = [1, 3, 7, 9, 1, 3, 7, 9]

    let pattern = "^(\\d{8})(\\d)"
    let medicareNumber = input.removeWhitespace()
    let length = validateWithIrn ? 11 : 10

    if medicareNumber.characters.count != length {return false}

    let expression = try! NSRegularExpression(pattern: pattern, options: NSRegularExpressionOptions.CaseInsensitive)

    let matches = expression.matchesInString(medicareNumber, options: NSMatchingOptions.ReportProgress, range: NSMakeRange(0, length))

    if (matches.count > 0 && matches[0].numberOfRanges > 2) {
        let base = medicareNumber.substringWithRange(medicareNumber.startIndex...medicareNumber.startIndex.advancedBy(matches[0].rangeAtIndex(1).length))
        let checkDigitStartIndex = medicareNumber.startIndex.advancedBy(matches[0].rangeAtIndex(2).location )
        let checkDigitEndIndex = checkDigitStartIndex.advancedBy(matches[0].rangeAtIndex(2).length)
        let checkDigit = medicareNumber.substringWithRange(checkDigitStartIndex..<checkDigitEndIndex)
        var total = 0

        for i in 0..<multipliers.count {
            total += Int(base.charAtIndex(i))! * multipliers[i]
        }

         return (total % 10) == Int(checkDigit)
    }
    return false
}

Я также использую некоторые строковые расширения, чтобы упростить некоторые операции.

extension String {

func charAtIndex (index: Int) -> String{
    var character = ""
    if (index < self.characters.count){
        let locationStart = self.startIndex.advancedBy(index)
        let locationEnd = self.startIndex.advancedBy(index + 1 )
        character = self.substringWithRange(locationStart..<locationEnd)
    }
    return character
}

func replace(string:String, replacement:String) -> String {
    return self.stringByReplacingOccurrencesOfString(string, withString: replacement, options: NSStringCompareOptions.LiteralSearch, range: nil)
}

func removeWhitespace() -> String {
    return self.replace(" ", replacement: "")
}
}
1 голос
/ 27 августа 2014

Принятый ответ, адаптированный к JavaScript:

var validator = function (input, validateWithIrn) {
    if (!input) {
        return false;
    }

    var medicareNumber;
    var pattern;
    var length;
    var matches;
    var base;
    var checkDigit;
    var total;
    var multipliers;
    var isValid;

    pattern = /^(\d{8})(\d)/;
    medicareNumber = input.toString().replace(/ /g, '');
    length = validateWithIrn ? 11 : 10;

    if (medicareNumber.length === length) {
        matches = pattern.exec(medicareNumber);
        if (matches) {
            base = matches[1];
            checkDigit = matches[2];
            total = 0;
            multipliers = [1, 3, 7, 9, 1, 3, 7, 9];

            for (var i = 0; i < multipliers.length; i++) {
                total += base[i] * multipliers[i];
            }

            isValid = (total % 10) === Number(checkDigit);
        } else {
            isValid = false;
        }
    } else {
        isValid = false;
    }

    return isValid;
};
1 голос
/ 11 марта 2013

Мой австралийский номер Medicare состоит из 11 цифр и не содержит букв или других символов.

Форматируется по группам, и последняя цифра зависит от члена моей семьи, например ::100100

  • Я: 5101 20591 8-1
  • Моя жена: 5101 20591 8-2
  • Мой первый ребенок: 5101 20591 8-3

Я видел номера медицинской помощи, отформатированные без пробелов и тире, но значение то же самое, поэтому я ожидал бы принять 51012059181 в качестве действительного номера медицинской помощи.

Я также видел контекст, в котором последняя цифра не требуется или не должна вводиться; например 5101205918, я думаю, где их интересует только семья в целом.

Поэтому я думаю, что это может быть уместно:

^\d{4}[ ]?\d{5}[ ]?\d{1}[- ]?\d?$

EDIT

Основываясь на логике в ответе user2247167, я использовал следующую функцию PL / SQL в своем приложении Apex, чтобы дать пользователю удобное предупреждение:

FUNCTION validate_medicare_no (i_medicare_no IN VARCHAR2)
  RETURN VARCHAR2 IS
  v_digit1 CHAR(1);
  v_digit2 CHAR(1);
  v_digit3 CHAR(1);
  v_digit4 CHAR(1);
  v_digit5 CHAR(1);
  v_digit6 CHAR(1);
  v_digit7 CHAR(1);
  v_digit8 CHAR(1);
  v_check  CHAR(1);
  v_result NUMBER;
BEGIN
  IF NOT REGEXP_LIKE(i_medicare_no, '^\d{10}\d?{2}$') THEN
    RETURN 'Must be 10-12 digits, no spaces or other characters';
  ELSE
    v_digit1 := SUBSTR(i_medicare_no, 1, 1);
    IF v_digit1 NOT IN ('2','3','4','5','6') THEN
      RETURN 'Not a valid Medicare number - please check and re-enter';
    ELSE
      v_digit2 := SUBSTR(i_medicare_no, 2, 1);
      v_digit3 := SUBSTR(i_medicare_no, 3, 1);
      v_digit4 := SUBSTR(i_medicare_no, 4, 1);
      v_digit5 := SUBSTR(i_medicare_no, 5, 1);
      v_digit6 := SUBSTR(i_medicare_no, 6, 1);
      v_digit7 := SUBSTR(i_medicare_no, 7, 1);
      v_digit8 := SUBSTR(i_medicare_no, 8, 1);
      v_check  := SUBSTR(i_medicare_no, 9, 1);
      v_result := mod(   to_number(v_digit1)
                      + (to_number(v_digit2) * 3)
                      + (to_number(v_digit3) * 7)
                      + (to_number(v_digit4) * 9)
                      +  to_number(v_digit5)
                      + (to_number(v_digit6) * 3)
                      + (to_number(v_digit7) * 7)
                      + (to_number(v_digit8) * 9)
                     ,10);
      IF TO_NUMBER(v_check) != v_result THEN
        RETURN 'Not a valid Medicare number - please check and re-enter';
      END IF;
    END IF;
  END IF;
  -- no error
  RETURN NULL;
END validate_medicare_no;
0 голосов
/ 20 июня 2019

Вы можете использовать простую проверку регулярных выражений: .replace (/ \ W / gi, "") .replace (/ (. {4}) (. {5}) / g, "$ 1 $ 2");

посмотрите мой пример здесь: codesandbox.io

0 голосов
/ 14 сентября 2018

Вот Typescript или современное решение Javascript:

  validateMedicare(medicare) {
    let isValid = false;

    if (medicare && medicare.length === 10) {
      const matches = medicare.match(/^(\d{8})(\d)/);

      if (!matches) {
        return { invalid: true };
      }

      const base = matches[1];
      const checkDigit = matches[2];
      const weights = [1, 3, 7, 9, 1, 3, 7, 9];

      let sum = 0;
      for (let i = 0; i < weights.length; i++) {
        sum += parseInt(base[i], 10) * weights[i];
      }

      isValid = sum % 10 === parseInt(checkDigit, 10);
    }

    return isValid;
  }

Пожалуйста, обратитесь к http://clearwater.com.au/code/medicare для объяснения.

Чтобы проверить, сгенерируйте номер Medicare здесь: https://precedencehealthcare.com/rmig/

0 голосов
/ 29 ноября 2017

Вы можете создать Атрибут подтверждения для подтверждения номера Medicare

Вы можете использовать его по

[AustralianMedicareNumberOnly]
public string MedicareNo { get; set; }

код

public class AustralianMedicareNumberOnlyAttribute : ValidationAttribute
{
    private string exampleNumber = "Example: 2234 56789 1-2";

    public AustralianMedicareNumberOnlyAttribute()
    {
        ErrorMessage = string.Concat("{0} is not in correct format, ", exampleNumber);
    }

    protected override ValidationResult IsValid(object value, ValidationContext validationContext)
    {
        if (value != null)
        {
            string objectValueString;
            int[] checksumDigits = new int[] { 1, 3, 7, 9, 1, 3, 7, 9 };
            int checksumDigit;
            int checksumtotal = 0;
            int checksumDigitCalculated;

            //convert incomming object value to string
            objectValueString = Convert.ToString(value).Trim();

            // check medicare number format should be 1234 56789 1-2
            if (!Regex.IsMatch(objectValueString, @"^[2-6]\d{3}\s\d{5}\s\d{1}-\d{1}$"))
            {
                return new ValidationResult(FormatErrorMessage(validationContext.DisplayName));
            }
            else
            { 
                //Check checksum value
                //--------------------

                // replace two spaces and one dash
                objectValueString = objectValueString.Replace(" ", "").Replace("-", "");

                // Calculate the sum of: ((digit 1) + (digit 2 * 3) + (digit 3 * 7) + (digit 4 * 9) + (digit 5) + (digit 6 * 3) + (digit 7 * 7) + (digit 8 * 9))
                for (int i = 0; i < checksumDigits.Length; i++)
                {
                    int digit = Convert.ToInt32(objectValueString.Substring(i, 1));

                    checksumtotal += digit * checksumDigits[i];
                }

                //find out checksum digit
                checksumDigit = Convert.ToInt32(objectValueString.Substring(8, 1));
                checksumDigitCalculated = checksumtotal % 10;

                // check calculated checksum with medicare checksum digit
                if (checksumDigit!= checksumDigitCalculated)
                {
                    return new ValidationResult("The Medicare Number is not Valid.");
                }

            }

        }

        return ValidationResult.Success;
    }
}
0 голосов
/ 28 августа 2010

Я нашел обсуждение на форуме по теме:

http://regexadvice.com/forums/thread/57337.aspx

Я собираюсь попробовать тот, который придумал австралиец Сьюзан:

^\d{9}B[ADGHJKLNPQRTWY1-9,]?$
...