Convert value to compare in NSPredicate - swift

I am trying to use NSPredicate with Swift and RealmSwift. I want to filter a Realm collection, with one predicate being date related. The dates are stored as Strings in the format yyyy-MM-dd — how do I convert this to a Date so I can compare it to today, as part of the predicate?
My [non-working] attempt so far:
let today = Date()
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd"
let datePredicate = NSPredicate(format: "nextReview <= %#", argumentArray: [today, dateFormatter]) {
let nextReviewDate = dateFormatter.date(from: $0.nextReview)
return nextReviewDate ?? today <= today
}
...
var cardsToReview: [RealmCard] = Cards.filter(compoundPredicate).map { $0 }

You are making things more complicated than needed. Since you have the date format "yyyy-MM-dd" in your database you can directly compare the strings since they will always have the same order as when converted to dates.
let today = dateFormatter.string(from: .now)
let datePredicate = NSPredicate(format: "nextReview <= %#", today)

Related

How to format dates without the '0' in the beginning with Swift?

I would like to format my dates to not have zeros in the beginning.
For example
04/03/20 -> swift should display as 4/3/20
I basically want to remove the zero that may be in front of the day, month, or year. The purpose of this is not for style purposes but for me to access data in a JSON. That's why it needs to be soo specific.
You can get by using Date & DateFormatter
let formatter = DateFormatter()
formatter.dateFormat = "dd/MM/yy" // change formate as per your requirement
let date = formatter.date(from: "04/03/20") //change "04/03/20" to your input string
formatter.dateFormat = "d/M/yy"
let dateString = formatter.string(from: date!)
print(dateString) // 4/3/20
let date = "04/03/20"
let parts = date.split(separator: "/")
var newDate = ""
for i in 0..<parts.count {
newDate = "\(newDate)\(i == 0 ? "" :"/")\(Int(parts[i])!)"
}
print(newDate) //Result - 4/3/20

Any way to sort custom object inside array?

