A lightweight SwiftUI date range picker built on top of Apple's native MultiDatePicker.
Unlike the standard MultiDatePicker, this package allows you to select a continuous date range by tapping a start date and an end date — everything in between is selected automatically.
⚠️ Requires iOS 16.0+, iPadOS 16.0+, Mac Catalyst 16.0+, or visionOS 1.0+ (sinceMultiDatePickeris only available starting these versions).
- Select a start and end date to define a range
- Dates can be selected in any order — either a future date first or an earlier date first.
- Automatically selects and highlights all days in between
- Tap anywhere to cancel selection
- Uses native SwiftUI
MultiDatePicker, hence No custom complicated UI - Lightweight and dependency-free
- Includes example project for quick testing
- Full dark mode support for a seamless appearance in both light and dark themes.
Simulator.Screen.Recording.mov
Add the package to your project:
- In Xcode, go to File → Add Packages…
- Enter the repository URL: https://github.com/14T/DateRangePicker.git
- Select the main branch (or a tagged release once you publish).
startDate: ABinding<Date?>that holds the selected start date of the range. Set tonilwhen no range is selected.endDate: ABinding<Date?>that holds the selected end date of the range. Set tonilwhen no range is selected.bounds: The exclusive range of selectable dates. ARange<Date>that constrains the calendar to only allow date selection within this range. This prevents users from selecting dates outside your desired timeframe.
DateRangePicker(startDate: $startDate, endDate: $endDate)import SwiftUI
import DateRangePicker
struct ContentView: View {
@State private var startDate: Date? = nil
@State private var endDate: Date? = nil
var body: some View {
VStack(spacing: 20) {
DateRangePicker(
startDate: $startDate,
endDate: $endDate
)
.frame(height: 400)
if let start = startDate, let end = endDate {
Text("Range: \(start.formatted(date: .abbreviated, time: .omitted)) → \(end.formatted(date: .abbreviated, time: .omitted))")
} else {
Text("No complete range selected")
}
}
.padding()
}
}struct BookingView: View {
@State private var checkInDate: Date? = nil
@State private var checkOutDate: Date? = nil
@State private var minimumStay = 2
private var bookingBounds: Range<Date> {
let calendar = Calendar.current
let start = calendar.date(byAdding: .day, value: 1, to: Date())! // Tomorrow onwards
let end = calendar.date(byAdding: .month, value: 6, to: Date())! // 6 months from now
return start..<end
}
var isValidBooking: Bool {
guard let checkIn = checkInDate, let checkOut = checkOutDate else { return false }
let daysBetween = Calendar.current.dateComponents([.day], from: checkIn, to: checkOut).day ?? 0
return daysBetween >= minimumStay
}
var body: some View {
VStack(spacing: 20) {
Text("Book your stay")
.font(.title2)
.fontWeight(.semibold)
DateRangePicker(
startDate: $checkInDate,
endDate: $checkOutDate,
bounds: bookingBounds
)
.frame(height: 350)
.tint(.green)
if let checkIn = checkInDate, let checkOut = checkOutDate {
let daysBetween = Calendar.current.dateComponents([.day], from: checkIn, to: checkOut).day ?? 0
Text("\(daysBetween) nights: \(checkIn.formatted(date: .abbreviated, time: .omitted)) - \(checkOut.formatted(date: .abbreviated, time: .omitted))")
.foregroundStyle(isValidBooking ? .green : .orange)
}
Button("Confirm Booking") {
if isValidBooking {
// Process booking
print("Booking confirmed!")
}
}
.buttonStyle(.borderedProminent)
.disabled(!isValidBooking)
}
.padding()
}
}You can further customize the appearance using standard SwiftUI modifiers:
DateRangePicker(
startDate: $startDate,
endDate: $endDate,
bounds: bounds
)
.frame(height: 400)
.tint(.yellow)The package includes a sample iOS app that demonstrates various use cases:
- Basic date range selection
- Constrained date ranges (e.g., future dates only)
- Integration with form validation
- Custom styling and theming
Open the example project in Xcode to see these implementations in action.
Contributions are welcome! Please feel free to submit a Pull Request or open an issue.
- Fork the project
- Create your feature branch (
git checkout -b feature/AmazingFeature) - Commit your changes (
git commit -m 'Add some AmazingFeature') - Push to the branch (
git push origin feature/AmazingFeature) - Open a Pull Request
This project is licensed under the MIT License

