Finding the difference in time between two NSDates Swift
Yes if you look at the second answer to your linked question you can do this: let interval = laterDate.timeIntervalSinceDate(earlierDate)
Swift days between two NSDates
You have to consider the time difference as well. For example if you compare the dates 2015-01-01 10:00
and 2015-01-02 09:00
, days between those dates will return as 0 (zero) since the difference between those dates is less than 24 hours (it's 23 hours).
If your purpose is to get the exact day number between two dates, you can work around this issue like this:
// Assuming that firstDate and secondDate are defined
// ...
let calendar = NSCalendar.currentCalendar()
// Replace the hour (time) of both dates with 00:00
let date1 = calendar.startOfDayForDate(firstDate)
let date2 = calendar.startOfDayForDate(secondDate)
let flags = NSCalendarUnit.Day
let components = calendar.components(flags, fromDate: date1, toDate: date2, options: [])
components.day // This will return the number of day(s) between dates
Swift 3 and Swift 4 Version
let calendar = Calendar.current
// Replace the hour (time) of both dates with 00:00
let date1 = calendar.startOfDay(for: firstDate)
let date2 = calendar.startOfDay(for: secondDate)
let components = calendar.dateComponents([.day], from: date1, to: date2)
Get Time interval between two NSDate
Hope this can help you.
NSString *startDate = @"2016-02-24 10:25:11 +0000";
NSString *endDate = @"2016-02-24 10:26:11 +0000";
NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
[formatter setDateFormat:@"yyyy-MM-dd HH:mm:ss Z"];
NSDate *start = [formatter dateFromString:startDate];
NSDate *end = [formatter dateFromString:endDate];
NSTimeInterval interval = [end timeIntervalSinceDate:start];
NSLog(@"time interval:%f", interval);
How to calculate days difference between two NSDate objects in different time zones?
This is an odd case. You're looking for the difference in calendar dates between two Dates when those dates are evaluated in a specific time zone.
I did some playing, and came up with code that works for dates that fall in the same year:
let date = Date()
guard let nycTimeZone = TimeZone(abbreviation: "EST"),
let nzTimeZone = TimeZone(abbreviation: "NZDT") else {
fatalError()
}
var nycCalendar = Calendar(identifier: .gregorian)
nycCalendar.timeZone = nycTimeZone
var nzCalendar = Calendar(identifier: .gregorian)
nzCalendar.timeZone = nzTimeZone
let now = Date()
let nycDayOfYear = nycCalendar.ordinality(of: .day, in: .year, for: now)
var nzDayOfYear = nzCalendar.ordinality(of: .day, in: .year, for: now)
I'm using New York and Aukland, NZ as my time zones because as of the time of this writing, those zones are on different dates.
As of now (~12:00 PM on Feb 11, 2017 in US Eastern Standard Time (UTC - 5) the code above gives
nycDayOfYear = 42
and
nzDayOfYear = 43
It would take some work to make that calculation work across year boundaries.
Curiously, the following code:
var nzDayOfEra = nzCalendar.ordinality(of: .day, in: .era, for: now)
let nycDayOfEra = nycCalendar.ordinality(of: .day, in: .era, for: now)
Gives the same value for both NZ and NYC. I'm not sure why.
EDIT:
Ok, I did some experimenting and got code that works. What I do is to convert both dates to month/day/year date components using a calendar set to the local time zone for each time. Then I use a method dateComponents(_:from:to:)
to calculate the difference between those 2 DateComponents
, in days:
import UIKit
let date = Date()
guard let nycTimeZone = TimeZone(abbreviation: "EST"),
let nzTimeZone = TimeZone(abbreviation: "NZDT") else {
fatalError()
}
var nycCalendar = Calendar(identifier: .gregorian)
nycCalendar.timeZone = nycTimeZone
var nzCalendar = Calendar(identifier: .gregorian)
nzCalendar.timeZone = nzTimeZone
let now = Date()
let nycDateComponents = nycCalendar.dateComponents([.month, .day, .year], from: now)
let nzDateComponents = nzCalendar.dateComponents([.month, .day, .year], from: now)
let difference = Calendar.current.dateComponents([.day],
from: nycDateComponents,
to: nzDateComponents)
let daysDifference = difference.days
As of this writing that gives a daysDifference of 1. Since we're using the dateComponents(_:from:to:)
function, it takes care of the math to calculate the number of days difference between the 2 month/day/year DateComponents
.
Getting the difference between two Dates (months/days/hours/minutes/seconds) in Swift
Xcode 8.3 • Swift 3.1 or later
You can use Calendar to help you create an extension to do your date calculations as follow:
extension Date {
/// Returns the amount of years from another date
func years(from date: Date) -> Int {
return Calendar.current.dateComponents([.year], from: date, to: self).year ?? 0
}
/// Returns the amount of months from another date
func months(from date: Date) -> Int {
return Calendar.current.dateComponents([.month], from: date, to: self).month ?? 0
}
/// Returns the amount of weeks from another date
func weeks(from date: Date) -> Int {
return Calendar.current.dateComponents([.weekOfMonth], from: date, to: self).weekOfMonth ?? 0
}
/// Returns the amount of days from another date
func days(from date: Date) -> Int {
return Calendar.current.dateComponents([.day], from: date, to: self).day ?? 0
}
/// Returns the amount of hours from another date
func hours(from date: Date) -> Int {
return Calendar.current.dateComponents([.hour], from: date, to: self).hour ?? 0
}
/// Returns the amount of minutes from another date
func minutes(from date: Date) -> Int {
return Calendar.current.dateComponents([.minute], from: date, to: self).minute ?? 0
}
/// Returns the amount of seconds from another date
func seconds(from date: Date) -> Int {
return Calendar.current.dateComponents([.second], from: date, to: self).second ?? 0
}
/// Returns the a custom time interval description from another date
func offset(from date: Date) -> String {
if years(from: date) > 0 { return "\(years(from: date))y" }
if months(from: date) > 0 { return "\(months(from: date))M" }
if weeks(from: date) > 0 { return "\(weeks(from: date))w" }
if days(from: date) > 0 { return "\(days(from: date))d" }
if hours(from: date) > 0 { return "\(hours(from: date))h" }
if minutes(from: date) > 0 { return "\(minutes(from: date))m" }
if seconds(from: date) > 0 { return "\(seconds(from: date))s" }
return ""
}
}
Using Date Components Formatter
let dateComponentsFormatter = DateComponentsFormatter()
dateComponentsFormatter.allowedUnits = [.second, .minute, .hour, .day, .weekOfMonth, .month, .year]
dateComponentsFormatter.maximumUnitCount = 1
dateComponentsFormatter.unitsStyle = .full
dateComponentsFormatter.string(from: Date(), to: Date(timeIntervalSinceNow: 4000000)) // "1 month"
let date1 = DateComponents(calendar: .current, year: 2014, month: 11, day: 28, hour: 5, minute: 9).date!
let date2 = DateComponents(calendar: .current, year: 2015, month: 8, day: 28, hour: 5, minute: 9).date!
let years = date2.years(from: date1) // 0
let months = date2.months(from: date1) // 9
let weeks = date2.weeks(from: date1) // 39
let days = date2.days(from: date1) // 273
let hours = date2.hours(from: date1) // 6,553
let minutes = date2.minutes(from: date1) // 393,180
let seconds = date2.seconds(from: date1) // 23,590,800
let timeOffset = date2.offset(from: date1) // "9M"
let date3 = DateComponents(calendar: .current, year: 2014, month: 11, day: 28, hour: 5, minute: 9).date!
let date4 = DateComponents(calendar: .current, year: 2015, month: 11, day: 28, hour: 5, minute: 9).date!
let timeOffset2 = date4.offset(from: date3) // "1y"
let date5 = DateComponents(calendar: .current, year: 2017, month: 4, day: 28).date!
let now = Date()
let timeOffset3 = now.offset(from: date5) // "1w"
Difference between two NSDates in Months and Years in Swift iOS
You can do this in following way...
//set start & end date in correct format
let strStartDate = "September 2019"
let strEndDate = "December 2019"
//create date formatter
let formatter = DateFormatter()
formatter.dateFormat = "MMMM yyyy"
//convert string into date object
guard let startDate = formatter.date(from: strStartDate) else {
print("invalid start date")
return
}
//convert string into date object
guard let endDate = formatter.date(from: strEndDate) else {
print("invalid end date time")
return
}
//calculate the month from end date and that should not exceed the start date
for month in 1...6 {
if let dt = Calendar.current.date(byAdding: .month, value: -month, to: endDate) {
if dt.compare(startDate) == .orderedAscending {
break
}
print(formatter.string(from: dt!))
}
}
Get minutes and hours between two NSDates?
Mac OS X 10.10 Yosemite introduces the smart NSDateComponentsFormatter to display time intervals in components like 18h 56m 4s
This result of this snippet is the formatted time interval from midnight until now.
let calendar = NSCalendar.currentCalendar()
let midnight = calendar.startOfDayForDate(NSDate())
let timeinterval = NSDate().timeIntervalSinceDate(midnight)
let formatter = NSDateComponentsFormatter()
formatter.unitsStyle = .Abbreviated
formatter.stringFromTimeInterval(timeinterval)
Find difference in seconds between NSDates as integer using Swift
Your attempt to calculate elapsedTime
is incorrect. In Swift 3, it would be:
let elapsed = Date().timeIntervalSince(timeAtPress)
Note the ()
after the Date
reference. The Date()
instantiates a new date object, and then timeIntervalSince
returns the time difference between that and timeAtPress
. That will return a floating point value (technically, a TimeInterval
).
If you want that as truncated to a Int
value, you can just use:
let duration = Int(elapsed)
And, BTW, your definition of the timeAtPress
variable doesn't need to instantiate a Date
object. I presume you intended:
var timeAtPress: Date!
That defines the variable as a Date
variable (an implicitly unwrapped one), but you'd presumably defer the actual instantiation of that variable until pressed
is called.
Alternatively, I often use CFAbsoluteTimeGetCurrent()
, e.g.,
var start: CFAbsoluteTime!
And when I want to set startTime
, I do the following:
start = CFAbsoluteTimeGetCurrent()
And when I want to calculate the number of seconds elapsed, I do the following:
let elapsed = CFAbsoluteTimeGetCurrent() - start
It's worth noting that the CFAbsoluteTimeGetCurrent
documentation warns us:
Repeated calls to this function do not guarantee monotonically increasing results. The system time may decrease due to synchronization with external time references or due to an explicit user change of the clock.
This means that if you're unfortunate enough to measure elapsed time when one of these adjustments take place, you can end up with incorrect elapsed time calculation. This is true for NSDate
/Date
calculations too. It's safest to use a mach_absolute_time
based calculation (most easily done with CACurrentMediaTime
):
let start = CACurrentMediaTime()
and
let elapsed = CACurrentMediaTime() - start
This uses mach_absolute_time
, but avoids some of its complexities outlined in Technical Q&A QA1398.
Remember, though, that CACurrentMediaTime
/mach_absolute_time
will be reset when the device is rebooted. So, bottom line, if you need accurate elapsed time calculations while an app is running, use CACurrentMediaTime
. But if you're going to save this start time in persistent storage which you might recall when the app is restarted at some future date, then you have to use Date
or CFAbsoluteTimeGetCurrent
, and just live with any inaccuracies that may entail.
Calculate the difference between two dates. Swift 1.2
To calculate the endtime you can use
timerEndTime = NSDate(timeIntervalSinceNow:NSTimeInterval(oreWanted * 11))
So you get a NSDate
object. Now you can fire a UILocalNotification
at that calculated time:
Note: You need to ask for notification permissions when your app starts up. I have simplified this here with notificationsAllowed
and soundsAllowed
which are boolean variables in my AppDelegate.
let appDelegate = UIApplication.sharedApplication.delegate as! AppDelegate
if appDelegate.notificationsAllowed {
let notification = UILocalNotification()
notification.fireDate = timerEndTime
notification.timeZone = NSTimeZone.defaultTimeZone()
notification.alertBody = "Notification body text"
notification.alertTitle = "Notification alert title"
if appDelegate.soundsAllowed {
notification.soundName = UILocalNotificationDefaultSoundName
}
UIApplication.sharedApplication().scheduleLocalNotification(notification)
}
EDIT
Register the app for notifications in AppDelegate:
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
var notificationsAllowed = false
var notificationSoundAllowed = false
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
let notificationSettings = UIUserNotificationSettings(forTypes: UIUserNotificationType.Sound | UIUserNotificationType.Alert, categories: nil)
UIApplication.sharedApplication().registerUserNotificationSettings(notificationSettings)
return true
}
func application(application: UIApplication, didRegisterUserNotificationSettings notificationSettings: UIUserNotificationSettings) {
if notificationSettings.types & UIUserNotificationType.Alert != nil {
self.notificationsAllowed = true
}
if notificationSettings.types & UIUserNotificationType.Sound != nil {
self.notificationSoundAllowed = true
}
}
Related Topics
How to Zip More Than 4 Publishers
Uisearchcontroller in Navigationitem iOS 11 Apple Way
How to Check If a String Contains Chinese in Swift
Swiftui - How to Use Oncommand with Nsmenuitem on MACos
Swiftui: Dismiss View Within MACos Navigationview
Swift - Take Nil as Argument in Generic Function with Optional Argument
Swift: Dictionary Access via Index
How to Override Layerclass in Swift
Changing Tab Bar Font in Swift
Difference Between Switch Cases "@Unknown Default" and "Default" in Swift 5
Combining Two Conditions in Nspredicate
Swift Check Type Against a Generic Type
Uisplitviewcontroller in Portrait on iPhone Always Show Master and Detail in iOS 8
Swift - Lazy Var VS. Let When Creating Views Programmatically (Saving Memory)
Difference Between Dispatchqueue Types in Swift