Swift: how to fetch objects made today from parse? - swift

I'm a Beginner so please be friendly while explaining, Thanks.
So basically i'm trying to fetch objects made today using createdAt.
let parseQuery = PFQuery(className: "request")
parseQuery.findObjectsInBackgroundWithBlock { (objects, error) -> Void in
if let objects = objects {
for object in objects {
self.reqDates.append(object.createdAt!)
}
}
}
let formatter = NSDateFormatter()
formatter.dateFormat = "yyyy-MM-dd HH:mm"
let formatteddate = formatter.stringFromDate(self.reqDates[indexPath.row])
myCell.reqDate.text = formatteddate
When i do this fetch it shows me all objects with their dates correctly. But how can i display objects of today only not all of them created.
I hope i explained good enough.

Request object where createdAt is greater than today (midnight)
let parseQuery = PFQuery(className: "request")
let cal = NSCalendar(calendarIdentifier: NSCalendarIdentifierGregorian)!
let components = cal.components([.Day , .Month, .Year ], fromDate: NSDate())
let todayDate = cal.dateFromComponents(components)
parseQuery.whereKey("createdAt", greaterThan:todayDate!)
parseQuery.findObjectsInBackgroundWithBlock { (objects, error) -> Void in
if let objects = objects {
for object in objects {
print(object.createdAt)
}
}
}

Related

swift Ekevents to 2 dimensional array sorted by Date

