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+ (sinceMultiDatePicker
is 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
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 tonil
when no range is selected.endDate
: ABinding<Date?>
that holds the selected end date of the range. Set tonil
when 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