I'm using NSSortDescriptors to sort an Array by the date element. The date is set as String using a formatter which formats in the style : "dd/MM/yy HH:mm". This date element is stored inside dictionaries which are all stored in the array. Parts of my code for this are below:
// Date Formatting
let currentTime = Date()
let timeFormatter = DateFormatter()
timeFormatter.locale = Locale.current
timeFormatter.dateFormat = "HH:mm dd/MM/yy"
let convertedTime:String! = timeFormatter.string(from: currentTime)
// Descriptor
let descriptorD: NSSortDescriptor = NSSortDescriptor(key: "Date", ascending: false)
// Dictionary
let newUserRecord = [
"Name" : enteredName!,
"Score" : self.gameScore,
"Date" : convertedTime
] as [String : Any]
// Sorting
newUserArray.sort(using: [descriptorD])
However my problem is the date is only being sorted by the time (HH:mm) and not taking in account the (dd/MM/yy) part. For example if I sort by the date and have a date of 13:12 19/11/16 and a date of 09:12 18/11/16 the 09:12 date will appear first even though it should be the 13:12 as it is a day later. How do I fix this?
This is the object oriented Swift way:
Declare a struct rather than a dictionary and include the time formatter
struct User {
let timeFormatter : DateFormatter = {
let formatter = DateFormatter()
formatter.locale = Locale.current
formatter.dateFormat = "HH:mm dd/MM/yy"
return formatter
}()
let name : String
let score : Int
let time : Date
var convertedTime : String {
return timeFormatter.string(from: time)
}
}
Declare an array of the User type and add two instances
var newUserArray = [User]()
newUserArray.append(User(name: "Foo", score: 12, time: Date().addingTimeInterval(1000.0)))
newUserArray.append(User(name: "Bar", score: 78, time: Date()))
Sort the array by time descending
newUserArray.sort(by: {$0.time > $1.time })
And print the formatted date
print(newUserArray[0].convertedTime)
Related
I have an array of dates like this :-
var dateArray = ["2016-04-20", "2016-04-22", "2016-04-25", "2016-04-30"]
and I want to find out the difference of days between them. I do some research and i am able to do that with only two dates here is the approach i did in finding the difference between two date
let dateFormatter = DateFormatter()
let isoDate = "2016-04-20"
let calendar = NSCalendar.current
let currentDate = Date()
And in my viewDidLoad method I did this
override func viewDidLoad() {
super.viewDidLoad()
// let components = calendar.dateComponents([.day], from: )
dateFormatter.dateFormat = "yyyy-MM-dd"
dateFormatter.locale = Locale(identifier: "en_US_POSIX") //en_US_POSIX
let formatedStartDate = dateFormatter.date(from: isoDate)
let date = dateArray.compactMap { dateFormatter.date(from: $0) } // for date array
print(date)
let components = Set<Calendar.Component>([.day])
let differenceOfDate = Calendar.current.dateComponents(components, from: formatedStartDate!, to: currentDate )
print (differenceOfDate)
apiData()
}
As you can see in the code i created a constant let isoDate = "2016-04-20" and changed into formatedStartDate and find the difference between form this date to current date then it worked. But what if I have my own array of dates and how can i find the difference of my own array of dates and sort it into increasing or decreasing order. Please help?
Create the date formatter
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd"
dateFormatter.locale = Locale(identifier: "en_US_POSIX") //en_US_POSIX
Map the date string array to Date instances
let dateStringArray = ["2016-04-20", "2016-04-22", "2016-04-25", "2016-04-30"]
let dateArray = dateStringArray.map {dateFormatter.date(from: $0)!} // add .sorted() if the array is unordered.
In a loop get the differences between adjacent items
var differences = [Int]()
for i in 0..<dateArray.count - 1 {
let dayComponent = Calendar.current.dateComponents([.day], from: dateArray[i], to: dateArray[i+1])
differences.append(dayComponent.day!)
}
print(differences)
I'm not sure if you only want to compare the dates next to each other or compare each and every date. In the first case go with vadians solution. In the other case you can do something like this:
let dateStrings = ["2016-04-20", "2016-04-22", "2016-04-25", "2016-04-30"]
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd"
dateFormatter.locale = Locale(identifier: "en_US_POSIX")
let dates = dateStrings.compactMap { dateFormatter.date(from: $0) }
let calendar = Calendar.current
var differences: [Int] = []
for i in 0..<dates.count {
for j in i + 1..<dates.count {
if let difference = calendar.dateComponents([.day], from: dates[i], to: dates[j]).day {
differences.append(difference)
}
}
}
let descendingDifferences = differences.sorted(by: >)
print(descendingDifferences) // results in [10, 8, 5, 5, 3, 2]
I am trying to make my date display such as "March 2nd, 2018 10:00pm". I tried "MM-dd-yyyy" and "yyyy-MM-dd hh:mm:ss" but it seems like none of these combinations are getting the date I desire.The function to pick the date is sendRequest and it is using a UIDatePicker.
func getCurrentDateTimeFromTimeStamp(timestamp:String)->String{
let date = NSDate(timeIntervalSince1970:Double(timestamp)!)
let formatter = DateFormatter()
formatter.dateFormat = "MMMM d, yyyy HH:mm a"
return formatter.string(from: date as Date)
}
let dateCellVar = request.timestamp
let dateString = dateCellVar.description
dateCell.textLabel?.text = self.getCurrentDateTimeFromTimeStamp(timestamp: dateString)
class Request {
var timestamp:Double
init(dict: [String: Any]) {
self.timestamp = dict["timestamp"] as? Double ?? 0.0
}
func sendRequest(){
print("HEY:")
guard let user = currentUser else { return }
print("USER: \(user.firstLastName)")
if let da = dateField.text{
print(da)
}
print(timeField.text)
print(locationField.text)
print(messageTextView.text)
guard let pickedDate = pickedDate else { return print("pickedDate") }
guard let date = dateField.text else { return print("pickedDate") }
guard let time = timeField.text else { return print("time") }
guard let location = locationField.text else { return print("location")}
let db = Database.database().reference()
let ref = db.child("requests").childByAutoId()
let data = [
"sender": user.uid,
"recipient": recipientUser.uid,
"name": user.firstLastName,
"photoURL": user.photoURL,
"location": location,
"date": date,
"time": time,
"pickedTimestamp": pickedDate.timeIntervalSince1970,
"message": messageTextView.text ?? "",
"status": "PENDING",
"timestamp": [".sv": "timestamp"]
] as [String:Any]
print("HEYO")
ref.setValue(data) { error, ref in
if error == nil {
print("Success")
} else {
print("Failed")
}
}
}
Based on your result, your timestamp is in milliseconds, not seconds. You need to divide by 1000.
You also have the wrong dateFormat. You want to use hh, not HH for the hour. H is for 24-hour time which makes no sense when using a for AM/PM. You should also avoid using dateFormat. Use dateStyle and timeStyle. Let the formatter give you a date formatted best for the user's locale.
Your code also does a lot of needless conversion. You get your timestamp as a Double and store it as a Double. But then your function to convert the timestamp you expect your number of seconds as a String which you then convert back to a Double. Avoid the needless use of a String.
To get the ordinal day, you can use Calendar to extract the day from your Date.
let date = Date()
let calendar = Calendar.current
let dateComponents = calendar.component(.day, from: date)
let numberFormatter = NumberFormatter()
numberFormatter.numberStyle = .ordinal
let day = numberFormatter.string(from: dateComponents as NSNumber)
From there, you'd just code your date format with a DateFormatter and drop in the ordinal date you extracted above, like so:
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "MMMM '\(String(describing: day!)),' yyyy h:mm a"
let dateString = "\(dateFormatter.string(from: date))"
print(dateString)
Additionally, the issue with your year probably stems from the number you're feeding it. timeIntervalSince1970 is expecting whole seconds, so make sure you're feeding it whole seconds.
init(timeIntervalSince1970: TimeInterval) Returns a date object
initialized relative to 00:00:00 UTC on 1 January 1970 by a given
number of seconds.
Adapted from this answer. Additionally, you may find this site helpful for formatting dates.
Here is the problem:
My API returns a list of monthly transactions, I have to grab that result, divide it into sections to populate a tableView where each section is a month with its respective transactions.
Here is the Code
var sectionTest = Dictionary<String, Array<TableSections>>()
var sortedSections: [String] = []
for entry in entries {
if entry.type != "S" {
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "yyyy/MM/dd"
if let date = dateFormatter.date(from: entry.date) {
dateFormatter.dateFormat = "MMMM"
dateFormatter.locale = NSLocale(localeIdentifier: "pt_BR") as Locale!
let sectionMonth = dateFormatter.string(from: date)
if self.sectionTest.index(forKey: sectionMonth) == nil {
self.sectionTest[sectionMonth] = [TableSections(month: sectionMonth, description: entry.description, value: entry.value, date: entry.date, type: entry.type)]
} else {
self.sectionTest[sectionMonth]?.append(TableSections(month: sectionMonth, description: entry.description, value: entry.value, date: entry.date, type: entry.type))
}
self.sortedSections = self.sectionTest.keys.sorted(by: >)
Here is where I'm stuck
self.sortedSections returns an array sorted by alphabetical order, in this case if I request for the last 60 days of transactions it will return an array with:
print(sortedSections)
["november", "january", "december"]
Basically my challenge is :
I got an array of objects . Each object has a date property .
I want to get the array of objects which matches today's date.
So, I want to group the array based on date.
I want to show in history list by grouping objects from today, yesterday, last 7 days ,.....
I can sort array using sort function:
historylist.sort(by: {$0.createdDate! as Date > $1.createdDate! as Date })
But I need a filter function based on date.
I want all the data in historicist which are created today only.
Any quick pseudo code .
Thanks.
let date1 = NSDate()
let date2 = NSDate()
let dates = [date1, date2]
let calendar = NSCalendar.currentCalendar()
let todayDates = dates.filter({calendar.isDateInToday($0)})
Demo of how this works with filtering date objects:
let d1 = Date().addingTimeInterval(22000000)
let d2 = Date().addingTimeInterval(23000000)
let d3 = Date().addingTimeInterval(30000000)
let dates = [d1, d2, d3, Date(), Date()]
let calendar = Calendar.current
let todayDates = dates.filter({calendar.isDateInToday($0 as Date)})
print(todayDates) // [2017-06-03 15:50:11 +0000, 2017-06-03 15:50:11 +0000]
So in your case you should do it like this:
let todayDates = historylist.filter({calendar.isDateInToday($0.createdDate as Date)})
Update:
To convert a string to a Date use the following:
extension String {
var toDate: Date {
return Date.Formatter.customDate.date(from: self)!
}
}
extension Date {
struct Formatter {
static let customDate: DateFormatter = {
let formatter = DateFormatter()
formatter.locale = Locale(identifier: "en_US_POSIX")
formatter.dateFormat = "MM-dd-yyyy hh:mm:ss a"
return formatter
}()
}
}
let strDate = "06-01-2017 09:32:48 PM"
let date = strDate.toDate
I have an array called myArray in which dictionaries are added I want that dictionary to be sorted by time which is a key in dictionary. And that time is in String. The date format of time is "yyyy/MM/dd HH:mm:ss"
I tried with below code solution but gives a warning of "Cast from 'String?' to unrelated type 'Date' always fails".
let sortedArray = self.myArray.sorted{ ($0["Time"] as? Date)! > ($1["Time"] as? Date)! }
print(sortedArray)
If anyone can help me out, Thank You.
You don't need to convert to date time for this sort. The international format (yyyy/MM/dd HH:mm:ss) you're using provides the right sorting order as a string.
You have to convert string into date using this code:
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "yyyy/MM/dd HH:mm:ss"
let date = dateFormatter.date(from: "2017/04/22 00:00:00") ?? Date()
So, use this:
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "yyyy/MM/dd HH:mm:ss"
let sortedArray = self.myArray.sorted{[dateFormatter] one, two in
return dateFormatter.date(from:one["Time"] )! > dateFormatter.date(from: two["Time"] )! }
//Sort any dictionary with string dates using any date format
var incisions = [["initials": "B.B. ", "date": "12/18/17 09:39 AM", "patientID": "snowball"], ["patientID": "snowball", "date": "01/03/18 04:03 PM", "initials": "C.J."], ["initials": "B.B. ", "date": "01/04/18 09:47 AM", "patientID": "snowball"]]
func sortArrayDictDescending(dict: [Dictionary<String, String>], dateFormat: String) -> [Dictionary<String, String>] {
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = dateFormat
return dict.sorted{[dateFormatter] one, two in
return dateFormatter.date(from: one["date"]! )! > dateFormatter.date(from: two["date"]! )! }
}
//use:
let sortedArray = sortArrayDictDescending(dict: incisions, dateFormat: "MM/dd/yy a")
for i in sortedArray {
print("incisions \(i["date"]!)")
}
//output:
incisions 01/04/18 09:47 AM
incisions 01/03/18 04:03 PM
incisions 12/18/17 09:39 AM
simple code for sort an array of dictionary with date
let formatter = NSDateFormatter()
formatter.dateFormat = "MMM d, yyyy hh:mm a"
formatter.locale = NSLocale(localeIdentifier: "en_US")
let sorted = displayArray.sort {
formatter.dateFromString($0["fullfireDate"] as! String)?.compare(formatter.dateFromString($1["fullfireDate"] as! String)!) != .OrderedAscending
}