Как я могу рассчитать разницу между двумя датами?

115

Как я могу рассчитать дни между 1 января 2010 г. и (например) 3 февраля 2010 г.?

Фредерик Хайнинк
источник

Ответы:

237
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);

РЕДАКТИРОВАТЬ:

Помните, что NSDateобъекты представляют собой точные моменты времени, с ними не связана информация о часовых поясах. Когда вы конвертируете строку в дату, например, с помощью NSDateFormatter, NSDateFormatterпреобразует время из настроенного часового пояса. Следовательно, количество секунд между двумя NSDateобъектами всегда не зависит от часового пояса.

Кроме того, в этой документации указано, что реализация времени в Какао не учитывает дополнительных секунд, поэтому, если вам нужна такая точность, вам нужно будет свернуть свою собственную реализацию.

dreamlax
источник
5
@RalucaGurau: 86400 - это количество секунд в дне (т.е. 60 секунд, умноженное на 60 минут, умноженное на 24 часа). Это не имеет ничего общего с месяцем.
dreamlax
18
Не во все дни 86400 секунд. Для тривиального примера это нормально, но в реальном мире это плохая идея. Смена летнего времени, дополнительные секунды и т. Д. Могут повлиять на это. NSCalendar может сказать вам, сколько секунд в данном дне.
NeilInglis
2
@muthukumar: Не для iOS, этот метод доступен только в Mac OS X. Этот вопрос помечен, cocoaи cocoa-touchпоэтому этот ответ применим только к Mac OS X.
dreamlax
1
Количество дней между любыми двумя моментами времени всегда будет 86400. Находятся ли люди в стадии обмана, чтобы проснуться на час раньше, чем обычно, или нет, не имеет значения, что день длится 86400 секунд (без учета скачка секунд)
dreamlax
1
Просто хочу добавить, что если у вас нет этого +0000 в конце, вы всегда будете получать нулевые даты и значение 0 в diff, несмотря ни на что. Так что не попадайтесь в эту ловушку.
Volomike
84

Вы можете использовать что-то вроде этого:

NSDateComponents *components;
NSInteger days;

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

Я считаю, что этот метод учитывает такие ситуации, как даты, которые охватывают изменение летнего времени.

Кейси Флезер
источник
2
есть ли простой способ также игнорировать время для указанных дат?
Михай Тимар
можно соответственно изменить для других календарных единиц :), используемых для единицы года.
техническая подкованность,
NSDateобъекты уже не зависят от часового пояса. Информация о часовом поясе удаляется при синтаксическом анализе дат, например NSDateFormatter, чтобы NSDateобъекты представляли точные моменты времени. Следовательно, если у вас уже есть startDateи endDate, эти два объекта будут находиться на расстоянии x секунд друг от друга. Часовые пояса тут ни при чем.
dreamlax
@ Бенджамин: Почему ты так говоришь?
dreamlax
dreamlax, ваш ответ неверен. Легко и просто. Вычислите количество дней между 12 полуднем 1 января по летнему времени и 12 полуднем 1 апреля, и ваша формула не сработает. Это ленивая формула, и разработчики должны использовать объект NSDateComponents для ее вычисления.
Rickster
25
NSTimeInterval diff = [date2 timeIntervalSinceDate:date1]; // in seconds

где date1и date2находятся NSDateрусские.

Также обратите внимание на определение NSTimeInterval:

typedef double NSTimeInterval;
Четан
источник
Обратите внимание, что NSTimeInterval действительно является двойным, поэтому вы можете использовать его как любое другое число.
Кендалл Хельмштеттер Гельнер,
19

Проверить это. Он заботится о переходе на летнее время и високосном году, поскольку для расчета используется календарь iOS. Вы можете изменить строку и условия, включив минуты с часами и днями.

+(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 @""; 
}
Анкиш Джайн
источник
этот метод - идеальный способ вычисления разницы во времени.
Moxarth
просто вы можете оставить elseif со всеми этими условиями if. в противном случае вы получите только один формат времени.
Moxarth
3

В Swift 5 и iOS 12, в соответствии с вашими потребностями, вы можете использовать один из двух следующих способов, чтобы найти разницу между двумя датами в днях.


# 1. Использование Calendar«S dateComponents(_:from:to:)метод

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. Использование DateComponentsFormatter«S string(from:to:)метод

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")
Иману Пети
источник
1

Swift 4
Попробуйте это и посмотрите (диапазон дат со строкой):

// 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
источник
Не во все дни такое количество секунд.
Паван
@Pavan - Приглашаем вас поделиться своими впечатлениями, обновив этот ответ и сделав его лучше.
Krunal
Чтобы сделать его лучше, мне потребовалось бы переписать весь ваш ответ, и в этом случае его также можно удалить, потому что это будет то же решение, что и в приведенном выше ответе, в котором не используются жестко запрограммированные значения :)
Паван
0

Вы можете найти разницу, преобразовав дату в секунды и взяв для этого временной интервал с 1970 года, а затем вы можете найти разницу между двумя датами.

Химаншу Бхатия
источник
когда две даты могут быть вычислены друг с другом напрямую (при условии, что один и тот же временной интервал). Есть ли какая-то конкретная причина сначала рассчитать обе даты с 1970 года, а затем найти разницу?
Adeel
0

Чтобы найти разницу, вам нужно получить текущую дату и дату в будущем. В следующем случае я использовал 2 дня в качестве примера будущей даты. Рассчитано:

2 days* 24 hours* 60 minutes* 60 seconds. Мы ожидаем, что количество секунд за 2 дня составит 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
Рой Закай
источник
1
Пожалуйста, не публикуйте только код в качестве ответа, но также объясните, что делает ваш код и как он решает проблему вопроса. Ответы с объяснением обычно более высокого качества и с большей вероятностью получат положительные отзывы.
Марк Роттевил