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)!
}
How to get an array of days between two dates in Swift?
You could implement it like this:
func datesRange(from: Date, to: Date) -> [Date] {
// in case of the "from" date is more than "to" date,
// it should returns an empty array:
if from > to { return [Date]() }
var tempDate = from
var array = [tempDate]
while tempDate < to {
tempDate = Calendar.current.date(byAdding: .day, value: 1, to: tempDate)!
array.append(tempDate)
}
return array
}
Usage:
let today = Date()
let nextFiveDays = Calendar.current.date(byAdding: .day, value: 5, to: today)!
let myRange = datesRange(from: today, to: nextFiveDays)
print(myRange)
/*
[2018-03-20 14:46:03 +0000,
2018-03-21 14:46:03 +0000,
2018-03-22 14:46:03 +0000,
2018-03-23 14:46:03 +0000,
2018-03-24 14:46:03 +0000,
2018-03-25 14:46:03 +0000]
*/
How to determine date falls in between two dates swift
If you have Date objects, they are Comparable and Equatable. You can write code like:
if breakDate >= startDate && breakDate <= endDate then {
// breakDate is between startDate and endDate
}
Edit:
As pointed out by LeoDabus in the comments, you could also use the pattern match operator (although I personally don't like it)
if startDate ... endDate ~= breakDate then {
// breakDate is between startDate and endDate
}
or contains:
if (startDate...endDate).contains(breakDate) then {
// breakDate is between startDate and endDate
}
If you have date strings, create a date formatter that converts your date strings to Date
objects, then use code like the above.
If the date strings are always in "Internet" date format (ISO 8601), and you are certain they will always be in the same time zone, you can also use string comparison and compare the date strings directly (using any of the above forms of comparison, except maybe contains?)
How can I generate every date between two dates to a given granularity?
Logic could be something like this. Create array with start date as first element. Then append dates with added components to last date until new date should be greater than end date
func pad(to repletion: Int, _ component: Calendar.Component, from: Date? = nil, to: Date? = nil) {
guard let start = from ?? self.earliest, let end = to ?? self.latest else {
print("no date given and none available")
return
}
var components = DateComponents()
components.setValue(repletion, for: component)
let calendar = Calendar.current
var dates = [start] // results
while start < end {
if let newDate = calendar.date(byAdding: components, to: dates.last!),
newDate <= end {
dates.append(newDate)
} else { break }
}
}
Calculating the difference between two dates in Swift
I ended up creating a custom operator for Date
:
extension Date {
static func - (lhs: Date, rhs: Date) -> TimeInterval {
return lhs.timeIntervalSinceReferenceDate - rhs.timeIntervalSinceReferenceDate
}
}
With this operator I can now compute the difference between two dates on a more abstract level without caring about timeIntervalSinceReferenceDate
or what exactly the reference date is – and without losing precision, for example:
let delta = toDate - fromDate
Obviously, I didn't change much, but for me it's a lot more readable and consequent: Swift has the +
operator already implemented for a Date
and a TimeInterval
:
/// Returns a `Date` with a specified amount of time added to it.
public static func + (lhs: Date, rhs: TimeInterval) -> Date
So it's already supporting
Date + TimeInterval = Date
Consequently, it should also support
Date - Date = TimeInterval
in my opinion and that's what I added with the simple implementation of the -
operator. Now I can simply write the example function exactly as mentioned in my question:
func computeNewDate(from fromDate: Date, to toDate: Date) -> Date
let delta = toDate - fromDate // `Date` - `Date` = `TimeInterval`
let today = Date()
if delta < 0 {
return today
} else {
return today + delta // `Date` + `TimeInterval` = `Date`
}
}
It might very well be that this has some downsides that I'm not aware of at this moment and I'd love to hear your thoughts on this.
Array for dates between two dates
// minDate and maxDate represent your date range
NSCalendar *gregorianCalendar = [[NSCalendar alloc] initWithCalendarIdentifier: NSGregorianCalendar];
NSDateComponents *days = [[NSDateComponents alloc] init];
NSInteger dayCount = 0;
while ( TRUE ) {
[days setDay: ++dayCount];
NSDate *date = [gregorianCalendar dateByAddingComponents: days toDate: minDate options: 0];
if ( [date compare: maxDate] == NSOrderedDescending )
break;
// Do something with date like add it to an array, etc.
}
[days release];
[gregorianCalendar release];
How to get dates for every Friday between two dates?
You just need to add a weekday parameter to your method and check if the weekday of the date inside the loop before adding it to your array:
extension Formatter {
static let date = DateFormatter()
}
func dates(for date: String, weekday: Int? = nil) -> [String] {
Formatter.date.locale = Locale(identifier: "en_US_POSIX")
Formatter.date.dateFormat = "yyyy-MM-dd"
// first get the endDate
guard var endDate = Formatter.date.date(from: date) else { return [] }
// for calendrical calculations you should use noon time
endDate = Calendar.current.date(bySettingHour: 12, minute: 0, second: 0, of: endDate)!
// lets get todays noon time to start
var date = Calendar.current.date(bySettingHour: 12, minute: 0, second: 0, of: Date())!
var dates: [String] = []
// while date less than or equal to end date
while date <= endDate {
if weekday == nil {
dates.append(Formatter.date.string(from: date))
date = Calendar.current.date(byAdding: .day, value: 1, to: date)!
} else if let weekday = weekday, Calendar.current.component(.weekday, from: date) == weekday {
// add the formatted date to the array
dates.append(Formatter.date.string(from: date))
date = Calendar.current.date(byAdding: .weekOfYear, value: 1, to: date)!
} else {
date = Calendar.current.date(byAdding: .day, value: 1, to: date)!
}
}
return dates
}
dates(for: "2019-12-25") // ["2019-10-23", "2019-10-24", "2019-10-25", "2019-10-26", "2019-10-27", "2019-10-28", "2019-10-29", "2019-10-30", "2019-10-31", "2019-11-01", "2019-11-02", "2019-11-03", "2019-11-04", "2019-11-05", "2019-11-06", "2019-11-07", "2019-11-08", "2019-11-09", "2019-11-10", "2019-11-11", "2019-11-12", "2019-11-13", "2019-11-14", "2019-11-15", "2019-11-16", "2019-11-17", "2019-11-18", "2019-11-19", "2019-11-20", "2019-11-21", "2019-11-22", "2019-11-23", "2019-11-24", "2019-11-25", "2019-11-26", "2019-11-27", "2019-11-28", "2019-11-29", "2019-11-30", "2019-12-01", "2019-12-02", "2019-12-03", "2019-12-04", "2019-12-05", "2019-12-06", "2019-12-07", "2019-12-08", "2019-12-09", "2019-12-10", "2019-12-11", "2019-12-12", "2019-12-13", "2019-12-14", "2019-12-15", "2019-12-16", "2019-12-17", "2019-12-18", "2019-12-19", "2019-12-20", "2019-12-21", "2019-12-22", "2019-12-23", "2019-12-24", "2019-12-25"]
dates(for: "2019-12-25", weekday: 6) // ["2019-10-25", "2019-11-01", "2019-11-08", "2019-11-15", "2019-11-22", "2019-11-29", "2019-12-06", "2019-12-13", "2019-12-20"]
func firstDayOfTheMonth(until date: String) -> [String] {
Formatter.date.locale = Locale(identifier: "en_US_POSIX")
Formatter.date.dateFormat = "yyyy-MM-dd"
guard let endDate = Formatter.date.date(from: date) else { return [] }
var date = Date()
var dates: [String] = []
// while date less than or equal to end date
while let firstDayOfTheMonth = Calendar.current.nextDate(after: date, matching: .init(day: 1), matchingPolicy: .nextTime), firstDayOfTheMonth <= endDate {
dates.append(Formatter.date.string(from: firstDayOfTheMonth))
date = firstDayOfTheMonth
}
return dates
}
firstDayOfTheMonth(until: "2019-12-25") // ["2019-11-01", "2019-12-01"]
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
A method which returns an array of dates that are in between two dates - Swift 3
You are adding 1 to the same start date so your array is filled with the same date over and over. Simply replace 1
with the loop index + 1.
for i in 0 ... 30 {
if let newDate = cal.date(byAdding: .day, value: i + 1, to: startDate) {
dates.append(newDate)
}
}
And you don't need the start
variable.
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")
}
Related Topics
Inter-App Data Migration (Migrating Data to New App Version)
How to Check If a String Contains Another String in Swift
Sending Json Array Via Alamofire
Overriding Superclass Property With Different Type in Swift
Firestore Search Array Contains For Multiple Values
Access Firebase Variable Outside Closure
Check Password String Strength Criteria in Swift
What Does the Dollar Sign Do in Swift/Swiftui
Remove or Edit User Location Blue Pulsing Circle
How to Make a Swiftui List Scroll Automatically
How to Create Instances of Managed Object Subclasses in a Nsmanagedobject Swift Extension
Setting Device Orientation in Swift Ios