I have an array with events which are sorted by date. I want a separate section for each day [monday], [tuesday], ....
How do I create a 2-dimensional array that looks like this?
And how do i get each event in the appropriate section?
[
[monday]
[tuesday]
[wednesday]
. .and so on ]
func getEvents(){
let calendars = eventStore.calendars(for: .event)
for calendar in calendars {
// if calendar.title == "Arbeit" {
let anfang = NSDate()
let ende = Calendar.current.date(byAdding: .day, value: 6, to: anfang as Date)!
let predicate = eventStore.predicateForEvents(withStart: anfang as Date, end: ende as Date, calendars: [calendar])
let events = eventStore.events(matching: predicate)
var found:Bool = false
for event in events {
if (allEvents.count == 0)
{
allEvents.append(event)
}
if (allEvents.count > 0)
{
found = false
if ( event.title == allEvents[allEvents.count-1].title && event.startDate == allEvents[allEvents.count-1].startDate)
{
found = true
}
}
if(!found)
{
allEvents.append(event)
}
}
The following solution first groups the events based start date by weekday in a dictionary and then transforms the dictionary to a 2D array sorted with todays day first
First set up a Calendar and DateFormatter to use
let locale = Locale(identifier: "en_US_POSIX")
var calendar = Calendar.current
calendar.locale = locale
let formatter = DateFormatter()
formatter.locale = locale
formatter.dateFormat = "EEEE"
Group the events
let byWeekday = Dictionary(grouping: events, by: { formatter.string(from: $0.startDate) })
Get the weekdays in the right order
let weekdays = calendar.weekdaySymbols
let todayIndex = weekdays.firstIndex(of: formatter.string(from: Date())) ?? calendar.weekdaySymbols.startIndex
let sortedWeekdays = weekdays[todayIndex..<weekdays.endIndex] + weekdays[weekdays.startIndex..<todayIndex]
and then create and fill the array
var eventsByDay = [[EKEvent]]()
for day in sortedWeekdays {
eventsByDay.append(byWeekday[day] ?? [])
}

How to read a Firestore timestamp in Swift

I'm trying to read a timestamp from my Firestore database and ultimately convert it to a date, but for some reason my code doesn't seem to be returning anything. Instead, it only seems to use the default value that I provide, which is 0, so it always reads as Jan 1, 1970.
The document I'm trying to read in Firestore includes a field called date, which has a type of timestamp. There are other fields in the document, but to keep things simple I've left those out from this question. For reference, the other fields from the document are successfully read.
I've tried the below code. Note that I have imported Firebase to the class:
surveyDataCollectionRef.whereField("uid", isEqualTo: Auth.auth().currentUser?.uid ?? "").getDocuments { (snapshot, error) in
if let err = error {
debugPrint("Error fetching docs: \(err)")
} else {
guard let snap = snapshot else { return }
for document in snap.documents {
let data = document.data()
let timestamp = data["date"] as? TimeInterval ?? 0
let date = Date(timeIntervalSince1970: timestamp)
dateFormatter.timeZone = TimeZone(abbreviation: "GMT")
dateFormatter.locale = NSLocale.current
dateFormatter.dateFormat = "yyyy-MM-dd HH:mm"
let strDate = dateFormatter.string(from: date)
let newSurvey = Survey(date: strDate)
self.surveys.append(newSurvey!)
self.currentSurveys = self.surveys
}
self.tableView.reloadData()
}
}
}
After even more trial and error I found that the below code seemed to be able to get me a date as a String value (and in the correct format that I was aiming for:
if let timestamp = data["date"] as? Timestamp {
let date = timestamp.dateValue()
dateFormatter.dateStyle = .medium
dateFormatter.timeStyle = .none
strDate = "\(dateFormatter.string(from: date))"
}

How can I filter by specific date from realm object in swift?

I have a realm object with date property type of Date , and want to get list of items with specific date.
If I click specific date from calendar, for example 2020-03-06 , then it will present list of items which was created in 2020-03-06.
:: EDITED ::
Here is my realm object named "Profile" and there are dates from
2020-03-05 to 2020-03-08 .
Here is my Profile object and ProfileManager Singleton.
class Profile: Object {
#objc dynamic var date: Date!
#objc dynamic var content: String!
convenience init(_ content: String) {
self.init()
self.content = content
self.date = Date()
}
}
class ProfileManager {
static let shared = ProfileManager()
private var realm = try! Realm()
var profileList: Results<Profile>?
private init() {
profileList = realm.objects(Profile.self)
}
func save(_ object: Profile) {
do {
try realm.write {
realm.add(object)
}
} catch {
print(error)
}
}
func addNewProfile(_ content: String) {
let newProfile = Profile(content)
save(newProfile)
}
}
And lastly, here is a viewController which has to buttons. One for
adding new Profile, and one for printing filtered profile list.
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
}
#IBAction func addProfilePressed(_ sender: Any) {
ProfileManager.shared.addNewProfile("profile content")
}
#IBAction func filterButtonPressed(_ sender: Any) {
let stringDate = "2020-03-09"
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd"
let searchDate:Date = dateFormatter.date(from: stringDate)!
let results = ProfileManager.shared.profileList!.filter("date == %#", searchDate)
print(searchDate)
print(results)
for profile in results {
print(profile.content!)
}
}
}
the result on the console, when filterButtonPressed method called.
2020-03-08 15:00:00 +0000
Results<Profile> <0x7f9b36f160a0> (
)
How can I fix this problem?
And here is another problem.
I set to 'stringDate' a value of "2020-03-09"
but when I print converted date 'searchDate' , it prints "2020-03-08"
why this happens?
Hope now my questions is more clear to understand.
My original answer is below which, after a lot of research was only somewhat correct.
The actual answer has to do with the timestamp portion of the date.
So... if we create a date object using the below code and set it to a known date,
let stringDate = "2020-03-08"
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd"
let searchDate:Date = dateFormatter.date(from: stringDate)!
the actual object will look like this
2020-03-08T05:00:00.000Z
However, how the Profile object is being created is like this
convenience init(_ content: String) {
self.init()
self.content = content
self.date = Date()
}
and that date object looks like this
2020-03-08T16:10:25.123Z
so as you can see, if we filter for a specific date these are not equal
2020-03-08T05:00:00.000Z != 2020-03-08T16:10:25.123Z
which is why this
let stringDate = "2020-03-08"
let searchDate:Date = dateFormatter.date(from: stringDate)!
let searchResults = realm.objects(Profile.self).filter("date == %#", searchDate)
could not find the date because it's filtering for this
2020-03-08T05:00:00.000Z
To fix, change the profile class with a date stamp with a default time stamp
class Profile: Object {
#objc dynamic var date: Date!
#objc dynamic var content: String!
convenience init(_ content: String) {
self.init()
self.content = content
let formatter = DateFormatter()
formatter.timeStyle = .none
formatter.dateFormat = "MM/dd/yy"
let today = Date()
let s = formatter.string(from: today)
let d = formatter.date(from: s)
self.date = d
}
}
or, store your dates as a string yyyymmdd which will remove the ambiguity completely.
-- ORIGINAL ANSWER BELOW ---
Filtering by date is fully supported on date objects. Here's two quick examples. One for filtering for a specific date (for your question) and one for a date range using BETWEEN.
Note, I have a function makeDate that casts a string to a date object. This example uses a Realm DogClass object that has a dog_birthdate Date property.
This filters for objects with a specific date
let searchDate = self.makeDate(fromString: "06/01/2019")
let specificDateResults = realm.objects(DogClass.self)
.filter("dog_birthdate == %#", searchDate)
for dog in specificDateResults {
print(dog.dog_name)
}
This filters for objects within a date range
let startDate = self.makeDate(fromString: "06/01/2019")
let endDate = self.makeDate(fromString: "06/20/2019")
let dateRangeResuls = realm.objects(DogClass.self)
.filter("dog_birthdate BETWEEN {%#,%#}", startDate, endDate)
for dog in dateRangeResuls {
print(dog.dog_name)
}
EDIT: Using the code in the comment from the OP for testing
let stringDate = "2019-06-01"
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd"
let searchDate:Date = dateFormatter.date(from: stringDate)!
let result = realm.objects(DogClass.self).filter("dog_birthdate == %#", searchDate)
for dog in result {
print(dog.dog_name)
}
which works perfectly.

