CheckFutureDateRule
The CheckFutureDateRule validates that a date is in the future based on the language's calendar system and client timezone.
Namespace
JobMetric\Language\Rules\CheckFutureDateRule
Overview
This rule validates future dates considering:
- Language's calendar system (Gregorian, Jalali, Hijri, Hebrew, etc.)
- Client timezone (set by
SetTimezoneMiddleware) - Multi-calendar support (automatically converts calendar dates)
- Persian/Arabic numerals (supports localized number formats)
- Unchanged value bypass (skips validation if date hasn't changed on update)
Usage
Basic Usage
use JobMetric\Language\Rules\CheckFutureDateRule;
$request->validate([
'event_date' => ['required', new CheckFutureDateRule()],
]);
With Unchanged Value Bypass (Update Scenarios)
// When updating, skip validation if date hasn't changed
$event = Event::find($id);
$request->validate([
'event_date' => [
'required',
new CheckFutureDateRule(
Event::class, // Model class
$event->id, // Model ID
'event_date', // Field name
false // assumeEndOfDay
)
],
]);
With End of Day Policy
// Treat date-only inputs as end of day (23:59:59)
$request->validate([
'deadline' => [
'required',
new CheckFutureDateRule(null, null, null, true) // assumeEndOfDay = true
],
]);
Parameters
$modelClass(string|null): Model class for unchanged-value bypass$modelId(int|null): Model ID for unchanged-value bypass$modelField(string|null): Field name for unchanged-value bypass$assumeEndOfDay(bool): If true, date-only inputs treated as 23:59:59 (default: false)
Supported Input Formats
The rule supports multiple input formats:
Calendar Formats
- Gregorian:
2024-12-25,2024/12/25,2024.12.25 - Jalali:
1403-09-05(Persian calendar) - Hijri:
1446-06-15(Islamic calendar) - Other calendars: Hebrew, Buddhist, Coptic, Ethiopian, Chinese
Date and Time Formats
- Date only:
2024-12-25(treated as 00:00:00 or 23:59:59 based onassumeEndOfDay) - Date with time:
2024-12-25 14:30:00 - ISO 8601:
2024-12-25T14:30:00Z - Unix timestamp:
1703520000
Number Formats
- English numerals:
2024-12-25 - Persian numerals:
۱۴۰۳-۰۹-۰۵ - Arabic numerals:
٢٠٢٤-١٢-٢٥
When to Use CheckFutureDateRule
Primary Use Cases
1. Event Scheduling
When: Creating events that must occur in the future.
Why: Prevents scheduling events in the past, which would be invalid.
Example:
// app/Http/Requests/StoreEventRequest.php
use JobMetric\Language\Rules\CheckFutureDateRule;
public function rules(): array
{
return [
'title' => 'required|string',
'event_date' => ['required', new CheckFutureDateRule()],
'description' => 'nullable|string',
];
}
Real-World Scenario: Event management system. User creates an event - rule ensures the event date is in the future.
2. Appointment Booking
When: Booking appointments that must be scheduled ahead of time.
Why: Ensures appointments can only be booked for future dates.
Example:
// app/Http/Requests/StoreAppointmentRequest.php
use JobMetric\Language\Rules\CheckFutureDateRule;
public function rules(): array
{
return [
'doctor_id' => 'required|exists:doctors,id',
'appointment_date' => ['required', new CheckFutureDateRule()],
'reason' => 'nullable|string',
];
}
Real-World Scenario: Healthcare appointment system. Patient books appointment - rule ensures it's for a future date.
3. Deadline Management
When: Setting deadlines that must be in the future.
Why: Prevents setting past deadlines, which would be meaningless.
Example:
// app/Http/Requests/StoreTaskRequest.php
use JobMetric\Language\Rules\CheckFutureDateRule;
public function rules(): array
{
return [
'title' => 'required|string',
'deadline' => [
'required',
new CheckFutureDateRule(null, null, null, true) // End of day
],
];
}
Real-World Scenario: Task management system. User sets deadline - rule ensures it's in the future, treating date-only as end of day.
4. Update Scenarios with Unchanged Value Bypass
When: Updating records where the date might not change.
Why: Avoids unnecessary validation errors when the date hasn't changed.
Example:
// app/Http/Requests/UpdateEventRequest.php
use JobMetric\Language\Rules\CheckFutureDateRule;
public function rules(): array
{
$event = $this->route('event');
return [
'title' => 'required|string',
'event_date' => [
'required',
new CheckFutureDateRule(
Event::class,
$event->id,
'event_date',
false
)
],
];
}
Real-World Scenario: Editing an event. If user doesn't change the date, validation passes. If changed, validates it's still in the future.
5. Multi-Calendar Support
When: Users input dates in their local calendar system (Jalali, Hijri, etc.).
Why: Automatically converts and validates dates regardless of calendar system.
Example:
// Persian user inputs Jalali date
$request->validate([
'event_date' => ['required', new CheckFutureDateRule()],
]);
// Input: "1403-09-05" (Jalali)
// Rule converts to Gregorian and validates it's in the future
Real-World Scenario: Persian users input dates in Jalali calendar. Rule automatically handles conversion and validation.
6. Timezone-Aware Validation
When: Validating dates considering user's timezone.
Why: Ensures dates are validated in the user's local timezone, not server timezone.
Example:
// User in New York timezone
// Server in UTC
$request->validate([
'event_date' => ['required', new CheckFutureDateRule()],
]);
// Input: "2024-12-25 23:00:00" (New York time)
// Rule validates in New York timezone, not UTC
Real-World Scenario: Global event system. User in Tokyo books event - rule validates in Tokyo timezone.
When NOT to Use
- Past Date Validation: Don't use for validating past dates - this rule only validates future dates
- Date Format Validation: Don't use for format validation - use
dateordate_formatrules - Required Validation: Don't use as a replacement for
required- combine withrequired - Simple Date Checks: If you don't need calendar/timezone awareness, use simpler validation
Decision Tree
Do you need to validate a future date?
├─ Yes → Does it need calendar system support?
│ ├─ Yes → Use CheckFutureDateRule()
│ └─ No → Use simple 'after:now' rule
└─ No → Don't use this rule
Common Mistakes to Avoid
-
Not combining with 'required':
// ❌ Wrong - allows empty values
'event_date' => [new CheckFutureDateRule()]
// ✅ Correct - validates presence and future
'event_date' => ['required', new CheckFutureDateRule()] -
Using for past dates:
// ❌ Wrong - this rule only validates future dates
'birth_date' => [new CheckFutureDateRule()]
// ✅ Correct - use 'before:now' for past dates
'birth_date' => ['required', 'date', 'before:now'] -
Not using unchanged-value bypass on updates:
// ❌ Wrong - will fail if date hasn't changed
'event_date' => [new CheckFutureDateRule()]
// ✅ Correct - skips validation if unchanged
'event_date' => [
new CheckFutureDateRule(Event::class, $event->id, 'event_date')
] -
Wrong assumeEndOfDay usage:
// ❌ Wrong - might not match user expectation
'deadline' => [new CheckFutureDateRule()] // Treated as 00:00:00
// ✅ Correct - deadline is end of day
'deadline' => [
new CheckFutureDateRule(null, null, null, true) // 23:59:59
]
Best Practices
-
Always combine with 'required':
'date' => ['required', new CheckFutureDateRule()] -
Use unchanged-value bypass for updates:
new CheckFutureDateRule(Model::class, $id, 'field_name') -
Set assumeEndOfDay for deadlines:
new CheckFutureDateRule(null, null, null, true) -
Ensure SetTimezoneMiddleware is registered:
// app/Http/Kernel.php
protected $middlewareGroups = [
'web' => [
\JobMetric\Language\Http\Middleware\SetTimezoneMiddleware::class,
],
];