Primarily what I’m looking to do, is to pull out documents from my Cloud Firestore when the current date falls between two timestamp fields. I have included simplified code snippets below. Hopefully it makes sense, as I’m a noob.
I have a Cloud Firestore collection named ‘calendar’ with numerous documents in it.
Each document has an event ‘title’ field plus two timestamp fields ‘datebegin’ and ‘dateend’.
struct Calendar: Decodable, Identifiable {
var title: String = ""
var datebegin: Date = Date()
var dateend: Date = Date()
}
I am parsing out the values from each document into event calendar instances:
class Calendars: ObservableObject {
let db = Firestore.firestore()
@Published var calendars = [Calendar]()
init() {
getDatabaseModules()
}
func getDatabaseModules() {
db.collection("calendar")
.getDocuments { snapshot, error in
if error == nil && snapshot != nil {
var calendars = [Calendar]()
for event in snapshot!.documents {
var e = Calendar()
e.title = event["title"] as? String ?? ""
e.datebegin = (event["datebegin"] as? Timestamp)?.dateValue() ?? Date()
e.dateend = (event["dateend"] as? Timestamp)?.dateValue() ?? Date()
calendars.append(e)
}
DispatchQueue.main.async {
self.calendars = calendars
}
}
}
}
And I have been able to pull out the data in my view, so I know that I am able to access it okay:
struct HomeView: View {
@EnvironmentObject var calendars: Calendars
var body: some View {
ForEach(0..<calendars.calendars.count, id: \.self) { events in
Text("\(calendars.calendars[events].title)")
Text("\(calendars.calendars[events].datebegin)")
Text("\(calendars.calendars[events].dateend)”)
}
}
}
Primarily what I’m looking to do, is only pull out only the calendar events when the current date (i.e. now) falls between the datebegin and dateend.
And then I would subsequently sort the resulting list by day ideally (based on the Day of datebegin), so it should end up with something like this (for an example with 9 documents that meet the criteria):
Monday
- document2.title
- document5.title
Tuesday
- document4.title
- document9.title
Wednesday
- document3.title
- document6.title
- document7.title
Friday
- document1.title
Saturday
- Document8.title
Any advice is appreciated and can provide more info as needed.
CodePudding user response:
you could try this approach, using some functions to ...pull out only the calendar events when the current date (i.e. now) falls between the datebegin and dateend...
and sorting the results based on time to ...then I would subsequently sort the resulting list by day ideally (based on the Day of datebegin)...
. Adjust the approach to suit your desired time accuracy, for example, day, weeks ...
Note, it is not a good idea to use the name Calendar
for your struct, as Swift already has a Calendar
declared.
struct ContentView: View {
@StateObject var model = Calendars()
var body: some View {
HomeView().environmentObject(model)
}
}
struct HomeView: View {
@EnvironmentObject var calendars: Calendars
let now = Date()
var body: some View {
// -- here
List {
ForEach(calendars.allBetween(now).sorted(by: {$0.datebegin < $1.datebegin})) { event in
VStack {
Text("\(event.title)")
Text("\(event.datebegin)")
Text("\(event.dateend)")
}
}
}
}
}
struct Calendar: Decodable, Identifiable {
let id = UUID() // <-- here
var title: String = ""
var datebegin: Date = Date()
var dateend: Date = Date()
// -- here
func isBetween(_ date: Date) -> Bool {
datebegin.timeIntervalSince1970 < date.timeIntervalSince1970
&&
date.timeIntervalSince1970 < dateend.timeIntervalSince1970
}
// alternatively, day comparison
func isBetweenDay(_ date: Date) -> Bool {
!(Foundation.Calendar.current.compare(date, to: datebegin, toGranularity: .day) == .orderedAscending || Foundation.Calendar.current.compare(date, to: dateend, toGranularity: .day) == .orderedDescending)
}
}
class Calendars: ObservableObject {
let db = Firestore.firestore()
@Published var calendars = [Calendar]()
init() {
getDatabaseModules()
}
// -- here
func allBetween(_ date: Date) -> [Calendar] {
calendars.filter{ $0.isBetweenDay(date) } // <-- or $0.isBetween(date)
}
func getDatabaseModules() {
db.collection("calendar")
.getDocuments { snapshot, error in
if error == nil && snapshot != nil {
var calendars = [Calendar]()
for event in snapshot!.documents {
var e = Calendar()
e.title = event["title"] as? String ?? ""
e.datebegin = (event["datebegin"] as? Timestamp)?.dateValue() ?? Date()
e.dateend = (event["dateend"] as? Timestamp)?.dateValue() ?? Date()
calendars.append(e)
}
DispatchQueue.main.async {
self.calendars = calendars
}
}
}
}
}