티스토리 뷰

반응형
SMALL

빙그레 바나나맛우유, 240ml, 8개

 

이번 포스트에서는 특정 월에 대하여 각 주 별로 월요일과 일요일에 해당하는 날짜를 리스트로 반환하는 방법에 대해 알아보고자 합니다.

예를 들어 2022년 4월의 경우, 

(2022.04.01 금, 2022.04.03 일)

(2022.04.04 월, 2022.04.10 일)

(2022.04.11 월, 2022.04.17 일)

(2022.04.18 월, 2022.04.24 일)

(2022.04.25 월, 2022.04.30 토)

와 같이 날짜 범위를 추출하고 싶을 경우가 있을텐데요 아래 코드로 구현이 가능합니다.

아래 코드는 Date에 대한 extension으로 구현한 함수입니다.

extension Date {
    // 여기에 아래 함수를 넣으시면 됩니다.
}

실제 기능을 구현하는 함수는 아래와 같습니다.

func weeklyDateList() -> [(Date, Date)] {
        var result: [(Date, Date)] = []
        
        let components = Calendar.current.dateComponents([.year, .month], from: self)
        if let startDayOfMonth = Calendar.current.date(from: components),
           let nextMonth = Calendar.current.date(byAdding: .month, value: +1, to: startDayOfMonth),
           let endOfMonth = Calendar.current.date(byAdding: .day, value: -1, to: nextMonth) {
            let startDayIndex = Calendar.current.component(.weekday, from: startDayOfMonth)
            let firstWeekStartDay = Date(timeInterval: -(Double(86400 * ((startDayIndex + 5) % 7))), since: startDayOfMonth)
            
            var weekStartDay: Date
            var weekEndDay: Date
            
            // MARK: Week 1
            if !(startDayOfMonth == firstWeekStartDay) {
                weekStartDay = startDayOfMonth
            } else {
                weekStartDay = firstWeekStartDay
            }
            
            weekEndDay = Calendar.current.date(byAdding: .day, value: 6 - (Calendar.current.component(.weekday, from: weekStartDay) + 5) % 7, to: weekStartDay)!
            result.append((weekStartDay, weekEndDay))
            
            var nextWeekStartDay: Date = firstWeekStartDay
            for _ in 0..<6 {
                nextWeekStartDay = Date(timeInterval: 86400 * 7, since: nextWeekStartDay)
                if nextWeekStartDay <= endOfMonth {
                    weekEndDay = Calendar.current.date(byAdding: .day, value: 6 - (Calendar.current.component(.weekday, from: nextWeekStartDay) + 5) % 7, to: nextWeekStartDay)!
                    if weekEndDay > endOfMonth {
                        weekEndDay = endOfMonth
                    }
                    result.append((nextWeekStartDay, weekEndDay))
                }
            }
        }
        return result
    }

 

먼저 구하고자 하는 특정 달에 대한 year, month를 추천하여 components 변수에 넣고 이 값을 이용하여 해당 달의 첫번째 날과 마지막 날을 계산합니다. (startDayOfMonth, endOfMonth)

let components = Calendar.current.dateComponents([.year, .month], from: self)
let startDayOfMonth = Calendar.current.date(from: components),
let nextMonth = Calendar.current.date(byAdding: .month, value: +1, to: startDayOfMonth),
let endOfMonth = Calendar.current.date(byAdding: .day, value: -1, to: nextMonth)

 

그리고 인덱스 값을 구하게 되는데 인덱스가 마지막 인덱스가 될 경우 주를 바꿔주기 위한 목적으로 사용합니다.

예를 들어 월요일 인덱스가 0이면 일요일은 6이 되는데 만약 1일부터 30일까지 Iteration을 돌면서 인덱스를 보는데 인덱스가 6이 되면 마지막 날짜라고 인지하고 해당 주의 시작날과 마지막날을 쌍으로 구성하여 리스트에 넣게 됩니다.

(즉, 2022년 4월의 경우 4월 1일과 4월 3일이 쌍으로 들어가게 됩니다.)

 

이렇게 인덱스가 0인 경우와 6인 경우의 날짜를 추출하게 되는데 첫 번째 주의 경우 1일이 월요일이 아닐 수 있기 때문에 이 경우를 처리할 필요가 있습니다. 아래 코드가 관련된 부분입니다.

// MARK: Week 1
if !(startDayOfMonth == firstWeekStartDay) {
    weekStartDay = startDayOfMonth
} else {
    weekStartDay = firstWeekStartDay
}

 

이렇게 계산하여 추출하면 올바른 (시작 요일 Date, 끝 요일 Date) 쌍의 리스트로 반환하게 됩니다.

 

읽어주셔서 감사합니다.

 

 

 

 

 

 

반응형
LIST
반응형
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/04   »
1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30
글 보관함