I have this array
var bookTimeArray = [BookTime]()
BookTime class contains followings
var time : String = ""
var status : String = ""
var booked_by : String = ""
Now i need to sort the array bookTimeArray by seeing the BookTime.time variable.
Time variable may contain one time from "12AM" to "11PM"
The object need to be sorted in following pattern
["12AM", "1AM", "2AM", "3AM", "4AM", "5AM", "6AM", "7AM", "8AM", "9AM", "10AM", "11AM", "12PM", "1PM", "2PM", "3PM", "4PM", "5PM", "6PM", "7PM", "8PM", "9PM","10PM", "11PM"]
if bookTimeArray has 5 object
bookTimeArray[0].time = "10AM"
bookTimeArray[1].time = "6AM"
bookTimeArray[2].time = "9AM"
bookTimeArray[3].time = "6PM"
bookTimeArray[4].time = "9PM"
Expected output
bookTimeArray[0].time = "6AM"
bookTimeArray[1].time = "9AM"
bookTimeArray[2].time = "10AM"
bookTimeArray[3].time = "6PM"
bookTimeArray[4].time = "9PM"
I cant figure out how to achieve this. Help me out :(
You can do it this way:
// First create a DateFormatter object to convert your time strings to Date objects so you can compare between them.
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "ha"
dateFormatter.locale = Locale(identifier: "en_US_POSIX")
// Then you only need to sort the bookTimeArray by *time* property after converting *time* string to a Date object using the dateFormatter that we've created above.
let sortedBooks = bookTimeArray.sorted { dateFormatter.date(from: $0.time)! < dateFormatter.date(from: $1.time)! }
You can use dateFormatter for creating Date objects from your String property and then you can sort your array by these Dates
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "ha" // format 1AM, 2AM, 12PM, ...
dateFormatter.locale = Locale(identifier: "en_US_POSIX")
Sorting:
bookTimeArray.sort { bookTime1, bookTime2 in
guard let date1 = dateFormatter.date(from: bookTime1.time), let date2 = dateFormatter.date(from: bookTime2.time) else { return false }
return date1 < date2
}
Hope this will help:
// Custom models array
let dataArray = [Class(fileID:1),Class(fileID:2),Class(fileID:3)]
// here is sorting code
dataArray.sorted({ $0.fileID > $1.fileID })

How to get the date formate from the time stamp in swift

I want to get the date formate from the time stamp.so I am getting the timestamp is from the firebase database. so I am getting this output when it is retrieved from the firestore 2018-08-31T05:33:31.408Z . so I want to format the timestamp in the form "Aug 2018", 11.39 AM. so I tried to convert it with this code
let timestamp = deyaPaybalance.value(forKey: "timestamp") as! NSArray
print("timestamp is",timestamp)
//let len = timestamp.count
for element in timestamp {
let ele = element
let formatter = ISO8601DateFormatter()
//print("date is",date1!)
formatter.formatOptions = [.withFullDate,
.withTime,
.withDashSeparatorInDate,
.withColonSeparatorInTime]
let date2 = formatter.date(from: ele as! String)
print("timestamp with date is",date2!)
print("element is",ele)
}
But I am getting this type of output 2018-09-22 09:29:11 +0000 . So how to solve that one.
You are actually parsing the timestamp to a Date Object. Now if you want the date object to format any other way take a DateFormatter Variable, set dateFormat of the formatter and get the string from the date. That will convert the date to the expected string.
let anotherFormatter = DateFormatter()
anotherFormatter.dateFormat = "MMM yyyy, h:mm a"
anotherFormatter.string(from: date2)

How to save the current date to CoreData?

I have an attribute in CoreData which accepts a date value. I just want to get the current date and save it in this format "dd/mm/yyyy" . But don't know how. Thanks
If you're storing it as Date, then you have no control over the format until you try to present the returned value somewhere, and you just store Date()
If you're storing it as shown, then you need to use a DateFormatter to create the string you need
Here you can store date in coreData as shown in format
let date = NSDate()
var dateFormatter = DateFormatter()
dateFormatter.dateFormat = "dd/MM/yyyy"
var dateString = dateFormatter.string(from: date as Date)
store dateString in your coreData
To save dates in Core Data I have created the following extension
extension Date {
/**
Formats a Date
- parameters format: (String) for eg dd-MM-yyyy hh-mm-ss
*/
func format(format:String = "dd-MM-yyyy hh-mm-ss") -> Date {
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = format
let dateString = dateFormatter.string(from: self)
if let newDate = dateFormatter.date(from: dateString) {
return newDate
} else {
return self
}
}
}
To set a date value of a field
let date = Date()
entity?.setValue(date.format(), forKey: "updated_at")
Note: You may see date saved as timestamp when you open your database. Please refer to the following issue NSDate being saved as timestamp in CoreData
You can also pass you own date formats in the "format()" extension to get different types of dates in the application

How to check valid Date() in Swift

How to check if the date is valid, before making a SQL query using
request.predicate = NSPredicate (format: "% # <= AND myDate% #> = myDate" startDate, endDate)
an error occurs with the leap years, like 30 of February 2016.
// code form comment...
let startDate:NSDate = dateFormatter.dateFromString("2016-10-01")!
let endDate:NSDate = dateFormatter.dateFromString("2016-10-29")!
The return value of a date generated by DateFormatter's date(from:) method is an optional. If nil is returned the date is invalid, otherwise it's valid.
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd"
if let date = dateFormatter.date(from:"2016-02-30") {
print(date) // if this prints date is valid
}
else {
print("Date is Invalid") // if this prints date is invalid
}
A Date cannot be instantiated with an invalid date string that is outside of the realm of real calendar dates.
If what you are asking is whether a date falls between two other dates, see here: https://stackoverflow.com/a/40057117/1694526
Use DateFormatter class... It can be used to check any string whether it is a valid date or not and accordingly the string can be converted into nsdata.