2012-03-10 17 views
5

Chcę utworzyć tablicę zakresów obejmującą dni między konkretną datą rozpoczęcia i zakończenia.Utwórz zakres dat

Na przykład mam datę rozpoczęcia od 1 stycznia 2012 r. Oraz datę końcową z 7 stycznia 2012 r. Tablica lub zakres powinien zawierać kolekcję obiektów NSDate (łącznie 7).

Jak to zrobić?

Odpowiedz

7

NSCalendar jest tu pomocne, ponieważ zna kalendarz związane z datami. Tak więc, używając następujących (zakładając, że masz startDate i endData i chcesz uwzględnić oba na liście), możesz wykonywać iteracje poprzez daty, dodając jeden dzień (NSCalendar zajmie się pakowaniem miesięcy i roku przestępnego itp.).

NSMutableArray *dateList = [NSMutableArray array]; 
NSCalendar *currentCalendar = [NSCalendar currentCalendar]; 
NSDateComponents *comps = [[NSDateComponents alloc] init]; 
[comps setDay:1]; 

[dateList addObject: startDate]; 
NSDate *currentDate = startDate; 
// add one the first time through, so that we can use NSOrderedAscending (prevents millisecond infinite loop) 
currentDate = [currentCalendar dateByAddingComponents:comps toDate:currentDate options:0]; 
while ([endDate compare: currentDate] != NSOrderedAscending) { 
    [dateList addObject: currentDate]; 
    currentDate = [currentCalendar dateByAddingComponents:comps toDate:currentDate options:0]; 
} 

[comps release];   
+0

Dzięki, myślę, że to jest to, czego szukałem. Jednak warunek w pętli while zwraca true. '(lldb) po endDate' ' (NSDate *) $ 6 = 0x06b9cc60 2012-03-11 00:12:42 + 0000' '(lldb) po currentDate' ' (NSDate *) $ 7 = 0x06b9dd20 2012- 03-11 00:12:42 + 0000' Jednak nadal zwracana jest wartość true. – joostevilghost

+0

Zgaduję, że uruchomiłeś to z startDate = [NSDate date] i endDate = [NSDate date], które powodują dwie daty, które nie są identyczne, ale są bardzo podobne (wyłączone o kilka milisekund). Zmodyfikowałem to tak, aby było bezpieczne dla tego warunku, chociaż jeśli używasz próbnika dat, prawdopodobnie nie będzie to problemem, ponieważ daty zostaną ustawione ręcznie na 00: 00: 00.0, a nie 00:12 : 42.xx i 00: 12: 42.yy – gaige

+0

Działa to świetnie, ale natrafiłem na problem, w którym brakowało mi daty zakończenia w listopadzie. Okazało się, że jest to czas letni. Dodaj to do swojej deklaracji NSCalendar, aby uniknąć, że '[currentCalendar setTimeZone: [NSTimeZone timeZoneWithAbbreviation: @" GMT "]]]; // ignoruj ​​letnie oszczędności' – smokingoyster

1

Wystarczy utworzyć je i dodać je do tablicy ...

NSMutableArray *arr = [NSMutableArray array]; 
NSDateComponents *comps = [[[NSDateComponents alloc] init] autorelease]; 
[comps setMonth:1]; 
[comps setYear:2012]; 

for(int i=1;i<=7;i++) { 
    [comps setDay:i]; 
    [arr addObject:[[NSCalendar currentCalendar] dateFromComponents:comps]]; 
} 
0

firmy Apple doc: Aby obliczyć sekwencję dat, użyj enumerateDatesStartingAfterDate: matchingComponents: Opcje: usingBlock: Metoda zamiast wywołanie tej metody ( - nextDateAfterDate: matchingComponents: opcje: ) w pętli z poprzedni wynik iteracji pętli.

Jak mam, będzie iteracyjne wszystkie daty dopasowane „matchingComponents” aż skończysz iteracji z „stop.memory = true”

let calendar = NSCalendar.currentCalendar() 
let startDate = calendar.startOfDayForDate(NSDate()) 
let finishDate = calendar.dateByAddingUnit(.Day, value: 10, toDate: startDate, options: []) 
let dayComponent = NSDateComponents() 
dayComponent.hour = 1 

calendar.enumerateDatesStartingAfterDate(startDate, matchingComponents: dayComponent, options: [.MatchStrictly]) { (date, exactMatch, stop) in 
    print(date) 
    if date!.compare(finishDate!) == NSComparisonResult.OrderedDescending { 
     // .memory gets at the value of an UnsafeMutablePointer 
     stop.memory = true 
    } 
} 
+0

Witaj w SO :) Proszę, nie ** po prostu ** zaksięguj blok kodu jako odpowiedź, ale daj też trochę wyjaśnienia, aby poprawić jakość twojej odpowiedzi. –

Powiązane problemy