120

How can I calculate the days between 1 Jan 2010 and (for example) 3 Feb 2010?

Cristik
  • 30,989
  • 25
  • 91
  • 127
Frederik Heyninck
  • 3,493
  • 4
  • 20
  • 19

9 Answers9

245
NSDate *date1 = [NSDate dateWithString:@"2010-01-01 00:00:00 +0000"];
NSDate *date2 = [NSDate dateWithString:@"2010-02-03 00:00:00 +0000"];

NSTimeInterval secondsBetween = [date2 timeIntervalSinceDate:date1];

int numberOfDays = secondsBetween / 86400;

NSLog(@"There are %d days in between the two dates.", numberOfDays);

EDIT:

Remember, NSDate objects represent exact moments of time, they do not have any associated time-zone information. When you convert a string to a date using e.g. an NSDateFormatter, the NSDateFormatter converts the time from the configured timezone. Therefore, the number of seconds between two NSDate objects will always be time-zone-agnostic.

Furthermore, this documentation specifies that Cocoa's implementation of time does not account for leap seconds, so if you require such accuracy, you will need to roll your own implementation.

dreamlax
  • 93,976
  • 29
  • 161
  • 209
  • why it is 86400 ? If it is February that has 28 days ...or other month it should be different . An additional method has to be added – Raluca Lucaci May 14 '12 at 15:05
  • 5
    @RalucaGurau: 86400 is the number of seconds in a day (i.e. 60 seconds, times 60 minuts, times 24 hours). It has nothing to so with the month. – dreamlax May 14 '12 at 18:50
  • 18
    Not all days have 86400 seconds. For a trivial example that's fine but it's not a good idea in the real world. DST changes, leap seconds, etc can all mess with it. NSCalendar can tell you how many seconds are in a given day. – NeilInglis Jun 07 '12 at 21:19
  • dateWtihString is Not Available in NSDate – muthukumar Sep 07 '12 at 09:50
  • 2
    @muthukumar: Not on iOS, the method is only available on Mac OS X. This question is tagged `cocoa` and not `cocoa-touch` so this answer only applies to Mac OS X. – dreamlax Sep 07 '12 at 11:11
  • @NeilInglis: [This documentation](https://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/DatesAndTimes/Articles/dtCalendricalCalculations.html) says Cocoa's time calculations never incorporate leap seconds. POSIX also mandates that a day has exactly 86400 seconds. – dreamlax Oct 29 '14 at 06:37
  • @NeilInglis: futhermore, NSDate objects are time-zone-agnostic, they represent exact moments in time, therefore, time-zone-specific adjustments such as DST do not affect the result of the calculation. – dreamlax Oct 29 '14 at 07:00
  • Finding the number of days between identical times when switching from standard time to daylights time breaks the assumption there are 86400 seconds in a day. Therefore I'm down voting this answer. Instead use somegeekintn's answer below. – Rickster Apr 07 '15 at 21:41
  • @Rickster: You obviously did not read my edit. Daylight saving time is a property of a time zone. `NSDate` objects have absolutely nothing to do with time zones. They represent exact moments in time. Since Cocoa does not account of leap seconds, the number of seconds will always be 86400. – dreamlax Apr 08 '15 at 01:59
  • All my NSDate objects are set to noon local time. The difference between 4/7/15 noon pacific time and 4/8/15 noon pacific time is NOT 86400 seconds, but is in fact 82800 seconds. Therefore that equation is wrong. Using NSDateComponents to calculate the difference gives the correct answer always, regardless of daylight savings time. – Rickster Apr 09 '15 at 23:23
  • @Rickster: `NSDate` objects are not set to any timezone. They have absolutely nothing to do with timezones. If you want the number of calendar days between two moments in time, you need to use a calendar (like somegeekintn's answer). If you want to calculate the number of 24 hour periods between two moments in time, the above works fine. Again, `NSDate` has nothing to do with timezones. You can find out what time an `NSDate` represents in a particular timezone, but by itself, it represents a single moment in time and nothing else. POSIX defines each day to have 86400 seconds, so working – dreamlax Apr 10 '15 at 01:46
  • out the number of days between any two moments in time will always be found by dividing by 86400. – dreamlax Apr 10 '15 at 01:46
  • That's exactly my point. Your formula calculates the number of 24 hour segments between two `NSDate` objects. The original question is how to calculate the number of days between two `NSDate` objects. Your answer is correct for calculating 24 hour segments, but is incorrect in determining the number of days between two `NSDate` objects, because not every day of the year is 86400 seconds. For example, in California, March 8, 2015 was 82800 seconds, not 86400 seconds. – Rickster Apr 11 '15 at 03:07
  • This argument reminds me of this: http://www.deathandtaxesmag.com/233107/two-body-builders-argue-on-the-internet-about-how-many-days-are-in-the-week/ – Rickster Apr 11 '15 at 03:09
  • @Rickster: You have to remember that `NSDate` objects have no timezone. Once you've got an `NSDate` object, that object represents the same moment in time regardless of the calendar (Gregorian, Buddhist, Hindu, etc) or timezone. If you are converting dates and times **from** a particular timezone or calendar, then of course the resulting `NSDate` objects may not be 86400 seconds apart. Since `NSDate` objects don't represent calendar dates or times, you can't calculate the number of calendar days between two of them without an `NSCalendar`. If you want 24-hour periods, dividing by 86400 works. – dreamlax Apr 20 '15 at 23:30
  • @Rickster: The `NSDate` class probably should have been called `NSMomentInTime`, since it doesn't actually represent a date, but a moment in time. – dreamlax Apr 20 '15 at 23:31
  • 1
    The number of days between any two moments in time will always be 86400. Whether humans are in the stage of fooling themselves to wake up an hour earlier than normal or not makes no difference to the fact that a day is 86400 seconds long (ignoring leap seconds) – dreamlax Apr 21 '15 at 01:32
  • @Rickster: http://en.wikipedia.org/wiki/Day#International_System_of_Units_.28SI.29 – dreamlax Apr 21 '15 at 01:33
  • 1
    Just want to add that if you don't have that +0000 on the end, you'll be getting null dates and a value of 0 always on the diff, no matter what. So, don't fall in that trap. – Volomike Jun 17 '16 at 03:09
85

You may want to use something like this:

NSDateComponents *components;
NSInteger days;

components = [[NSCalendar currentCalendar] components: NSDayCalendarUnit 
        fromDate: startDate toDate: endDate options: 0];
days = [components day];

I believe this method accounts for situations such as dates that span a change in daylight savings.

Casey Fleser
  • 5,707
  • 1
  • 32
  • 43
  • 2
    is there a simple way to also ignore the time for the given dates? – Mihai Timar Oct 18 '13 at 07:40
  • can be accordingly changed for other calendar units :) used for Year unit. – tech savvy Feb 21 '14 at 10:49
  • `NSDate` objects are already time-zone agnostic. The time-zone information is removed when parsing dates with e.g. `NSDateFormatter`, so that `NSDate` objects represent exact moments in time. Therefore, if you already have `startDate` and `endDate`, these two objects will be **x** number of seconds apart. Time-zones will have nothing to do with it. – dreamlax Oct 29 '14 at 07:26
  • @Benjamin: Why do you say that? – dreamlax Dec 10 '14 at 19:02
  • dreamlax, your answer is wrong. Plain and simple. Calculate the number of days between 12 noon January 1 standard time and 12 noon April 1 daylight time, and your formula doesn't work. It is a lazy formula and developers should use the NSDateComponents object to calculate this. – Rickster Apr 07 '15 at 21:46
25
NSTimeInterval diff = [date2 timeIntervalSinceDate:date1]; // in seconds

where date1 and date2 are NSDate's.

Also, note the definition of NSTimeInterval:

typedef double NSTimeInterval;
Chetan
  • 46,743
  • 31
  • 106
  • 145
19

Checkout this out. It takes care of daylight saving , leap year as it used iOS calendar to calculate.You can change the string and conditions to includes minutes with hours and days.

+(NSString*)remaningTime:(NSDate*)startDate endDate:(NSDate*)endDate
{
    NSDateComponents *components;
    NSInteger days;
    NSInteger hour;
    NSInteger minutes;
    NSString *durationString;

    components = [[NSCalendar currentCalendar] components: NSCalendarUnitDay|NSCalendarUnitHour|NSCalendarUnitMinute fromDate: startDate toDate: endDate options: 0];

    days = [components day];
    hour = [components hour];
    minutes = [components minute];

    if(days>0)
    {
        if(days>1)
            durationString=[NSString stringWithFormat:@"%d days",days];
        else
            durationString=[NSString stringWithFormat:@"%d day",days];
        return durationString;
    }
    if(hour>0)
    {        
        if(hour>1)
            durationString=[NSString stringWithFormat:@"%d hours",hour];
        else
            durationString=[NSString stringWithFormat:@"%d hour",hour];
        return durationString;
    }
    if(minutes>0)
    {
        if(minutes>1)
            durationString = [NSString stringWithFormat:@"%d minutes",minutes];
        else
            durationString = [NSString stringWithFormat:@"%d minute",minutes];

        return durationString;
    }
    return @""; 
}
iPatel
  • 46,010
  • 16
  • 115
  • 137
Ankish Jain
  • 11,305
  • 5
  • 36
  • 34
3

With Swift 5 and iOS 12, according to your needs, you may use one of the two following ways to find the difference between two dates in days.


#1. Using Calendar's dateComponents(_:from:to:) method

import Foundation

let calendar = Calendar.current

let startDate = calendar.date(from: DateComponents(year: 2010, month: 11, day: 22))!
let endDate = calendar.date(from: DateComponents(year: 2015, month: 5, day: 1))!

let dateComponents = calendar.dateComponents([Calendar.Component.day], from: startDate, to: endDate)

print(dateComponents) // prints: day: 1621 isLeapMonth: false
print(String(describing: dateComponents.day)) // prints: Optional(1621)

#2. Using DateComponentsFormatter's string(from:to:) method

import Foundation

let calendar = Calendar.current

let startDate = calendar.date(from: DateComponents(year: 2010, month: 11, day: 22))!
let endDate = calendar.date(from: DateComponents(year: 2015, month: 5, day: 1))!

let formatter = DateComponentsFormatter()
formatter.unitsStyle = .full
formatter.allowedUnits = [NSCalendar.Unit.day]

let elapsedTime = formatter.string(from: startDate, to: endDate)
print(String(describing: elapsedTime)) // prints: Optional("1,621 days")
Imanou Petit
  • 89,880
  • 29
  • 256
  • 218
1

Swift 4
Try this and see (date range with String):

// Start & End date string
let startingAt = "01/01/2018"
let endingAt = "08/03/2018"

// Sample date formatter
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "dd/MM/yyyy"

// start and end date object from string dates
var startDate = dateFormatter.date(from: startingAt) ?? Date()
let endDate = dateFormatter.date(from: endingAt) ?? Date()


// Actual operational logic
var dateRange: [String] = []
while startDate <= endDate {
    let stringDate = dateFormatter.string(from: startDate)
    startDate = Calendar.current.date(byAdding: .day, value: 1, to: startDate) ?? Date()
    dateRange.append(stringDate)
}

print("Resulting Array - \(dateRange)")

Swift 3

var date1 = Date(string: "2010-01-01 00:00:00 +0000")
var date2 = Date(string: "2010-02-03 00:00:00 +0000")
var secondsBetween: TimeInterval = date2.timeIntervalSince(date1)
var numberOfDays: Int = secondsBetween / 86400
print(numberOfDays)
Krunal
  • 77,632
  • 48
  • 245
  • 261
  • Not all days have that amount of seconds. – Pavan Feb 04 '18 at 11:48
  • @Pavan - You are welcomed to share your inputs by updating this answer and make it better. – Krunal Feb 04 '18 at 15:12
  • To make it better would require me rewriting your whole answer, in which case it may as well be deleted because it'll be the same solution as the answer above which doesn't use hardcoded values :) – Pavan Apr 06 '18 at 11:53
