Как получить все воскресенья в массиве даты ios

мне просто нужен массив, который содержит все понедельники в году в форме NSDate, но быстро. Я использую следующий код в цели -c, но не знаю, как использовать его в Swift.

 NSDate *pickerDate = [NSDate date];
    NSLog(@"pickerDate: %@", pickerDate);

    NSDateComponents *dateComponents;
    NSCalendar *calendar = [NSCalendar currentCalendar];

    dateComponents = [calendar components:NSWeekdayCalendarUnit fromDate:pickerDate];
    NSInteger firstMondayOrdinal = 9 - [dateComponents weekday];
    dateComponents = [[NSDateComponents alloc] init];
    [dateComponents setDay:firstMondayOrdinal];
    NSDate *firstMondayDate = [calendar dateByAddingComponents:dateComponents toDate:pickerDate options:0];

    dateComponents = [[NSDateComponents alloc] init];
    [dateComponents setWeek:1];

    for (int i=0; i<64; i++) {
        [dateComponents setWeek:i];
        NSDate *mondayDate = [calendar dateByAddingComponents:dateComponents toDate:firstMondayDate options:0];
        NSLog(@"week#: %i, mondayDate: %@", i, mondayDate);
    }

person PAn Kaj Khatri    schedule 11.09.2015    source источник
comment
Есть ли определенная часть этого кода, которую вы не можете перевести?   -  person Shamas S    schedule 11.09.2015
comment
Да, я просто хочу преобразовать этот код, чтобы получить все воскресенья в одном массиве.   -  person PAn Kaj Khatri    schedule 11.09.2015


Ответы (5)


Xcode 8 или новее • Swift 3 или новее

extension Calendar {
    static let gregorian = Calendar(identifier: .gregorian)
}

extension Date {
    var startOfWeek: Date {
        return Calendar.gregorian.date(from: Calendar.gregorian.dateComponents([.yearForWeekOfYear, .weekOfYear], from: self))!
    }
    var addingOneWeek: Date {
        return Calendar.gregorian.date(byAdding: DateComponents(weekOfYear: 1), to: self)!
    }
    var nextSunday: Date {
        return startOfWeek.addingOneWeek
    }
    func nextFollowingSundays(_ limit: Int) -> [Date] {
        precondition(limit > 0)
        var sundays = [nextSunday]
        sundays.reserveCapacity(limit)
        return [nextSunday] + (0..<limit-1).compactMap { _ in
            guard let next = sundays.last?.addingOneWeek else { return nil }
            sundays.append(next)
            return next
        }
    }
}

Использование:

let today = Date()
let nextFollowingSundays = today.nextFollowingSundays(52)
nextFollowingSundays.forEach { sunday in
    print(sunday.description(with: .current), terminator: "\n")
}
// ["Feb 17, 2019 at 12:00 AM", "Feb 24, 2019 at 12:00 AM", "Mar 3, 2019 at 12:00 AM", "Mar 10, 2019 at 12:00 AM", "Mar 17, 2019 at 12:00 AM", "Mar 24, 2019 at 12:00 AM", "Mar 31, 2019 at 12:00 AM", "Apr 7, 2019 at 12:00 AM", "Apr 14, 2019 at 12:00 AM", "Apr 21, 2019 at 12:00 AM", "Apr 28, 2019 at 12:00 AM", "May 5, 2019 at 12:00 AM", "May 12, 2019 at 12:00 AM", "May 19, 2019 at 12:00 AM", "May 26, 2019 at 12:00 AM", "Jun 2, 2019 at 12:00 AM", "Jun 9, 2019 at 12:00 AM", "Jun 16, 2019 at 12:00 AM", "Jun 23, 2019 at 12:00 AM", "Jun 30, 2019 at 12:00 AM", "Jul 7, 2019 at 12:00 AM", "Jul 14, 2019 at 12:00 AM", "Jul 21, 2019 at 12:00 AM", "Jul 28, 2019 at 12:00 AM", "Aug 4, 2019 at 12:00 AM", "Aug 11, 2019 at 12:00 AM", "Aug 18, 2019 at 12:00 AM", "Aug 25, 2019 at 12:00 AM", "Sep 1, 2019 at 12:00 AM", "Sep 8, 2019 at 12:00 AM", "Sep 15, 2019 at 12:00 AM", "Sep 22, 2019 at 12:00 AM", "Sep 29, 2019 at 12:00 AM", "Oct 6, 2019 at 12:00 AM", "Oct 13, 2019 at 12:00 AM", "Oct 20, 2019 at 12:00 AM", "Oct 27, 2019 at 12:00 AM", "Nov 3, 2019 at 1:00 AM", "Nov 10, 2019 at 1:00 AM", "Nov 17, 2019 at 12:00 AM", "Nov 24, 2019 at 12:00 AM", "Dec 1, 2019 at 12:00 AM", "Dec 8, 2019 at 12:00 AM", "Dec 15, 2019 at 12:00 AM", "Dec 22, 2019 at 12:00 AM", "Dec 29, 2019 at 12:00 AM", "Jan 5, 2020 at 12:00 AM", "Jan 12, 2020 at 12:00 AM", "Jan 19, 2020 at 12:00 AM", "Jan 26, 2020 at 12:00 AM", "Feb 2, 2020 at 12:00 AM", "Feb 9, 2020 at 12:00 AM", "Feb 16, 2020 at 12:00 AM"]
person Leo Dabus    schedule 11.09.2015

Ну вот,

var pickerDate = NSDate()
println(pickerDate)

var dateComponents: NSDateComponents? = nil
var calendar = NSCalendar.currentCalendar()

