Jak mogę obliczyć różnicę między dwiema datami?

115

Jak mogę obliczyć liczbę dni między 1 stycznia 2010 r. A (na przykład) 3 lutego 2010 r.?

Frederik Heyninck
źródło

Odpowiedzi:

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

EDYTOWAĆ:

Pamiętaj, że NSDateobiekty reprezentują dokładne momenty czasu, nie mają żadnych skojarzonych informacji o strefie czasowej. Kiedy konwertujesz ciąg znaków na datę za pomocą np. An NSDateFormatter, NSDateFormatterkonwertuje czas ze skonfigurowanej strefy czasowej. W związku z tym liczba sekund między dwoma NSDateobiektami zawsze będzie niezależna od strefy czasowej.

Ponadto, dokumentacja ta określa, że ​​implementacja czasu Cocoa nie uwzględnia sekund przestępnych, więc jeśli potrzebujesz takiej dokładności, będziesz musiał rzucić własną implementację.

dreamlax
źródło
5
@RalucaGurau: 86400 to liczba sekund w ciągu dnia (tj. 60 sekund, razy 60 minut, razy 24 godziny). Nie ma to nic wspólnego z miesiącem.
dreamlax
18
Nie wszystkie dni mają 86400 sekund. Dla trywialnego przykładu to jest w porządku, ale w prawdziwym świecie nie jest to dobry pomysł. Zmiany czasu letniego, sekundy przestępne itp. Mogą z tym wszystkim zepsuć. NSCalendar może powiedzieć, ile sekund trwa dany dzień.
NeilInglis,
2
@muthukumar: Nie na iOS, metoda jest dostępna tylko w systemie Mac OS X. To pytanie jest oznaczone tagiem, cocoaa cocoa-touchwięc nie, więc ta odpowiedź dotyczy tylko Mac OS X.
dreamlax
1
Liczba dni pomiędzy dowolnymi dwoma momentami zawsze będzie wynosić 86400. To, czy ludzie są na etapie oszukiwania siebie, aby obudzić się godzinę wcześniej niż zwykle, czy nie, nie ma znaczenia dla faktu, że dzień ma 86400 sekund (ignorując skok sekund)
dreamlax
1
Chcę tylko dodać, że jeśli nie masz na końcu +0000, otrzymasz daty zerowe i wartość 0 zawsze na różnicy, bez względu na wszystko. Więc nie wpadnij w tę pułapkę.
Volomike
84

Możesz użyć czegoś takiego:

NSDateComponents *components;
NSInteger days;

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

Uważam, że ta metoda uwzględnia sytuacje, takie jak daty obejmujące zmianę czasu letniego.

Casey Fleser
źródło
2
czy istnieje prosty sposób na zignorowanie czasu dla podanych dat?
Mihai Timar
można odpowiednio zmienić na inne jednostki kalendarzowe :) używane w jednostce roku.
doświadczony technologicznie
NSDateobiekty są już niezależne od strefy czasowej. Informacje o strefie czasowej są usuwane podczas analizowania dat np. NSDateFormatter, Aby NSDateobiekty reprezentowały dokładne momenty w czasie. Dlatego jeśli już masz startDatei endDate, te dwa obiekty będą oddalone od siebie o x sekund. Strefy czasowe nie będą miały z tym nic wspólnego.
dreamlax
@Benjamin: Dlaczego tak mówisz?
dreamlax
dreamlax, twoja odpowiedź jest błędna. Jasne i proste. Oblicz liczbę dni między 12 w południe standardowego czasu 1 stycznia a 12 w południe 1 kwietnia czasu letniego, a Twoja formuła nie działa. Jest to leniwa formuła i programiści powinni użyć obiektu NSDateComponents do obliczenia tego.
Rickster
25
NSTimeInterval diff = [date2 timeIntervalSinceDate:date1]; // in seconds

gdzie date1i date2NSDate.

Zwróć również uwagę na definicję NSTimeInterval:

typedef double NSTimeInterval;
Chetan
źródło
Zauważ, że NSTimeInterval jest w rzeczywistości wartością podwójną, więc możesz jej używać jak każdej innej liczby.
Kendall Helmstetter Gelner
19

Sprawdź to. Dba o czas letni, rok przestępny, ponieważ do obliczeń używał kalendarza iOS.Możesz zmienić ciąg i warunki, aby zawierały minuty z godzinami i dniami.

+(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 @""; 
}
Ankish Jain
źródło
ta metoda jest doskonałym sposobem obliczenia różnicy czasu.
Moxarth
po prostu możesz zachować elseif z tymi wszystkimi warunkami. w przeciwnym razie zostanie wyświetlony tylko jeden format czasu.
Moxarth
3

Dzięki Swift 5 i iOS 12, w zależności od potrzeb, możesz użyć jednego z dwóch poniższych sposobów, aby znaleźć różnicę między dwiema datami w dniach.


# 1. Korzystanie Calendarz dateComponents(_:from:to:)metody

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. Korzystanie DateComponentsFormatterz string(from:to:)metody

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
źródło
1

Swift 4
Spróbuj tego i zobacz (zakres dat ze stringiem):

// 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)")

Szybki 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
źródło
Nie wszystkie dni mają taką ilość sekund.
Pavan
@Pavan - Zapraszamy do dzielenia się swoimi uwagami, aktualizując tę ​​odpowiedź i ulepszając ją.
Krunal
Żeby było lepiej, wymagałoby ode mnie przepisania całej twojej odpowiedzi, w takim przypadku równie dobrze może zostać usunięta, ponieważ będzie to to samo rozwiązanie, co odpowiedź powyżej, która nie używa wartości zakodowanych na stałe :)
Pavan
0

Możesz znaleźć różnicę, przeliczając datę w sekundach i biorąc dla tego przedział czasu od 1970 r., A następnie możesz znaleźć różnicę między dwiema datami.

Himanshu Bhatia
źródło
kiedy dwie daty można obliczyć bezpośrednio ze sobą (przy założeniu tej samej dziedziny czasu). Czy istnieje jakiś konkretny powód, aby najpierw obliczyć obie daty od 1970 roku, a następnie znaleźć różnicę?
Adeel
0

Aby znaleźć różnicę, musisz uzyskać aktualną datę i datę w przyszłości. W poniższym przypadku użyłem 2 dni jako przykład przyszłej daty. Obliczone przez:

2 days* 24 hours* 60 minutes* 60 seconds. Oczekujemy, że liczba sekund w ciągu 2 dni wyniesie 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
Roi Zakai
źródło
1
Nie wysyłaj tylko kodu jako odpowiedzi, ale także wyjaśnij, co robi twój kod i jak rozwiązuje problem pytania. Odpowiedzi z wyjaśnieniem są zwykle wyższej jakości i częściej przyciągają głosy za.
Mark Rotteveel