1

I need to get all the dates of a week for the current month only when I pressed a specific date. For example, if I pressed Sept 28, the result will be Sept 23-28 dates but if I pressed Sept 30, the result will be Sept 30 ONLY because the dates after that are for October.

This is my code to get the dates of a week:

extension Date {
    var startOfWeek: Date? {
        let gregorian = Calendar(identifier: .gregorian)
        guard let sunday = gregorian.date(from: gregorian.dateComponents([.yearForWeekOfYear, .weekOfYear], from: self)) else { return nil }
        return gregorian.date(byAdding: .day, value: 0, to: sunday)
    }

    var endOfWeek: Date? {
        let gregorian = Calendar(identifier: .gregorian)
        guard let sunday = gregorian.date(from: gregorian.dateComponents([.yearForWeekOfYear, .weekOfYear], from: self)) else { return nil }
        return gregorian.date(byAdding: .day, value: 6, to: sunday)
    }
}

But for this code the result is Sept 30 - Oct 6 which is not what I want. Pls help

jay123456
  • 131
  • 1
  • 1
  • 10
  • Keep in mind that your logic also needs to deal with different starting days of the week in different locales. For locales that start the week on a Monday, the dates you want for September 30, 2018 would be Sept 24-30. – rmaddy Sep 28 '18 at 02:37
  • Thanks for the reminder but this will have a fixed locale. – jay123456 Sep 28 '18 at 02:48

3 Answers3

0

You could get the last day of the month, and then endOfWeek would be the minimum between what you already have and the end of the month.

var endOfWeek: Date? {
    let gregorian = Calendar(identifier: .gregorian)
    guard let sunday = gregorian.date(from: gregorian.dateComponents([.yearForWeekOfYear, .weekOfYear], from: self)) else { return nil }
    let endOfWeek = gregorian.date(byAdding: .day, value: 6, to: sunday)
    let firstOfNextMonth = gregorian.date(byAdding: .month, value: 1, to: sunday)
    let lastOfThisMonth = gregorian.date(byAdding: .day: value: -1, to: firstOfNextMonth)

    return min(endOfWeek, lastOfThisMonth)
}

I can't guarantee that that code will compile but it should give you an idea of how to accomplish what you want.

EmilioPelaez
  • 18,758
  • 6
  • 46
  • 50
0

I would like to recommend SwiftMoment as it's a Swift port of Moment.js.

Moment.js is a rich library that has great documentation and super useful functions for this purpose.

Given a date, you can get the start of week Date, and end of week Date.

Then from there, you can enumerate the dates in between.

I'm currently using Moment.js in my web app project with this function to get the week dates given a date:

getWeekDates (dateReference, format) {
    const startOfWeek = moment(dateReference).startOf('isoWeek');
    const endOfWeek = moment(dateReference).endOf('isoWeek');

    var days = [];
    var day = startOfWeek;

    while (day <= endOfWeek) {
        if (format !== undefined) {
          days.push(day.format(format));
        } else {
          days.push(day);
        }
        day = day.clone().add(1, 'd');
    }

    return days;
  }
remingtonchan
  • 479
  • 4
  • 11
0

You could intersect the intervals for the week and month containing the date.

Here's a quick test:

let calendar = Calendar(identifier: .gregorian)
let date = DateComponents(calendar: calendar, year: 2018, month: 9, day: 30).date!

let weekComponents = calendar.dateComponents([.yearForWeekOfYear, .weekOfYear], from: date)
let startOfWeek = calendar.date(from: weekComponents)!
let endOfWeek = calendar.date(byAdding: .weekOfYear, value: 1, to: startOfWeek)!
let weekInterval = DateInterval(start: startOfWeek, end: endOfWeek)

let monthComponents = calendar.dateComponents([.year, .month], from: date)
let startOfMonth = calendar.date(from: monthComponents)!
let endOfMonth = calendar.date(byAdding: .month, value: 1, to: startOfMonth)!
let monthInterval = DateInterval(start: startOfMonth, end: endOfMonth)

let targetRange = monthInterval.intersection(with: weekInterval)!
let firstDay = targetRange.start
let lastDay = calendar.date(byAdding: .day, value: -1, to: targetRange.end)

You'll want to refactor to avoid force unwrapping all the dates.

Ken Boreham
  • 904
  • 6
  • 16