2017-02-10 6 views
0

КонтекстаSwift - получить следующую дату из массива будней

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

Импорт сроков погашения как Дата. Im сохранения рисунка повтора как Int32 (1 в воскресенье, 2 в понедельник, 4 во вторник ...), но я могу легко получить его в массив строк или чисел, представляющих каждый день

Проблема

Как я могу получить следующую дату в качестве даты (чтобы я мог повторить задачу)?

Пример

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

Фото картины повторения выбирают

Месяц никогда не выбирается при выборе других дней. Я знаю, как иметь дело с Месяцем. Проблема только с днями недели

+1

некоторый код будет полезным, мы не читать мысли ... –

ответ

2

Никогда не используйте 86400 для даты математики, Calendar и IndexSet имеют мощные методы, чтобы сделать это:

// Put your weekday indexes in an `IndexSet` 
let weekdaySet = IndexSet([1, 2, 4, 7]) // Sun, Mon, Wed and Sat 

// Get the current calendar and the weekday from today 
let calendar = Calendar.current 
var weekday = calendar.component(.weekday, from: Date()) 

// Calculate the next index 
if let nextWeekday = weekdaySet.integerGreaterThan(weekday) { 
    weekday = nextWeekday 
} else { 
    weekday = weekdaySet.first! 
} 

// Get the next day matching this weekday 
let components = DateComponents(weekday: weekday) 
calendar.nextDate(after: Date(), matching: components, matchingPolicy: .nextTime) 
1

Я надеюсь, что этот фрагмент может быть полезным

let SecondsPerDay: Int = (24 * 60 * 60) 

enum DayOfWeek: Int 
{ 
    case sunday = 1 
    case monday = 2 
    case tuesday = 3 
    case wendnesday = 4 
    case thrusday = 5 
    case friday = 6 
    case saturday = 7 

    /** 
     Convert a date to a enumeration member 
    */ 
    static func day(from date: Date) -> DayOfWeek 
    { 
     let formatter: DateFormatter = DateFormatter() 
     formatter.dateFormat = "e" 


     let day_number: Int = Int(formatter.string(from: date))! 

     return DayOfWeek(rawValue: day_number) 
    } 
} 


/** 
    Calculate the `TimeInterval` between days contained 
    in user preferences. 

    - Parameter days: Period selected by user 
    - Returns: Interval between dates days 
*/ 
func calculatePattern(withDays days: [DayOfWeek]) -> [TimeInterval] 
{ 
    var pattern: [TimeInterval] = [TimeInterval]() 

    for (index, day) in days.enumerated() 
    { 
     let distance: Int = (index == (days.count - 1)) ? (7 - (day.rawValue - days[0].rawValue)) : days[index + 1].rawValue - day.rawValue 

     let interval: TimeInterval = TimeInterval(SecondsPerDay * distance) 

     pattern.append(interval) 
    } 

    return pattern 
} 

func nextDay(from days: [DayOfWeek]) -> DayOfWeek 
{ 
    let today: DayOfWeek = DayOfWeek.day(from: Date()) 

    guard let days = days.filter({ $0.rawValue > today.rawValue }) else 
    { 
     return days.first! 
    } 

    return days.first! 
} 



let selectedDays: [DayOfWeek] = [ .monday, .wendnesday, .sunday, .saturday ] 

// Pass the array sorted by day in week 
let intervals: [TimeInterval] = calculatePattern(withDays: selectedDays.sorted(by: { $0.rawValue < $1.rawValue})) 

for interval in intervals 
{ 
    print(interval) 
} 

TimeInterval может быть преобразован в Date, используя один из классов Даты инициализаторов.

+0

Спасибо, вот полезно. Но как я могу сортировать Даты по тому, насколько они близки к текущей дате, чтобы я мог быстрее получить их? @Adolfo – toiavalle

+1

Добавлена ​​новая функция, которая вычисляет следующий день из массива DayOfWeek – Adolfo

0
func getdateArryFromWeekdays(_ date: Date, onWeekdaysForNotify weekdays:[Int]) -> [Date]{ 
    var correctedDate: [Date] = [Date]() 
    let now = Date() 
    let calendar = Calendar(identifier: Calendar.Identifier.gregorian) 
    let flags: NSCalendar.Unit = [NSCalendar.Unit.weekday, NSCalendar.Unit.weekdayOrdinal, NSCalendar.Unit.day] 
    let dateComponents = (calendar as NSCalendar).components(flags, from: date) 
    let weekday:Int = dateComponents.weekday! 

    //no repeat 
    if weekdays.isEmpty{ 
     //scheduling date is eariler than current date 
     if date < now { 
      //plus one day, otherwise the notification will be fired righton 
      correctedDate.append((calendar as NSCalendar).date(byAdding: NSCalendar.Unit.day, value: 1, to: date, options:.matchNextTime)!) 
     } 
     else { //later 
      correctedDate.append(date) 
     } 
     return correctedDate 
    } 
     //repeat 
    else { 
     let daysInWeek = 7 
     correctedDate.removeAll(keepingCapacity: true) 
     for wd in weekdays { 

      var wdDate: Date! 
      //schedule on next week 
      if compare(weekday: wd, with: weekday) == .before { 
       wdDate = (calendar as NSCalendar).date(byAdding: NSCalendar.Unit.day, value: wd+daysInWeek-weekday, to: date, options:.matchStrictly)! 
      } 
      else { //after 
       wdDate = (calendar as NSCalendar).date(byAdding: NSCalendar.Unit.day, value: wd-weekday, to: date, options:.matchStrictly)! 
      } 

      //fix second component to 0 
      wdDate = correctSecondComponent(date: wdDate, calendar: calendar) 
      correctedDate.append(wdDate) 
     } 
     return correctedDate 
    } 

} 
func correctSecondComponent(date: Date, calendar: Calendar = Calendar(identifier: Calendar.Identifier.gregorian))->Date { 
    let second = calendar.component(.second, from: date) 
    let d = (calendar as NSCalendar).date(byAdding: NSCalendar.Unit.second, value: -second, to: date, options:.matchStrictly)! 
    return d 
} 
enum weekdaysComparisonResult { 
    case before 
    case same 
    case after 
} 
Смежные вопросы