Converting timestamp from Firebase and adding to array

I'm trying to read a timeStamp from Firebase and append it to an array.
I have made some progress:
var orderDateHistoryArray = [String:Int]()
func getOrderDates() {
let uid = Auth.auth().currentUser!.uid
let orderDateHistoryRef = Database.database().reference().child("users/\(uid)/Orders/")
orderDateHistoryRef.observeSingleEvent(of: .value, with: { (snapshot) in
// Get dates
let value = snapshot.value as? NSDictionary
if let orderDate = value?["Date"] as? [String:Int] {
self.orderDateHistoryArray += Array(orderDate.values)//This does not conform
print(orderDate)
}
self.tableView.reloadData()
// ...
}) { (error) in
print(error.localizedDescription)
}
}
The print(orderDate)statement prints:
["-LQYspEghK3KE27MlFNE": 1541421618601,
"-LQsYbhf-vl-NnRLTHhK": 1541768379422,
"-LQYDWAKlzTrlTtO1Qiz": 1541410526186,
"-LQsILjpNqKwLl9XBcQm": 1541764115618]
This is childByAutoID : timeInMilliseconds
So, I want to read out the timeInMilliseconds, convert it to a readable timestampand append it to the orderDateHistoryArray
Those are timestamps. Parse it as a Date object then use .toLocaleDateString to get date.
alert( new Date(1541421618601).toLocaleDateString("en-US") );
In order to transform your timestamp you must, first remove milliseconds on each the values returned by the dictionary.
self.orderDateHistoryArray += Array(orderDate.values).map { Date(timeIntervalSince1970: TimeInterval($0/1000)) }
In order to get it in a "human way", you need to have a DateFormatter. It's on this object where you define how it's presented.
extension Date {
func format(_ dateFormat: String = "dd/MMMM")
let formatter = DateFormatter()
formatter.timeZone = TimeZone.current
formatter.dateFormat = "MMMM dd"
return formatter.string(from: self)
}
}
and on a Date element you can just call it by date.format() or by passing a string date.format("yyyy-MM-dd'T'HH:mm:ss.SSSXXXXX")

How to check whether record exists in Core Data? If yes don't add another. Swift

I have now something like this:
func addMonth() {
let appDelegate = (UIApplication.sharedApplication().delegate as AppDelegate)
var managedObjectContext = appDelegate.managedObjectContext
let entityDescription = NSEntityDescription.entityForName("DateString", inManagedObjectContext: managedObjectContext!)
let data = DateString(entity: entityDescription!, insertIntoManagedObjectContext: managedObjectContext!)
var dateFormatter = NSDateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd HH:mm:ss Z"
var dateString = datePicker.date.description
var date = dateFormatter.dateFromString(dateString)
dateFormatter.dateFormat = "MMMM"
var dateString2 = dateFormatter.stringFromDate(date!)
println(dateString2)
data.date = dateString2
//appDelegate.saveContext()
}
I can see actual month "February".
How check whether this month already exists in the database? If there is a month that does not add the next record.
Regards,
Mateusz Fraczek
Assuming that DateString is a child class of NSManagedObject, you should be able to grab DateString records from Core Data by running something like the following:
let entity = "DateString"
var request = NSFetchRequest(entityName: entity)
var error: NSError?
if let entities = managedObjectContext.executeFetchRequest(
request,
error: &error
) as? [NSManagedObject] {
for entity in entities {
if let dateString = entity as DateString {
...do whatever tests you need with the new DateString instance
}
}
}