1

If you want all the units, not just the biggest one, use one of these 2 methods (based on @Ankish's answer):

Example output: 28 D | 23 H | 59 M | 59 S

+ (NSString *) remaningTime:(NSDate *)startDate endDate:(NSDate *)endDate
{
    NSCalendarUnit units = NSCalendarUnitDay | NSCalendarUnitHour | NSCalendarUnitMinute | NSCalendarUnitSecond;
    NSDateComponents *components = [[NSCalendar currentCalendar] components:units fromDate: startDate toDate: endDate options: 0];
    return [NSString stringWithFormat:@"%ti D | %ti H | %ti M | %ti S", [components day], [components hour], [components minute], [components second]];
}

+ (NSString *) timeFromNowUntil:(NSDate *)endDate
{
    return [self remaningTime:[NSDate date] endDate:endDate];
}

CSawy
  • 904
  • 2
  • 14
  • 25
0

You can find the difference by converting the date in seconds and take time interval since 1970 for this and then you can find the difference between two dates.

  • when two dates can be calculated with each other directly(assuming same time domain). Is there any specific reason of calculating both dates since 1970 first and then finding the difference ? – Adeel Aug 16 '17 at 07:17
0

To find the difference, you need to get the current date and the date in the future. In the following case, I used 2 days for an example of the future date. Calculated by:

2 days * 24 hours * 60 minutes * 60 seconds. We expect the number of seconds in 2 days to be 172,800.

// Set the current and future date
let now = Date()
let nowPlus2Days = Date(timeInterval: 2*24*60*60, since: now)

// Get the number of seconds between these two dates
let secondsInterval = DateInterval(start: now, end: nowPlus2Days).duration

print(secondsInterval) // 172800.0
George
  • 25,988
  • 10
  • 79
  • 133
Roi Zakai
  • 252
  • 3
  • 3
  • 1
    Please don't post only code as an answer, but also provide an explanation what your code does and how it solves the problem of the question. Answers with an explanation are usually of higher quality, and are more likely to attract upvotes. – Mark Rotteveel Apr 25 '20 at 10:26