การ Validate วันที่เกิด (DateOfBirth) ให้ไม่อยู่ในอนาคต และไม่อายุเกินไป (เช่น > 120 ปี) ด้วย FluentValidation
หลักการ Validate
- Year ≤ Current Year (ไม่ใช่ปีหน้า)
- Year > Current Year - 120 (ไม่อายุเกิน 120 ปี)
- อาจเพิ่ม: ต้องมีอายุ ≥ 18 ปี (Business Rule)
ตัวอย่างโค้ดเต็ม
using FluentValidation;
using FluentValidation.Results;
using System;
using System.Collections.Generic;
public class PersonModel
{
public string FirstName { get; set; }
public string LastName { get; set; }
public decimal AccountBalance { get; set; }
public DateTime DateOfBirth { get; set; }
}
public class PersonValidator : AbstractValidator<PersonModel>
{
public PersonValidator()
{
RuleFor(p => p.DateOfBirth)
.Must(BeAValidDateOfBirth)
.WithMessage("'{PropertyName}' ไม่ถูกต้อง: ต้องไม่เป็นปีหน้า และอายุไม่เกิน 120 ปี");
// หรือเขียน Inline ได้
RuleFor(p => p.DateOfBirth)
.LessThanOrEqualTo(DateTime.Today)
.WithMessage("'{PropertyName}' ต้องไม่เป็นวันในอนาคต")
.GreaterThanOrEqualTo(DateTime.Today.AddYears(-120))
.WithMessage("'{PropertyName}' อายุต้องไม่เกิน 120 ปี");
}
// Custom Validation Method
private bool BeAValidDateOfBirth(DateTime date)
{
int currentYear = DateTime.Today.Year;
int dobYear = date.Year;
// ต้องไม่เกินปีปัจจุบัน และไม่น้อยกว่า 120 ปีที่แล้ว
return dobYear <= currentYear && dobYear > (currentYear - 120);
}
}
static void Main()
{
var person = new PersonModel
{
FirstName = "TestUser",
LastName = "TestUser",
AccountBalance = 100,
DateOfBirth = DateTime.Today.AddYears(1) // ปีหน้า - Invalid!
};
var validator = new PersonValidator();
ValidationResult result = validator.Validate(person);
if (!result.IsValid)
{
foreach (var failure in result.Errors)
{
Console.WriteLine($"[{failure.PropertyName}] {failure.ErrorMessage}");
}
}
else
{
Console.WriteLine("Validation Passed!");
}
}
ผลลัพธ์
[DateOfBirth] 'DateOfBirth' ไม่ถูกต้อง: ต้องไม่เป็นปีหน้า และอายุไม่เกิน 120 ปี
[DateOfBirth] 'DateOfBirth' ต้องไม่เป็นวันในอนาคต
วิธีอื่นๆ ที่มีประโยชน์
1. ตรวจสอบอายุขั้นต่ำ (เช่น ≥ 18 ปี)
RuleFor(p => p.DateOfBirth)
.Must(dob => dob <= DateTime.Today.AddYears(-18))
.WithMessage("ต้องมีอายุอย่างน้อย 18 ปี");
2. ใช้ LessThanOrEqualTo / GreaterThanOrEqualTo (Built-in)
RuleFor(p => p.DateOfBirth)
.LessThanOrEqualTo(DateTime.Today) // ไม่เกินวันนี้
.GreaterThanOrEqualTo(DateTime.Today.AddYears(-120)); // ไม่น้อยกว่า 120 ปีก่อน
3. Custom Validator แบบ Reusable
public class DateOfBirthValidator : PropertyValidator<DateTime>
{
private readonly int _minAge;
private readonly int _maxAge;
public DateOfBirthValidator(int minAge = 0, int maxAge = 120)
{
_minAge = minAge;
_maxAge = maxAge;
}
public override bool IsValid(ValidationContext<DateTime> context, DateTime value)
{
var today = DateTime.Today;
var minDate = today.AddYears(-_maxAge);
var maxDate = today.AddYears(-_minAge);
return value >= minDate && value <= maxDate;
}
protected override string GetDefaultMessageTemplate(string errorCode)
=> "วันที่เกิดต้องอยู่ระหว่าง {MinAge} ถึง {MaxAge} ปี";
}
// ใช้งาน
RuleFor(p => p.DateOfBirth).SetValidator(new DateOfBirthValidator(18, 120));
ข้อควรระวัง
- ใช้
DateTime.Today(Date Only) ไม่ใช่DateTime.Now(มี Time Component) - Time Zone: พิจารณาใช้
DateTimeOffsetหรือ UTC หากระบบ Multi-timezone - Leap Year: 29 Feb จัดการได้อัตโนมัติโดย DateTime