I need to compare two Date object to get the day difference between them, for example: 10/10 compares with today 10/7 will be 3, but the Date object returned to me from server is not aligned with the current time. There will be a few minutes difference which results in 10/10 being 2 days ahead of 10/7 because of the delay
I found a line of code that can give me a Date object of the current time, but I want to convert an existing Date object from somewhere else, how do I do it?
let today = Calendar.current.date(bySettingHour: 0, minute: 0, second: 0, of: Date())!
e.g. 2020-10-08 16:08:57.259580+0000 I want it to be 2020-10-08 00:00:00 +0000 something like this
Don’t use midnight. Just parse your date string first. For calendrical calculations you should always use noon. First create a custom date format to parse your date string properly.
extension Formatter {
static let iso8601: DateFormatter = {
let formatter = DateFormatter()
formatter.locale = .init(identifier: "en_US_POSIX")
formatter.dateFormat = "yyyy-MM-dd HH:mm:ss.SSSSSSxx"
formatter.timeZone = TimeZone(secondsFromGMT: 0)
return formatter
}()
}
Then create a helper to convert your date to noon time and another one to calculate the days between two dates and set them to noon:
extension Date {
var noon: Date {
Calendar.current.date(bySettingHour: 12, minute: 0, second: 0, of: self)!
}
func days(from date: Date) -> Int {
Calendar.current.dateComponents([.day], from: date.noon, to: noon).day!
}
var daysFromToday: Int { days(from: Date()) }
}
Playground testing:
let dateString = "2020-10-08 16:08:57.259580+0000"
let now = Date() // "Oct 8, 2020 at 5:56 AM"
print(Formatter.iso8601.string(from: now)) // "2020-10-08 08:56:46.179000+0000\n"
if let date = Formatter.iso8601.date(from: dateString) { // "Oct 8, 2020 at 1:08 PM"
let days = Date().days(from: date) // 0
}
let dateString = "2020-10-10 16:08:57.259580+0000"
if let date = Formatter.iso8601.date(from: dateString) {
let days = date.daysFromToday // 2
}
I need to get all the remaining hours of the day starting from whatever the current hour is until 11pm and save it in an array in a date format. Here is what I have written so far:
var sortedTime: [Date] = {
let today = Date()
var sortedTime: [Date] = []
(0..<14).forEach {
sortedTime.append(Calendar.current.date(byAdding: .hour, value: $0, to: today)!)
}
return sortedTime
}()
In the code I have: (0..<14).forEach { This is giving me the next 14 hours but thats not what I need; I need to make sure the hours I get are between 9am and 11pm. How would I be able to set this limit?
When you access .hour for any calender its in a 24h format. so you need to something like this:
let today = Date()
var sortedTime: [Date] = []
var calender = Calendar(identifier: .iso8601)
calender.locale = Locale(identifier: "en_US_POSIX")
let currentHour = calender.component(.hour, from: today)
(0...(24-currentHour)).forEach {
guard let newDate = calender.date(byAdding: .hour, value: $0, to: today) && calender.component(.hour, from: newDate) != 0,
calender.component(.hour, from: newDate) <= 23 else {
return
}
//convert date into desired format
sortedTime.append(newDate)
}
So, I am currently working on an app that will do a simple countdown to a specific date; however, I am getting this error: "Value of type '(NSCalendar.Unit, Date, Date [NSCalendar.Options]) -> ()' has no member 'day' "
Any way to fix this to finish the app?
class ViewController: UIViewController {
#IBOutlet weak var CountdownText: UILabel!
let formatter = DateFormatter()
let userCalendar = NSCalendar.current
let requestedComponent: NSCalendar.Unit = [
NSCalendar.Unit.month,
NSCalendar.Unit.day,
NSCalendar.Unit.hour,
NSCalendar.Unit.minute,
NSCalendar.Unit.second,
]
func printTime()
{
formatter.dateFormat = "MM/dd/yy hh:mm:ss a"
let startTime = NSDate()
let endTime = formatter.date(from: "12/03/18 2:00:00 p")
func timeDifference (requestedComponent: NSCalendar.Unit, from: Date, to: Date, options: [NSCalendar.Options]) {}
CountdownText.text = "\(timeDifference.day) Days \(timeDifference.minute) Minutes \(timeDifference.second) Seconds"
}
}
You're trying to get call .day property from your function type which does and returns nothing.
I bet your function timeDifference should be somewhere outside the printTime function.
Believe you want to do something like following:
func printTime() {
formatter.dateFormat = "MM/dd/yy hh:mm:ss a"
let startTime = Date()
let endTime = formatter.date(from: "12/03/18 2:00:00 p")
let days = timeDifference(requestedComponent: .day, from: startTime, to: endTime, options: [])
let minutes = timeDifference(requestedComponent: .minute, from: startTime, to: endTime, options: [])
let seconds = timeDifference(requestedComponent: .second, from: startTime, to: endTime, options: [])
CountdownText.text = "\(days) Days \(minutes) Minutes \(seconds) Seconds"
}
func timeDifference (requestedComponent: NSCalendar.Unit, from: Date, to: Date, options: [NSCalendar.Options]) -> Int {
var calculatedValue = 0
// calculatings
return calculatedValue
}
You've declared a function named timeDifference() and you're trying to access it like a variable instance
Here's what you need to do:-
func timeDifference (requestedComponent: NSCalendar.Unit, from: Date, to: Date, options: [NSCalendar.Options]) {
//Do your things here
}
And call the function inside the variable this way:-
var text = "\(timeDifference(requestedComponent: .day, from: Date(), to: Date(), options: [.searchBackwards])) Days \(timeDifference(requestedComponent: .minute, from: Date(), to: Date(), options: [.searchBackwards])) Minutes \(timeDifference(requestedComponent: .second, from: Date(), to: Date(), options: [.searchBackwards])) Seconds"
Additionally, you can make your function parameters optional like this:-
func timeDifference (requestedComponent: NSCalendar.Unit, from: Date, to: Date, options: [NSCalendar.Options]? = nil) {}
The fourth parameter here is optional and the you don't have to provide an option every time. It's considered to be nil without input and it won't affect you in any way, unless you use it somewhere within the function, where you might have to handle it with an 'if' statement
(Just in case if it helps!)
NOTE:-
You can also return a "NSCalendar.Unit" from your function and use it for calculation, in which case, your usage pattern is right.
But I assume that the function here is written for the purpose of calculation and you're dealing with a label's value to display the calculated result. Dealing this all within a function is the sole purpose of a function, and hence I recommend doing this
You are trying to use function (with no return type) as NSCalendarComponent, hence it is showing you error. Instead, you and get start time and end time components like this:
func printTime(){
formatter.dateFormat = "MM/dd/yy hh:mm:ss a"
let calendar = Calendar.current
let startTime=calendar.dateComponents([.hour,.minute,.second], from: Date())
print("\(startTime.hour!):\(startTime.minute!):\(startTime.second!)")
let endTime = calendar.dateComponents([.hour,.minute,.second], from: formatter.date(from: "12/03/18 2:00:00 p") ?? Date())
print("\(endTime.hour!):\(endTime.minute!):\(endTime.second!)")
//do calculations here for time difference
}
and now you can calculate time difference and show it on countdown text.
First of all don't use NSCalendar and NSDate at all in Swift 3+.
Your code doesn't work because the function timeDifference has no return value and does nothing anyway.
You probably mean
let requestedComponents: Set<Calendar.Component> = [.month, .day, .hour, .minute, .second]
...
func timeDifference (requestedComponents: Set<Calendar.Component>, from: Date, to: Date) -> DateComponents {
return Calendar.current.dateComponents(requestedComponents, from: from, to: to)
}
...
let difference = timeDifference(requestedComponents: requestedComponents, from: startTime, to: endTime)
CountdownText.text = "\(difference.day!) Days \(difference.minute!) Minutes \(difference.second!) Seconds"
There is a more convenient way to calculate and display time differences, DateComponentsFormatter
func printTime()
{
let formatter = DateFormatter()
formatter.dateFormat = "MM/dd/yy hh:mm:ss a"
let startTime = Date()
let endTime = formatter.date(from: "12/03/18 2:00:00 p")!
let componentsFormatter = DateComponentsFormatter()
componentsFormatter.allowedUnits = [.hour, .minute, .second]
componentsFormatter.unitsStyle = .full
CountdownText.text = componentsFormatter.string(from: startTime, to: endTime)
}
How would I take a certain amount of days (take away one day) off the current date and print with certain date format to the console.
I'm currently using:
print((Calendar.current as NSCalendar).date(byAdding: .day, value: -1, to: Date(), options: [])!)
Which prints the date and time as:
yyyy-MM-dd HH:MM:SS +0000
But I want it to print like:
dd-MM-yyyy
Is this at all possible?
It's best to break that into a few more easily readable/maintainable lines. First, calculate the date you want, then apply a date formatter.
let yesterday = Calendar.current.date(byAdding: .day, value: -1, to: Date())
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "dd-MM-yyyy"
print(dateFormatter.stringFromDate(yesterday))
swift 3.0 version
let yesterday = Calendar.current.date(byAdding: .day, value: -1, to: Date())
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "dd-MM-yyyy"
if let yesterday = yesterday {
print(dateFormatter.string(from: yesterday))
}else{
print("Date incorrectly manipulated")
}
You shouldn't use fixed format for Date format strings. Because you might have users from around the world and they don't see dates in the same way.
Rather you should use template format. You just specify which components you want to show and their order like:
let dateFormatter = DateFormatter()
// dateFormatter.locale = Locale(identifier: "bn-BD") // Enable this line only at the time of your debugging/testing
dateFormatter.dateFormat = DateFormatter.dateFormat(fromTemplate: "ddMMyyyy",
options: 0,
locale: dateFormatter.locale)
let date = Calendar.current.date(byAdding: .day, value: -1, to: Date())
if let date = date {
let dateString = dateFormatter.string(from: date)
print(dateString)
}
You shouldn't set your locale by yourself. It's done by the
framework. You should only set your locale manually only at the time
of testing your app.
In the above example I'm using Locale as "bn-BD" which means Bangla in Bangladesh. You can find your a list of locales here
I have a function where i have to retrieve a date from my own sqlite db of app. I have saved it using the formatter
My work flow
1..Save a date to db on Application did enter background(Saved as String)
2..When application become foreground again i make a date instance at that point of time too. Now i have two date's.
3..Convert both dates to correct format and get the seconds difference.
Convert from date to String-->
let formatter = NSDateFormatter()
formatter.dateFormat = "yyyy-MM-dd HH:mm:ss.Z"
let myString = formatter.stringFromDate(NSDate()) // i get value"2017-05-18 16:49:38.+0530"
But when i reconvert it to NSDate(I Mean when i convert this to string again)-->
let formatter = NSDateFormatter()
formatter.dateFormat = "yyyy-MM-dd HH:mm:ss.Z"
let lastloginDate=formatter.dateFromString(lastLogin) // i get value(Converting back to string \n for checking as the time difference was zero ) 2017-05-18 00:00:00.+0530
I want to compare two dates like a session out service , I do this by getting the calendar components difference of minute. However since its coming like this, the difference his always zero .
let myString1 = formatter.stringFromDate(date1)
let myString2 = formatter.stringFromDate(date2)
print("DATE 1\(myString1) DATE 2 \(myString2)")
let components = calendar.components(flags, fromDate: date2, toDate: date1, options: [])
let diff = components.second
print("Diffrence is \(diff)") // Always zero 😱
Why is this?
Try this one.
let myString1 = formatter.stringFromDate(date1)
let myString2 = formatter.stringFromDate(date2)
print("DATE 1\(myString1) DATE 2 \(myString2)")
let components = NSCalendar.currentCalendar().components([.Month, .Day, .Hour, .Minute, .Second], fromDate: myString1, toDate: myString2, options: [])
let diff = components.second
print("Difference is \(diff)")