dateComponents = calendar.components(NSCalendarUnit.CalendarUnitWeekday, fromDate: pickerDate)
var firstMondayOrdinal = 9 - dateComponents!.weekday
dateComponents =  NSDateComponents()
dateComponents!.day = firstMondayOrdinal
var firstMondayDate = calendar.dateByAddingComponents(dateComponents!, toDate: pickerDate, options: NSCalendarOptions(0))

dateComponents = NSDateComponents()
dateComponents?.weekdayOrdinal = 1

for (var i=0; i<64; i++){
    dateComponents?.weekdayOrdinal = i
    var mondayDate = calendar.dateByAddingComponents(dateComponents!, toDate: firstMondayDate!, options: NSCalendarOptions.MatchFirst)
     println("\(i)" + "\(mondayDate!)");
}
person Shamsudheen TK    schedule 11.09.2015
comment
тогда, пожалуйста, примите мой ответ :) (отметив галочку, которая отображается в верхней левой части предоставленного ответа) - person Shamsudheen TK; 11.09.2015

Есть недооцененный, но очень удобный метод enumerateDates(startingAfter:matching:matchingPolicy:) из Calendar

// Create the date component matching the weekday (Sunday = 1)
let mondayComponent = DateComponents(weekday: 2)

// Calculate Jan 1st of the current date
let calendar = Calendar.current
let currentDate = Date()
var startOfYear = currentDate
var interval : TimeInterval = 0.0
_ = calendar.dateInterval(of:.year, start: &startOfYear, interval: &interval, for: currentDate)

// Get the current year as integer
let thisYear = calendar.component(.year, from: startOfYear)

// Create an array for the result
var allMondays = [Date]()

// If Jan 1st is a Monday append it to the array
if calendar.component(.weekday, from: startOfYear) == 2 { allMondays.append(startOfYear) }

// Now enumerate all dates matching the weekday component within this year
// If the year reaches thisYear + 1 the block will be exited.    
calendar.enumerateDates(startingAfter: startOfYear, matching: mondayComponent, matchingPolicy: .nextTime) { (date, strict, stop) in
    guard let date = date else { return }
    if calendar.component(.year, from: date) > thisYear {
        stop = true
    } else {
        allMondays.append(date)
    }
}
person vadian    schedule 07.06.2017

Ну вот. Это довольно просто, но есть несколько ошибок, в частности, наборы параметров для NSCalendarOptions, тот факт, что dateByAddingComponents возвращает необязательный параметр, изменения в именах перечислений для NSCalendarUnit и устаревание NSDateComponents.week, но в остальном все просто. Логику не проверил...

//NSDate *pickerDate = [NSDate date];
let pickerDate = NSDate() /* I just used today for playground */

//NSLog(@"pickerDate: %@", pickerDate);
print("pickerDate: \(pickerDate)")

//NSDateComponents *dateComponents;
var dateComponents: NSDateComponents /* var because you keep reallocating it */

//NSCalendar *calendar = [NSCalendar currentCalendar];
let calendar = NSCalendar.currentCalendar()

//dateComponents = [calendar components:NSWeekdayCalendarUnit fromDate:pickerDate];
dateComponents = calendar.components(NSCalendarUnit.Weekday, fromDate: pickerDate)

//NSInteger firstMondayOrdinal = 9 - [dateComponents weekday];
let firstMondayOrdinal = 9 - dateComponents.weekday

//dateComponents = [[NSDateComponents alloc] init];
dateComponents = NSDateComponents()

//[dateComponents setDay:firstMondayOrdinal];
dateComponents.day = firstMondayOrdinal

//NSDate *firstMondayDate = [calendar dateByAddingComponents:dateComponents toDate:pickerDate options:0];
if let firstMondayDate = calendar.dateByAddingComponents(dateComponents, toDate: pickerDate, options: NSCalendarOptions(rawValue: 0)) {
    /* this returns an optional so test for it */

    //dateComponents = [[NSDateComponents alloc] init];
    dateComponents = NSDateComponents()

    //[dateComponents setWeek:1]; /* week deprecated */
    dateComponents.weekOfYear = 1 /* this line is redundant, re-done inside for */

    //for (int i=0; i<64; i++) {
    for i in 0 ..< 64 {
        //[dateComponents setWeek:i];
        dateComponents.weekOfYear = i
        //    NSDate *mondayDate = [calendar dateByAddingComponents:dateComponents toDate:firstMondayDate options:0];
        let mondayDate = calendar.dateByAddingComponents(dateComponents, toDate: firstMondayDate, options: NSCalendarOptions(rawValue: 0))
        /* no need to test for nil if just printing it, but beware */

        //NSLog(@"week#: %i, mondayDate: %@", i, mondayDate);
        print("week#: \(i), mondayDate: \(mondayDate)")
    }
}
person Grimxn    schedule 11.09.2015

Здесь я просто изменил приведенный выше код, чтобы получить разное количество воскресений

Вот расширение, чтобы получить следующее воскресенье от вашей даты

 extension Calendar {
            static let gregorian = Calendar(identifier: .gregorian)
        }

        extension Date {
            var startOfWeek: Date {
                return Calendar.gregorian.date(from: Calendar.gregorian.dateComponents([.yearForWeekOfYear, .weekOfYear], from: self))!
            }
            var nextSunday: Date {
                return Calendar.gregorian.date(byAdding: DateComponents(weekOfYear: 1), to: startOfWeek)!
            }
        }


//Write this logic in your custom function

 @objc func getNext100Sundsays(){
        let firstSunday = date?.nextSunday
        var result = [firstSunday]
        var displayResult = [String]()
        (1...1000).forEach  { _ in
            guard let nextSunday = result.last??.nextSunday else { return }
            let stringDispayDate = displayDateFormatter.string(from: nextSunday)
            result.append(nextSunday)
            displayResult.append(stringDispayDate)
        }
    }
person Sai kumar Reddy    schedule 23.08.2018