Як я можу обчислити різницю між двома датами?


Відповіді:


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об'єкти представляють точні моменти часу, вони не мають жодної пов'язаної інформації про часовий пояс. Коли ви перетворюєте рядок у дату, використовуючи, наприклад, an NSDateFormatter, NSDateFormatterперетворює час із налаштованого часового поясу. Тому кількість секунд між двома NSDateоб'єктами завжди буде агностичною за часовим поясом.

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


5
@RalucaGurau: 86400 - це кількість секунд за день (тобто 60 секунд, 60 хвилин, раз 24 години). З місяцем це не має нічого спільного.
dreamlax

18
Не всі дні мають 86400 секунд. Для тривіального прикладу це добре, але це не дуже гарна ідея в реальному світі. Зміни DST, стрибкові секунди тощо можуть все зіткнутися з цим. NSCalendar може повідомити, скільки секунд у заданий день.
NeilInglis

2
@muthukumar: Не на iOS, метод доступний лише на Mac OS X. Це питання позначено тегами, cocoaі не cocoa-touchтак, що ця відповідь стосується лише Mac OS X.
dreamlax

1
Кількість днів між двома моментами завжди буде 86400. Чи люди перебувають у стадії дуріння, щоб прокинутися на годину раніше, ніж зазвичай, чи ні, не має ніякого значення той факт, що день триває 86400 секунд (ігноруючи стрибок секунди)
dreamlax

1
Просто хочу додати, що якщо у вас немає цього +0000 в кінці, ви отримаєте нульові дати та значення 0 завжди на різниці, незалежно від того. Отже, не потрапляйте в цю пастку.
Воломійк

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ці два об'єкти будуть х кількість секунд один від одного. Часові пояси тут ні до чого.
dreamlax

@ Бенджамін: Чому ти це кажеш?
dreamlax

мрійник, ваша відповідь неправильна. Простий і простий. Обчисліть кількість днів між 12 полудня 1 січня за стандартним часом та 12 полудня 1 квітня, і ваша формула не працює. Це ледача формула, і розробники повинні використовувати об'єкт NSDateComponents для обчислення цього.
Рікстер

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 @""; 
}

цей метод є ідеальним способом обчислення різниці у часі.
Моксарт

просто ви можете тримати elseif з усіма тими, якщо є умови. інакше ви отримаєте лише один формат часу.
Моксарт

3

З Swift 5 та iOS 12, відповідно до ваших потреб, ви можете скористатися одним із двох наступних способів знайти різницю між двома датами в днях.


№1. Використання Calendarросійського 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російського 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)")

Швидкий 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)

Не всі дні мають таку кількість секунд.
Паван

@Pavan - Ви можете поділитися своїми даними, оновивши цю відповідь та покращивши її.
Крунал

Щоб зробити це краще, я зажадаю, щоб я переписав всю вашу відповідь, і в такому випадку він може бути видалений, оскільки це буде те саме рішення, що і відповідь, що не використовує твердо кодовані значення :)
Pavan,

0

Ви можете знайти різницю, перетворивши дату в секунди і взявши для цього інтервал часу з 1970 року, а потім ви зможете знайти різницю між двома датами.


коли дві дати можуть бути обчислені безпосередньо між собою (якщо вважати однакову часову область). Чи є якась конкретна причина обчислення спочатку обох дат з 1970 року, а потім виявлення різниці?
Адель

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
Будь ласка, не публікуйте код лише як відповідь, але також надайте пояснення, що робить ваш код і як він вирішує проблему. Відповіді з поясненням, як правило, вищої якості і, швидше за все, залучають репутацію.
Марк Ротвевель
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.