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)
Swift 3 - find number of calendar days between two dates
Turns out this is much simpler to do in Swift 3:
extension Date {
func interval(ofComponent comp: Calendar.Component, fromDate date: Date) -> Int {
let currentCalendar = Calendar.current
guard let start = currentCalendar.ordinality(of: comp, in: .era, for: date) else { return 0 }
guard let end = currentCalendar.ordinality(of: comp, in: .era, for: self) else { return 0 }
return end - start
}
}
Edit
Comparing the ordinality of the two dates should be within the same era
instead of the same year
, since naturally the two dates may fall in different years.
Usage
let yesterday = Date(timeInterval: -86400, since: Date())
let tomorrow = Date(timeInterval: 86400, since: Date())
let diff = tomorrow.interval(ofComponent: .day, fromDate: yesterday)
// return 2
Number of days between two NSDates
Here's an implementation I used to determine the number of calendar days between two dates:
+ (NSInteger)daysBetweenDate:(NSDate*)fromDateTime andDate:(NSDate*)toDateTime
{
NSDate *fromDate;
NSDate *toDate;
NSCalendar *calendar = [NSCalendar currentCalendar];
[calendar rangeOfUnit:NSCalendarUnitDay startDate:&fromDate
interval:NULL forDate:fromDateTime];
[calendar rangeOfUnit:NSCalendarUnitDay startDate:&toDate
interval:NULL forDate:toDateTime];
NSDateComponents *difference = [calendar components:NSCalendarUnitDay
fromDate:fromDate toDate:toDate options:0];
return [difference day];
}
EDIT:
Fantastic solution above, here's Swift version below as an extension on NSDate
:
extension NSDate {
func numberOfDaysUntilDateTime(toDateTime: NSDate, inTimeZone timeZone: NSTimeZone? = nil) -> Int {
let calendar = NSCalendar.currentCalendar()
if let timeZone = timeZone {
calendar.timeZone = timeZone
}
var fromDate: NSDate?, toDate: NSDate?
calendar.rangeOfUnit(.Day, startDate: &fromDate, interval: nil, forDate: self)
calendar.rangeOfUnit(.Day, startDate: &toDate, interval: nil, forDate: toDateTime)
let difference = calendar.components(.Day, fromDate: fromDate!, toDate: toDate!, options: [])
return difference.day
}
}
A bit of force unwrapping going on which you may want to remove depending on your use case.
The above solution also works for time zones other than the current time zone, perfect for an app that shows information about places all around the world.
How to calculate days between 2 dates
You need to convert the endDate
string into a Date
using the date formatter. Then pass date
and the new Date
to the dateComponents
call. Then access the day
property of the resulting components
.
And use Calendar, not NSCalendar.
let startDate = Date()
let endDateString = "16.05.2018"
let formatter = DateFormatter()
formatter.dateFormat = "dd.MM.yyyy"
if let endDate = formatter.date(from: endDateString) {
let components = Calendar.current.dateComponents([.day], from: startDate, to: endDate)
print("Number of days: \(components.day!)")
} else {
print("\(endDateString) can't be converted to a Date")
}
How can i calculate the days between two dates?
Try this code, updated for Swift 2.0
let dateFormatter = NSDateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd"
let first = "2010-09-01"
let firstDate = dateFormatter.dateFromString(first)!
let last = "2010-09-05"
let lastDate = dateFormatter.dateFromString(last)!
let currentCalendar = NSCalendar.currentCalendar()
let timeUnitDay = NSCalendarUnit.Day
let daysBetween = currentCalendar.components(timeUnitDay, fromDate: firstDate, toDate: lastDate, options: NSCalendarOptions.MatchStrictly)
print(daysBetween.day)
Days between 2 NSDates in a calendar year swift
What you need is to compute the next occurrence of the (day and month
component of the) birthday after today:
let cal = NSCalendar.currentCalendar()
let today = cal.startOfDayForDate(NSDate())
let dayAndMonth = cal.components(.CalendarUnitDay | .CalendarUnitMonth,
fromDate: birthday)
let nextBirthDay = cal.nextDateAfterDate(today,
matchingComponents: dayAndMonth,
options: .MatchNextTimePreservingSmallerUnits)!
Remarks:
The purpose of the
MatchNextTimePreservingSmallerUnits
option is
that if the birthday is on February 29 (in the Gregorian calendar), its next occurrence will be
computed as March 1 if the year is not a leap year.You might need to check first if the birthday is today, as it seems
thatnextDateAfterDate()
would return the next birthday in that case.
Then you can compute the difference in days as usual:
let diff = cal.components(.CalendarUnitDay,
fromDate: today,
toDate: nextBirthDay,
options: nil)
println(diff.day)
Update for Swift 2.2 (Xcode 7.3):
let cal = NSCalendar.currentCalendar()
let today = cal.startOfDayForDate(NSDate())
let dayAndMonth = cal.components([.Day, .Month],
fromDate: birthday)
let nextBirthDay = cal.nextDateAfterDate(today,
matchingComponents: dayAndMonth,
options: .MatchNextTimePreservingSmallerUnits)!
let diff = cal.components(.Day,
fromDate: today,
toDate: nextBirthDay,
options: [])
print(diff.day)
Update for Swift 3 (Xcode 8 GM):
let cal = Calendar.current
let today = cal.startOfDay(for: Date())
let dayAndMonth = cal.dateComponents([.day, .month], from: birthday)
let nextBirthDay = cal.nextDate(after: today, matching: dayAndMonth,
matchingPolicy: .nextTimePreservingSmallerComponents)!
let diff = cal.dateComponents([.day], from: today, to: nextBirthDay)
print(diff.day!)
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"
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
.
All dates between two Date objects (Swift)
Just add one day unit to the date until it reaches
the current date (Swift 2 code):
var date = startDateNSDate // first date
let endDate = NSDate() // last date
// Formatter for printing the date, adjust it according to your needs:
let fmt = NSDateFormatter()
fmt.dateFormat = "dd/MM/yyyy"
// While date <= endDate ...
while date.compare(endDate) != .OrderedDescending {
print(fmt.stringFromDate(date))
// Advance by one day:
date = calendar.dateByAddingUnit(.Day, value: 1, toDate: date, options: [])!
}
Update for Swift 3:
var date = startDate // first date
let endDate = Date() // last date
// Formatter for printing the date, adjust it according to your needs:
let fmt = DateFormatter()
fmt.dateFormat = "dd/MM/yyyy"
while date <= endDate {
print(fmt.string(from: date))
date = Calendar.current.date(byAdding: .day, value: 1, to: date)!
}
Related Topics
iOS Firebase Push Notifications:How to Give Firebase User's Device Token and Send Notification
How to Exclude Notes and Reminders Apps from the Uiactivityviewcontroller
How to Use an .A Static Library in Swift
Is This Possible to Apply the Alternative Icon to the iOS Application
How to Detect iPhone Is on Silent Mode
Sprite Kit & Playing Sound Leads to App Termination
How to Get the Name of Image Picked Through Photo Library in Iphone
How to Get Text/String from Nth Line of Uilabel
Detecting a Point in a Mkpolygon Broke with iOS7 (Cgpathcontainspoint)
Passing Data Between View Controllers Using Segue
How to Make Outlet Connection to a Constraint in Ib
iPad Safari - Make Keyboard Disappear
How to Change the Status Bar Background Color and Text Color on iOS 13
How to Use Protocol as Associatedtype in Another Protocol in Swift