什么是一个很好的执行IsLeapYear功能在VBA?

编辑: 我跑的如果-然后和DateSerial执行与迭代裹在一定时器,并DateSerial是更快,平均1-2毫(5运行300次迭代,有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的Excel网站上获得了这个功能。

Pearson的网站

其他提示

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

维基百科了解更多...... 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

我在 CodeToad 上发现了这个有趣的内容:

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

我看到许多伟大的概念表明了更多的理解 以及可以学习的日期函数的使用...... 在代码效率方面..  考虑执行函数所需的机器代码

而不是复杂的日期函数 只使用相当快的整数函数 BASIC建立在GOTO之上 我怀疑下面的东西更快

  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:的 数学 版本都有关 5倍


我看到两个团体的答案在这里

  1. 数学上的解释闰年的定义
  2. 利用Excel的日期/时间功能检测月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日之前的日期是一年,所以我们会将其定为2月28日或29日。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top