How do I implement the date range for a custom DatePicker in Swift 5 - swift

I am building an iOS/iPhone application using Swift 5 / Xcode 14.1. I've created and can display a DatePicker. However, any range I provide, using the in: parameter is ignored. How do I correctly set the range.
I've constructed a view with a DatePicker as so:
DatePicker(
"Please enter the start time",
selection: $startTime,
in: ...Date()
) .labelsHidden()
.datePickerStyle( WheelDatePickerStyle() )
I am expecting to see a date picker that would allow a date up to the current date and time but instead I see this:
a datepicker

#State var selectedDate = Date()
var dateClosedRange: ClosedRange<Date> {
let min = Calendar.current.date(byAdding: .day, value: -1, to: Date())!
let max = Calendar.current.date(byAdding: .day, value: 1, to: Date())!
return min...max
}
DatePicker(
selection: $selectedDate,
in: dateClosedRange,
displayedComponents: [.hourAndMinute, .date],
label: { Text("Due Date") }
)
This example is working perfectly bro
DatePicker(
"", selection: $profile.goalDate,
in: Calendar.current.date(byAdding: .month, value: -1, to: profile.goalDate)! ... Calendar.current.date(byAdding: .month, value: 1, to: profile.goalDate)!,
displayedComponents: .date
)
.datePickerStyle( WheelDatePickerStyle() )
Wheel stop scrolling and again re position itself to date range

Related

SwiftUI - Use DatePicker GraphicalDatePickerStyle as a read-only calendar

I want to display a calendar with a set of dates marked (It reflects all the reservations a user has scheduled in a month on my application).
I'm trying to do that without creating a calendar component or importing a library. So, here I'm using the DatePicker component from SwiftUI with this configuration:
DatePicker(
"",
selection: $date,
displayedComponents: [.date])
.datePickerStyle(GraphicalDatePickerStyle())
It's possible to fill this calendar with all the days reserved on my data layer?
What I want is something similar to what the Calendar app does:
Quite tricky but you can declare binding variable to set date value to your old one.
var body: some View {
let binding = Binding<Date> {
self.date
} set: { newDate in
self.date = Date() // your old value
}
DatePicker(
"",
selection:binding,
displayedComponents: [.date])
.datePickerStyle(GraphicalDatePickerStyle())
}

minimumDate equivalent in swiftUI?

I have a DatePicker on my app and the user can't select a past date, because I'm creating a notification out of it
How can I implement a minimumDate equivalent in SwiftUI?
I tried creating an alert on my save button using “if date < Date(), else show alert”, but it didn't work.
You can provide a range to DatePicker:
#State private var date = Date()
let dateRange: ClosedRange<Date> = {
let calendar = Calendar.current
let startComponents = DateComponents(year: 2021, month: 1, day: 1)
let endComponents = DateComponents(year: 2021, month: 12, day: 31, hour: 23, minute: 59, second: 59)
return calendar.date(from:startComponents)!
...
calendar.date(from:endComponents)!
}()
var body: some View {
DatePicker(
"Start Date",
selection: $date,
in: dateRange,
displayedComponents: [.date, .hourAndMinute]
)
}
Source: https://developer.apple.com/documentation/swiftui/datepicker

How do I fetch a date range of a week to extract from core data?

