Я создаю приложение для создания привычек Swift. В определенный момент пользователь выбирает продолжительность (в днях) привычки, которую он хотел бы создать. Пользователь также может выбрать, какие дни недели он хотел бы практиковать (воскресенье, понедельник, вторник и т. Д.). Дата начала - день, когда они создают привычку.

В настоящее время у меня есть даты начала и окончания (в зависимости от количества дней, выбранных пользователем). Однако в этом диапазоне дат мне нужно извлечь даты для конкретных дней, выбранных пользователем.

Я думаю, что для каждого значения дня недели 'x' в пределах временного интервала (startDate, endDate), вернуть дату календаря. Тем не менее, я попытался создать DateInterval, и я не могу перебрать его, потому что он не соответствует протоколу «Sequence».

Есть ли эффективный способ перебора этого диапазона дат и извлечения этих других дат? Есть ли лучший способ, о котором я еще не думаю?

Вот мой текущий стартовый код даты ниже:

var date = Date()
var duration = 10
let calendar = Calendar.current

let dateEnding = Calendar.current.date(byAdding: .day, value: duration, to: date as Date)!

//Returns a number representing day of the week.  i.e. 1 = Sunday
let weekDay = calendar.component(.weekday, from: date)


//Initializing a time interval, based on user selected duration and start date
let timeInterval = DateInterval.init(start: date, end: dateEnding)

Спасибо за вашу помощь...

11
sharedev 21 Окт 2017 в 00:10

3 ответа

Лучший ответ

Если я правильно понимаю ваш вопрос, пользователь отметит некоторые дни недели и предоставит продолжительность в виде количества дней.

Предполагая, что у вас есть выбранные дни недели в массиве и продолжительность, вы можете получить список совпадающих дат следующим образом:

// User selected weekdays (1 = Sunday, 7 = Saturday)
var selectedWeekdays = [2, 4, 6] // Example - Mon, Wed, Fri
var duration = 10 // Example - 10 days

let calendar = Calendar.current
var today = Date()
let dateEnding = calendar.date(byAdding: .day, value: duration, to: today)!

var matchingDates = [Date]()
// Finding matching dates at midnight - adjust as needed
let components = DateComponents(hour: 0, minute: 0, second: 0) // midnight
calendar.enumerateDates(startingAfter: today, matching: components, matchingPolicy: .nextTime) { (date, strict, stop) in
    if let date = date {
        if date <= dateEnding {
            let weekDay = calendar.component(.weekday, from: date)
            print(date, weekDay)
            if selectedWeekdays.contains(weekDay) {
                matchingDates.append(date)
            }
        } else {
            stop = true
        }
    }
}

print("Matching dates = \(matchingDates)")
8
rmaddy 20 Окт 2017 в 23:04

Мы можем взять мощность протокола Strideable:

extension Date: Strideable {
    public func distance(to other: Date) -> TimeInterval {
        return other.timeIntervalSinceReferenceDate - self.timeIntervalSinceReferenceDate
    }

    public func advanced(by n: TimeInterval) -> Date {
        return self + n
    }
}

И тогда в вашем функционале:

// Iterate by 1 day
// Feel free to change this variable to iterate by week, month etc.
let dayDurationInSeconds: TimeInterval = 60*60*24
for date in stride(from: startDate, to: endDate, by: dayDurationInSeconds) {
    print(date)
}

Выход:

2018-07-19 12:18:07 +0000
2018-07-20 12:18:07 +0000
2018-07-21 12:18:07 +0000
2018-07-22 12:18:07 +0000
2018-07-23 12:18:07 +0000
....

Код взят из этого предложения

17
mesh 11 Июл 2019 в 15:39

Попробуй это

let calendar = NSCalendar.currentCalendar()
let startDate = ...
let endDate = ...
let dateRange = calendar.dateRange(startDate: startDate,
                                     endDate: endDate,
                                   stepUnits: .Day,
                                   stepValue: 1)

for date in dateRange {
    print("It's \(date)!")
}
4
Alexander Vitanov 20 Окт 2017 в 21:19