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


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ę.


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.


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;

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

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

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)

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.


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

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
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.