2016-11-08 7 views
3

ISO-week-system (ISO8601)에 따라 신속하게 주어진 연도의 주 수를 계산하는 함수를 만들어야합니다. 숫자가 Int로 필요합니다. 먼저 NSDate를 12 월 31 일에 만들어야한다고 생각하고 그 다음 주가 (예 : 1214 년 12 월 31 일)에 12 월 31 일이 있음을 알게되었습니다. 아무도이 작업을 수행하는 방법을 알고 있습니다. ?주어진 ISO 8601 연도의 주 수를 얻으십시오.

내가

var calendarr = NSCalendar(calendarIdentifier: NSCalendar.Identifier.ISO8601)! 
var monday = "01-01-2005" 

var dateFormatter = DateFormatter() 
dateFormatter.dateFormat = "dd/MM/yyyy" 
var datumet = dateFormatter.date(from: monday) 
var weekRange = calendarr.range(of: .weekOfYear, in: .year, for: datumet!) 
var weeksCount = weekRange.length 

print("this many weeks", weeksCount) 

을 시도하지만 53주 저를 준다 상관없이 I 2004은 53 주했고 2005 52주

스위프트 3

답변

1

일년 ISO 달력 의 주 수를 결정하는 간단한 수식 Long and Short ISO Calendar Years에서 찾을 수있다 :

이소 연도 y를 (53주 포함) 길면 :
- P (Y) 모듈로 7 = 4
거나 같은 경우
- P (Y-1) 모듈로 7 = 3
:
- P (Y) = Y + 층 (Y/4) - 층 (Y/100) + 층 (y/400)

Wikipedia: Weeks per year의 버전이 인 경우 "p (year) = 5"인 경우 "p (year) = 4"이면 작은 오류가 발생합니다.

이 스위프트의 구현은 다음과 같습니다

func weeks(in year: Int) -> Int { 
    func p(_ year: Int) -> Int { 
     return (year + year/4 - year/100 + year/400) % 7 
    } 
    return (p(year) == 4 || p(year-1) == 3) ? 53 : 52 
} 

테스트 :

위키 백과 문서에서 주어진 목록과 일치
print(weeks(in: 2015)) // 53 
print(weeks(in: 2016)) // 52 

let longYears = (2000...2100).filter({ weeks(in: $0) == 53 }) 
print(longYears) 
// [2004, 2009, 2015, 2020, 2026, 2032, 2037, 2043, 2048, 2054, 2060, 2065, 2071, 2076, 2082, 2088, 2093, 2099] 

. 당신의 편집 다시


는 : 귀하의 시도 코드는 거의 정확합니다. @vadian으로 이 이미 댓글에서 말했다, 그것은 또한

let weekRange = calendarr.range(of: .weekOfYear, in: .yearForWeekOfYear, for: datumet!) 

년 1 월 1 일 (예를 들어 2016 년의 경우) 이전 ISO 년 에 빠질 수 있어야한다. 주어진 해에 1 월 4 일에서 12 월 28 일 사이의 어느 날을 선택하면 그 문제가 해결 될 것입니다. (Kevin Sabbe's approach 기준) 다음 방법을 제공 약간 더 단순화와

:

위의 함수로서 동일한 결과를 생성
func weeks(in year: Int) -> Int { 
    let cal = Calendar(identifier: .iso8601) 
    let date = DateComponents(calendar: cal, year: year, month: 2, day: 1).date! 
    let weeksRange = cal.range(of: .weekOfYear, in: .yearForWeekOfYear, for: date)! 
    return weeksRange.count 
} 

.

+1

그건 정말 훌륭합니다! 고맙습니다! –

2

일을했다 참고로 넣어 몇 년도 :.

let weekRange = NSCalendar.current.range(of: .weekOfYear, in: .yearForWeekOfYear, for: Date()) 

print("\(weekRange?.count)") 

연도를 Date()에 지정해야하며 전체 연도의 주 수를 지정해야합니다.

도움이 되었기를 바랍니다.

+0

* ISO-week-system *의 경우 'NSCalendar'의'ISO8601' 캘린더와'.yearForWeekOfYear' – vadian

+0

Vadian이 필요합니다. 제 질문에 추가 한 코드를보고 제게 보여주십시오. yearForWeekOfYear가 있어야합니다. weekRange-line의 "of :"슬롯과 "in :"슬롯에서 모두 시도했습니다. –

+0

@KlasZetterlund : 'in : .yearForWeekOfYear' 여야합니다. 또한 1 월 1 일을 이전 ISO 연도로 분류 할 수 있으므로 날짜로 선택하면 안됩니다. '01-02-yyyy'가 있으면 효과가 있습니다. –