Flutter DatePicker: How to Use SelectableDayPredicate to Limit to Weekdays Only

Flutter’s showDatePicker is a powerful widget for letting users select dates, but by default, it allows selection of all days—including weekends. In many apps (e.g., booking platforms, work schedulers), you might need to restrict users to weekdays only (Monday–Friday). This is where SelectableDayPredicate comes in.

In this blog, we’ll dive deep into how to use SelectableDayPredicate to disable weekends (Saturdays and Sundays) in Flutter’s DatePicker. We’ll cover the basics, step-by-step implementation, customization options, and common pitfalls to avoid. By the end, you’ll have full control over which days users can select.

Table of Contents#

  1. Prerequisites
  2. Understanding SelectableDayPredicate
  3. Step-by-Step Implementation: Limit to Weekdays
  4. Customization Options
  5. Common Pitfalls & Solutions
  6. Conclusion
  7. References

Prerequisites#

Before we start, ensure you have:

  • Flutter SDK installed (v3.0+ recommended).
  • A basic Flutter project set up (we’ll use a StatefulWidget for date selection).
  • Familiarity with Flutter’s showDatePicker (if not, don’t worry—we’ll recap it briefly).

Understanding SelectableDayPredicate#

SelectableDayPredicate is a callback function used in showDatePicker to determine if a specific day is selectable. Its signature is:

bool Function(DateTime day)  
  • It takes a DateTime object (the day to check).
  • Returns true if the day is selectable, false if it should be disabled (grayed out).

By default, showDatePicker allows all days (the predicate returns true for every day). To limit to weekdays, we’ll customize this function to return false for Saturdays and Sundays.

Step-by-Step Implementation: Limit to Weekdays#

Let’s build a simple app that uses SelectableDayPredicate to disable weekends. We’ll create a button to open the DatePicker and display the selected date.

Step 1: Set Up the Basic App Structure#

Start with a StatefulWidget to manage the selected date state. Here’s the skeleton:

import 'package:flutter/material.dart';  
 
void main() => runApp(const MyApp());  
 
class MyApp extends StatelessWidget {  
  const MyApp({super.key});  
 
  @override  
  Widget build(BuildContext context) {  
    return MaterialApp(  
      title: 'Weekday DatePicker Demo',  
      theme: ThemeData(primarySwatch: Colors.blue),  
      home: const DatePickerDemo(),  
    );  
  }  
}  
 
class DatePickerDemo extends StatefulWidget {  
  const DatePickerDemo({super.key});  
 
  @override  
  State<DatePickerDemo> createState() => _DatePickerDemoState();  
}  
 
class _DatePickerDemoState extends State<DatePickerDemo> {  
  DateTime? _selectedDate; // Stores the selected date  
 
  @override  
  Widget build(BuildContext context) {  
    return Scaffold(  
      appBar: AppBar(title: const Text('Select a Weekday')),  
      body: Center(  
        child: Column(  
          mainAxisAlignment: MainAxisAlignment.center,  
          children: [  
            // Display selected date  
            Text(_selectedDate == null  
                ? 'No date selected'  
                : 'Selected: ${_selectedDate!.toLocal().toString().split(' ')[0]}'),  
            const SizedBox(height: 20),  
            // Button to open DatePicker  
            ElevatedButton(  
              onPressed: () => _selectDate(context),  
              child: const Text('Open Date Picker'),  
            ),  
          ],  
        ),  
      ),  
    );  
  }  
 
  // TODO: Implement _selectDate and the predicate  
}  

Step 2: Implement the DatePicker with SelectableDayPredicate#

Add the _selectDate method to trigger showDatePicker, and define the SelectableDayPredicate to disable weekends.

Key Logic: Check for Weekdays#

In Dart, DateTime.weekday returns an integer representing the day of the week:

  • 1 = Monday
  • 2 = Tuesday
  • ...
  • 5 = Friday
  • 6 = Saturday
  • 7 = Sunday

Thus, we want to return true only when day.weekday is between 1 and 5.

Add this to _DatePickerDemoState:

Future<void> _selectDate(BuildContext context) async {  
  final DateTime? picked = await showDatePicker(  
    context: context,  
    initialDate: DateTime.now(),  
    firstDate: DateTime(2023),  
    lastDate: DateTime(2025),  
    // Custom predicate to limit to weekdays  
    selectableDayPredicate: (day) => _isWeekday(day),  
  );  
 
  if (picked != null && picked != _selectedDate) {  
    setState(() => _selectedDate = picked);  
  }  
}  
 
// Predicate function: returns true for weekdays (Mon-Fri)  
bool _isWeekday(DateTime day) {  
  return day.weekday >= 1 && day.weekday <= 5; // 1=Mon, 5=Fri  
}  

Step 3: Test the App#

Run the app. When you tap "Open Date Picker":

  • Weekdays (Mon–Fri) will be selectable (black text).
  • Weekends (Sat–Sun) will be disabled (grayed out and unselectable).

Example Output:
Saturdays (6) and Sundays (7) appear gray, while Monday–Friday are interactive. Selecting a weekday updates the displayed date.

Customization Options#

SelectableDayPredicate is flexible—you can extend it to handle more complex rules. Here are common customizations:

1. Exclude Holidays#

To disable specific holidays (e.g., New Year’s Day, Christmas), add a list of holiday dates and check against it:

// List of holidays (year, month, day)  
final List<DateTime> _holidays = [  
  DateTime(2024, 1, 1), // New Year's Day  
  DateTime(2024, 12, 25), // Christmas  
];  
 
bool _isSelectable(DateTime day) {  
  // Allow only weekdays AND not a holiday  
  return day.weekday >= 1 && day.weekday <= 5 && !_holidays.any((holiday) =>  
      holiday.year == day.year &&  
      holiday.month == day.month &&  
      holiday.day == day.day);  
}  

2. Allow Specific Weekends#

To enable selectable weekends (e.g., a special event on 2024-06-15, which is a Saturday):

bool _isSelectable(DateTime day) {  
  // Allow weekdays OR June 15, 2024 (a Saturday)  
  return (day.weekday >= 1 && day.weekday <= 5) ||  
      (day.year == 2024 && day.month == 6 && day.day == 15);  
}  

3. Adjust Disabled Day Styling#

By default, disabled days use the theme’s disabledColor. To customize this, modify your ThemeData:

ThemeData(  
  primarySwatch: Colors.blue,  
  disabledColor: Colors.grey[300], // Lighter gray for disabled days  
)  

Common Pitfalls & Solutions#

Pitfall 1: Misunderstanding DateTime.weekday#

Issue: Assuming DateTime.weekday starts at 0 (e.g., Sunday = 0).
Fix: Remember: 1 = Monday, 7 = Sunday. Always validate with print(day.weekday) if unsure.

Pitfall 2: Time Zone Conflicts#

Issue: If your app uses UTC time, day might be considered a different weekday locally.
Fix: Convert to local time before checking:

bool _isWeekday(DateTime day) {  
  final localDay = day.toLocal(); // Use local time zone  
  return localDay.weekday >= 1 && localDay.weekday <= 5;  
}  

Pitfall 3: Null Return Values#

Issue: Accidentally returning null in the predicate (causes runtime errors).
Fix: Ensure the predicate always returns a bool (e.g., add a default return false).

Conclusion#

SelectableDayPredicate is a powerful tool to control date selection in Flutter. By mastering it, you can create user-friendly DatePickers that align with business rules (e.g., weekdays only, exclude holidays). We covered the basics, step-by-step implementation, customizations, and pitfalls—now you’re ready to build more intuitive date selection flows!

References#