VBA에서 Leapeear를 어떻게 찾습니까?
-
02-07-2019 - |
문제
VBA에서 ISLEAPYEAR 기능의 좋은 구현은 무엇입니까?
편집하다: 나는 타이머에 반복이 감겨있는 IF-THEN과 데이트 레알 구현을 실행했으며, 날짜는 평균적으로 1-2ms (300 회 반복의 5 개 실행, 1 개의 평균 셀 워크 시트 공식도 작동 함)를 평균적으로 더 빠르게 수행했습니다.
해결책
Public Function isLeapYear(Yr As Integer) As Boolean
' returns FALSE if not Leap Year, TRUE if Leap Year
isLeapYear = (Month(DateSerial(Yr, 2, 29)) = 2)
End Function
나는 원래 Chip Pearson의 Great Excel 사이트 에서이 기능을 얻었습니다.
다른 팁
public function isLeapYear (yr as integer) as boolean
isLeapYear = false
if (mod(yr,400)) = 0 then isLeapYear = true
elseif (mod(yr,100)) = 0 then isLeapYear = false
elseif (mod(yr,4)) = 0 then isLeapYear = true
end function
더 많은 Wikipedia ...http://en.wikipedia.org/wiki/leap_year
효율성이 고려 사항이고 예상 연도가 무작위 인 경우 가장 먼저 가장 빈번한 사례를 수행하는 것이 약간 더 나을 수 있습니다.
public function isLeapYear (yr as integer) as boolean
if (mod(yr,4)) <> 0 then isLeapYear = false
elseif (mod(yr,400)) = 0 then isLeapYear = true
elseif (mod(yr,100)) = 0 then isLeapYear = false
else isLeapYear = true
end function
Chip Pearson 솔루션의 변형으로 시도 할 수도 있습니다.
Public Function isLeapYear(Yr As Integer) As Boolean
' returns FALSE if not Leap Year, TRUE if Leap Year
isLeapYear = (DAY(DateSerial(Yr, 3, 0)) = 29)
End Function
나는이 재미있는 것을 발견했다 코드로드 :
Public Function IsLeapYear(Year As Varient) As Boolean
IsLeapYear = IsDate("29-Feb-" & Year)
End Function
하지만 기능에서 ISDATE를 사용하는 것이 아마도 몇 가지 if, elseifs보다 느리게 느려질 것이라고 확신합니다.
Public Function ISLeapYear(Y As Integer) AS Boolean
' Uses a 2 or 4 digit year
'To determine whether a year is a leap year, follow these steps:
'1 If the year is evenly divisible by 4, go to step 2. Otherwise, go to step 5.
'2 If the year is evenly divisible by 100, go to step 3. Otherwise, go to step 4.
'3 If the year is evenly divisible by 400, go to step 4. Otherwise, go to step 5.
'4 The year is a leap year (it has 366 days).
'5 The year is not a leap year (it has 365 days).
If Y Mod 4 = 0 Then ' This is Step 1 either goto step 2 else step 5
If Y Mod 100 = 0 Then ' This is Step 2 either goto step 3 else step 4
If Y Mod 400 = 0 Then ' This is Step 3 either goto step 4 else step 5
ISLeapYear = True ' This is Step 4 from step 3
Exit Function
Else: ISLeapYear = False ' This is Step 5 from step 3
Exit Function
End If
Else: ISLeapYear = True ' This is Step 4 from Step 2
Exit Function
End If
Else: ISLeapYear = False ' This is Step 5 from Step 1
End If
End Function
Public Function isLeapYear(Optional intYear As Variant) As Boolean
If IsMissing(intYear) Then
intYear = Year(Date)
End If
If intYear Mod 400 = 0 Then
isLeapYear = True
ElseIf intYear Mod 4 = 0 And intYear Mod 100 <> 0 Then
isLeapYear = True
End If
End Function
코드 효율성 측면에서 배울 수있는 데이트 기능의 추가 이해와 사용법을 나타내는 많은 훌륭한 개념을 봅니다. 기능이 실행하는 데 필요한 기계 코드를 고려하십시오.
복잡한 날짜 기능보다는 상당히 빠른 정수 기능 만 사용하는 대신 기본적으로 기본적으로 구축되었습니다.
Function IsYLeapYear(Y%) As Boolean
If Y Mod 4 <> 0 Then GoTo NoLY ' get rid of 75% of them
If Y Mod 400 <> 0 And Y Mod 100 = 0 Then GoTo NoLY
IsYLeapYear = True
Noly :
End Function
성능 질문을 해결하기위한 늦은 답변.
tl/dr : the 수학 버전이 있습니다 더 빨리 5 배 더
여기서 두 그룹의 답변이 보입니다
- 도약 연도 정의의 수학적 해석
- Excel 날짜/시간 기능을 활용하여 2 월 29 일을 감지합니다 (이것은 두 개의 캠프에 속합니다 : 날짜를 끈으로 구축하는 것과 그렇지 않은 것들)
나는 모든 게시 된 답변에서 시간 테스트를 실행했다. 수학 방법이 있습니다 더 빨리 5 배 더 날짜/시간 방법보다.
그런 다음 방법을 최적화하고 생각해 냈습니다 (믿거 나 말거나 Integer
미미한 것보다 더 빠릅니다 Long
이 경우 이유를 모릅니다.)
Function IsLeapYear1(Y As Integer) As Boolean
If Y Mod 4 Then Exit Function
If Y Mod 100 Then
ElseIf Y Mod 400 Then Exit Function
End If
IsLeapYear1 = True
End Function
비교를 위해, 나는 올라 갔다 (게시 된 버전과는 거의 차이가 없다)
Public Function IsLeapYear2(yr As Integer) As Boolean
IsLeapYear2 = Month(DateSerial(yr, 2, 29)) = 2
End Function
문자열로 날짜를 빌드하는 날짜/시간 버전은 다시 속도가 느리기 때문에 할인되었습니다.
테스트는 얻는 것이 었습니다 IsLeapYear
100..9999 년 동안 1000 번 반복했습니다
결과
- 수학 버전 : 640ms
- 날짜/시간 버전 : 3360ms
테스트 코드였습니다
Sub Test()
Dim n As Long, i As Integer, j As Long
Dim d As Long
Dim t1 As Single, t2 As Single
Dim b As Boolean
n = 1000
Debug.Print "============================="
t1 = Timer()
For j = 1 To n
For i = 100 To 9999
b = IsYLeapYear1(i)
Next i, j
t2 = Timer()
Debug.Print 1, (t2 - t1) * 1000
t1 = Timer()
For j = 1 To n
For i = 100 To 9999
b = IsLeapYear2(i)
Next i, j
t2 = Timer()
Debug.Print 2, (t2 - t1) * 1000
End Sub
또 다른 간단한 옵션이 있습니다.
Leap_Day_Check = Day(DateValue("01/03/" & Required_Year) - 1)
leap_day_check = 28 인 경우 29 세가되는 경우 도약이 아닙니다.
VBA는 3 월 1 일 이전의 날짜가 1 년에 무엇인지 알고 있으며 2 월 28 일 또는 29 일로 설정 될 것입니다.