How do I query a date range in Swift code data IOS? If I store attributes: date, breakfast meals, lunch meals. How can I query what meals I ate this week?
I was able to get the current week using the following code:
var today = Date()
//finds date for Sunday start of week
var todayweekdaycomp = Calendar.component(.weekday, from: Date())
let startOfWeekSunday = Calendar.current.date(byAdding: .day, value: -(todayweekdaycomp - 1), to: today)!
//finds date for Saturday end of week
let endOfWeekSatvalue = 7 - todayweekdaycomp
let endofWeekSat = Calendar.current.date(byAdding: .day, value: endOfWeekSatvalue, to: today)!
//array of dates this week
var arr: [Date] = []
for n in 1...7 {
arr.append(Calendar.current.date(byAdding: .day, value: n, to: startOfWeekSunday)!)
}
Defining the begin date :
First you have to define a begin date. This will help us retrieve all the meals from that date .
If you want to get it from 7 days ago define it like that :
let calendar = Calendar.current
let beginDate = calendar.date(byAdding: .day, value: -7, to: Date())!
If you want to get it since the beginning of the week you first need to add this extension :
extension Date {
func startOfWeek(using calendar: Calendar = Calendar(identifier: .gregorian)) -> Date {
calendar.dateComponents([.calendar, .yearForWeekOfYear, .weekOfYear], from: self).date!
}
}
Then you can define your begin date like so :
let beginDate = Date().startOfWeek()
Creating the request :
// Creating the predicate.
let predicate = NSPredicate(format: "%K >= %#", #keyPath(YourData.date) ,beginDate as NSDate)
let request: NSFetchRequest<YourData> = YourData.fetchRequest()
// Adding a predicate to your request.
request.predicate = predicate
Note that you need to replace "YourData" by the name of the class of your meal data object.
Once you have your request ready you can fetch it as usual.

Firestore timestamp date range query with order by generate an error

I wrote a query to filter some data based on the date range and want to order the result by some field (Int). The code I wrote generate "FIRInvalidArgumentException" exception.
If I removed the "order by" then the query execute perfectly. I have already created the index for visitDate and views fields.
Index: visitDate Ascending views Descending
let calendar = Calendar.current
let currentDateComponents = DateComponents(
calendar: calendar,
year: calendar.component(.year, from: Date()),
month: calendar.component(.month, from: Date()),
day: calendar.component(.day, from: Date()),
hour: 0,
minute: 0)
guard let currentDate = calendar.date(from: currentDateComponents) else {
print("error");
return
}
guard let weekEndDate = calendar.date(byAdding: .day, value: -7, to: currentDate) else {
print("error");
return
}
let queryRef = Firestore.firestore().collection("ArticleVisits")
.whereField("visitDate", isGreaterThanOrEqualTo: weekEndDate)
.whereField("visitDate", isLessThanOrEqualTo: currentDate)
.order(by: "views", descending: true)
.limit(to: limit)
Is there any issue using order by with date range? Do I need to create a special index for this?
Appreciate all the help.
#Jay thanks for point me to right direction. According to the documentation it says,
However, if you have a filter with a range comparison (<, <=, >, >=), your first ordering must be on the same field:
So I have to order it by visitDate instead of views.

Swift - nextDate() search by day of year

Hoping for some help on this one. I'm trying to search (forwards and backwards) to find the next date that matches the day of the year
So, for instance I have a day value of 300, I know we are currently on day 237 of this year (as of writing this post, 25/08/18!), and I want to search backwards to find the previous occurrence of the 300th day of a year, and format a date from it.
I'm already extracting the 'day of year' from date using a small Date extension:
extension Date {
var dayOfYear: Int {
return Calendar.current.ordinality(of: .day, in: .year, for: self)!
}
}
Using the Calendar.nextDate() function I can search to match '.day' , but that's obviously day of month, not year:
let potentialSartDate = (Calendar.current as NSCalendar).nextDate(after: nowDate, matching: .day, value: dayOfYearValueToMatch, options: [.matchNextTime, .searchBackwards])!
Does anyone have any pointers, or approach, of how to perform a search like this build a date out of the result?
Thanks in advance!
Emile
You can get the current year component from today and use the Calendar date(from: DateComponents) method to get the 300th day of the year as follow:
extension Calendar {
static let iso8601 = Calendar(identifier: .iso8601)
}
extension Date {
var year: Int {
return Calendar.current.component(.year, from: self)
}
var last300ThDayOfYear: Date {
return Calendar.current.date(from: DateComponents(calendar: .iso8601, year: dayOfYear > 300 ? year : year - 1, day: 300))!
}
var dayOfYear: Int {
return Calendar.current.ordinality(of: .day, in: .year, for: self)!
}
}
let date = Date().last300ThDayOfYear // "Oct 27, 2017 at 12:00 AM"
print(date.dayOfYear) // 300