我的正则表达式有问题。我已经能够确定正确的瑞典社会安全号码以符合这些标准。
但如果用户未满18岁,我还想拒绝用户注册。我的reqular表达目前看起来像这样:有没有人遇到与年龄范围瑞典SSN相同的问题?
private const string RegExForValidation =
@"^(\d{6}|\d{8})[-|(\s)]{0,1}\d{4}$";
更新
private const string RegExForValidation = @"^(?<date>\d{6}|\d{8})[-\s]?\d{4}$";
string date = Regex.Match("19970918-1234", RegExForValidation).Groups["date"].Value;
DateTime dt;
[Required(ErrorMessage = "Du måste ange personnummer")]
[RegularExpression(RegExForValidation, ErrorMessage = "Personnummer anges med 10 siffror (yymmddnnnn)")]
public string PersonalIdentityNumber { get; set; }
第二次更新
public class ValidateOfAge : ValidationAttribute
{
public bool IsOfAge(DateTime birthdate)
{
DateTime today = DateTime.Today;
int age = today.Year - 18;
if (birthdate.AddYears(birthdate.Year) < today.AddYears(-age))
return false;
else
return true;
}
protected override ValidationResult IsValid(object value, ValidationContext validationContext)
{
string RegExForValidation = @"^(?<date>\d{6}|\d{8})[-\s]?\d{4}$";
string date = Regex.Match((string)value, RegExForValidation).Groups["date"].Value;
DateTime dt;
if (DateTime.TryParseExact(date, new[] { "yyMMdd", "yyyyMMdd" }, CultureInfo.InvariantCulture, DateTimeStyles.None, out dt))
if (IsOfAge(dt))
return ValidationResult.Success;
return new ValidationResult("Personnummer anges med 10 siffror (yymmddnnnn)");
}
}
答案 0 :(得分:3)
这是我不会使用正则表达式的情况,而是依赖于基类库的内置DateTime解析功能:
public DateTime GetBirthDate(string ssn)
{
var strippedOfSerial =
ssn.Substring(0, ssn.Length - 4).TrimEnd('-');
return DateTime.ParseExact(
strippedOfSerial,
new[] { "yyMMdd", "yyyyMMdd" },
new CultureInfo("se-SE"),
DateTimeStyles.None);
}
现在,您可以查看返回的DateTime
值,并将其与DateTime.Now
进行比较,以确定是否要拒绝它。
在我看来,这比依赖正则表达式更具可读性,并且可能更安全,更灵活。如您所知,您可以例如使用其他文化等来调整解析策略。
答案 1 :(得分:1)
您需要从SSN获取生日,解析为DateTime,然后与今天的日期进行比较。
以下是检查某人是否年龄的方法:
public bool IsOfAge(DateTime birthdate)
{
DateTime today = DateTime.Today; // Calculating age...
int age = today.Year - birthdate.Year;
if (birthdate > today.AddYears(-age))
age--;
return age < 18 ? false : true; // If the age is 18+ > true, else false.
}
以下是您可以使用的方法:
string RegExForValidation = @"^(?<date>\d{6}|\d{8})[-\s]?\d{4}$";
string date = Regex.Match("19970918-1234", RegExForValidation).Groups["date"].Value;
DateTime dt;
if (DateTime.TryParseExact(date, new[] { "yyMMdd", "yyyyMMdd" }, new CultureInfo("sv-SE"), DateTimeStyles.None, out dt))
Console.WriteLine(IsOfAge(dt));
请注意,[-|(\s)]
与-
,|
,(
,空格或)
匹配。我相信你只想匹配一个连字符或空格。
我在正则表达式中添加了一个命名捕获,并从字符类中删除了不必要的符号。另请注意,{0,1}
与?
相同。
<强>更新强>
要使其在MVC应用程序中运行,您需要实现自定义验证器:
[Required(ErrorMessage = "Du måste ange personnummer")]
[ValidateOfAge] // <---------------------------- HERE
public string PersonalIdentityNumber { get; set; }
并按如下方式实施:
public class ValidateOfAge: ValidationAttribute
{
protected override ValidationResult IsValid(object value, ValidationContext validationContext)
{
string RegExForValidation = @"^(?<date>\d{6}|\d{8})[-\s]?\d{4}$";
string date = Regex.Match((string)value, RegExForValidation).Groups["date"].Value;
DateTime dt;
if (DateTime.TryParseExact(date, new[] { "yyMMdd", "yyyyMMdd" }, new CultureInfo("sv-SE"), DateTimeStyles.None, out dt))
if (IsOfAge(dt))
return ValidationResult.Success;
return new ValidationResult("Personnummer anges med 10 siffror (yymmddnnnn)");
}
}
答案 2 :(得分:0)
建议不要查看自定义的RegEx,而是查看可用的NuGet程序包,该程序包可以解析有效的瑞典个人身份号码,然后提取诸如DateOfBirth,Age,Gender等信息,这些信息可以用作您的输入验证。方法.GetAge()
与您的情况最相关。 免责声明:我是该软件包的合著者之一。
使用ValidateOfAge
的{{1}}的实现如下所示:
SwedishPersonalIdentityNumber
public class ValidateOfAge : ValidationAttribute
{
protected override ValidationResult IsValid(object value, ValidationContext validationContext)
{
if (SwedishPersonalIdentityNumber.TryParse((string)value, out var personalIdentityNumber))
{
if(personalIdentityNumber.GetAge() >= 18) {
return ValidationResult.Success;
} else {
return new ValidationResult("Du måste vara minst 18 år gammal.");
}
}
return new ValidationResult("Ogiltigt personnummer.");
}
}
支持您描述的模式,包括更多有效的模式(例如,您是否知道PIN可以包含+吗?)。
第二个包含一个验证属性,用于验证模型中的PIN。 如果验证年龄的用例足够普遍,我们可以将其实现到该验证属性中。我created an issue来了解兴趣和设计。
目前建议的API设计如下(针对您的情况):
SwedishPersonalIdentityNumber
如果您希望实现此目标,请分享您对该问题的想法。