View Single Post
  #4   Report Post  
Posted to microsoft.public.excel.programming
Myrna Larson Myrna Larson is offline
external usenet poster
 
Posts: 863
Default Excel dates seem to confuse me ...

Here's another test routine that compares the week number returned by VBA's
DatePart with my ISO number routine. I adjusted the latter to start the week
on Sunday rather than Monday.

I found 34 discrepancies in the period from Jan 4, 1900 through Jan 11, 2201.

For Sat Jan 1, 2101, VBA gave 53 and ISO 52; for Sat Jan 3, 2201, results were
54 [sic!] and 53. The other 32 instances all involved the last Sunday of the
calendar year; VBA's result was 53 and the ISO routine gave 1. One of them was
the Dec 30, 2007 date that you've already discovered.

Here's my lastest ISO routine and test code:

Option Explicit

Sub WEEKNOProblems()
Dim d As Date
Dim ErrCount As Long
Dim ErrList() As Double
Dim w1 As Long
Dim w2 As Long

Const Year1 As Long = 1900
Const YearN As Long = 2200

'maximum of 2 errors per year
ReDim ErrList(1 To (YearN - Year1 + 1) * 2 + 2, 1 To 3)

ErrCount = 0

For d = DateSerial(Year1, 1, 4) To DateSerial(YearN + 1, 1, 11)
w1 = DatePart("ww", d, vbSunday, vbFirstFourDays)
w2 = ISOWeekNum(d, vbSunday)
If w1 < w2 Then
ErrCount = ErrCount + 1
ErrList(ErrCount, 1) = CDbl(d)
ErrList(ErrCount, 2) = w1
ErrList(ErrCount, 3) = w2
End If
Next d

ActiveSheet.Columns(1).Resize(, 3).Clear
If ErrCount = 0 Then
MsgBox "No errors!", vbOKOnly
Else
With ActiveSheet
.Cells(1, 1).Resize(1, 3).Value = Array("Date", "VBA", "ISO")
With .Cells(2, 1).Resize(ErrCount, 3)
.Value2 = ErrList()
.NumberFormat = "0"
.Columns(1).NumberFormat = "mm/dd/yyyy"
End With
End With
End If
End Sub

Function ISOWeekNum(TheDate As Date, _
Optional StartDay As Long = vbMonday, _
Optional NumFormat As Long = 1) As Long

Dim y As Long
Dim YearStart As Date
Dim NextYearStart As Date
Dim n As Long

y = Year(TheDate)
YearStart = ISOYearStart(y, StartDay)
NextYearStart = ISOYearStart(y + 1, StartDay)
If TheDate = NextYearStart Then 'end of December
y = y + 1
YearStart = NextYearStart
ElseIf TheDate < YearStart Then 'early January
y = y - 1
YearStart = ISOYearStart(y, StartDay)
End If
n = (TheDate - YearStart) \ 7 + 1

Select Case NumFormat
Case 1: ISOWeekNum = n
Case 2: ISOWeekNum = (y Mod 100) * 100 + n
Case 3: ISOWeekNum = y * 100 + n
End Select
End Function

Private Function ISOYearStart(TheYear As Long, _
Optional StartDay As Long = vbMonday) As Date
Dim Jan4 As Date

Jan4 = DateSerial(TheYear, 1, 4)
ISOYearStart = Jan4 - Weekday(Jan4, StartDay) + 1

End Function