[РЕДАКТИРОВАТЬ] Я только что заметил, что последний ответ на эту тему также был сделан мной, говоря о том, чтобы заново изобрести колесо. Тем не менее, я думаю, что следующий класс является хорошей оболочкой для метода, описанного выше, поэтому я модифицировал его, чтобы включить в него метод вычисления, который я использовал.
Я не уверен насчет VSExpress, но в полном VB я бы просто расширил GregorianCalendar, чтобы добавить функциональность для получения года недели и упростить доступ к правильному номеру недели:
Public Class IsoWeekCalendar
Inherits Globalization.GregorianCalendar
'Get the ISO week number
Public Overloads Function GetWeekOfYear(d As DateTime) As Integer
Dim Week As Integer
'year is passed byref
GetYearAndWeek(d, Week:=Week)
Return Week
End Function
'Get the year that belongs with the week
Public Function GetWeekYear(d As DateTime) As Integer
Dim Year As Integer
'year is passed byref
GetYearAndWeek(d, Year:=Year)
Return Year
End Function
'Get both the week and year by ref
Public Sub GetYearAndWeek(d As DateTime, Optional ByRef Year As Integer = 0, Optional ByRef Week As Integer = 0)
Dim yearweek = GetYearAndWeek(d)
Year = yearweek.Item1
Week = yearweek.Item2
End Sub
'Get both the week and year
Public Function GetYearAndWeek(d As DateTime) As Tuple(Of Integer, Integer)
Dim year = Me.GetYear(d)
Dim dow = Me.GetDayOfWeek(d)
'Per MSDN, dow is 0 for sunday, per ISO, this should be 7
If (dow = 0) Then dow = 7
'usually, this calculation gives the week number
'http://en.wikipedia.org/wiki/ISO_week_date#Calculation
Dim week As Integer = Math.Floor((Me.GetDayOfYear(d) - dow + 10) / 7)
'If the week is 0 or 53, we should do some checks
If (week = 0) Then
'if we get week=0, the week is actually in last year
year -= 1
'A week has 53 weeks only if it starts on a thursday
'or is a leap year starting on a wednesday
Dim jan1st = New Date(year, 1, 1, Me)
If (jan1st.DayOfWeek = DayOfWeek.Thursday _
OrElse jan1st.DayOfWeek = DayOfWeek.Wednesday _
AndAlso Me.IsLeapYear(year)) Then
week = 53
Else
week = 52
End If
ElseIf (week = 53) Then
'determine if this week's thursday is in this year, if
'it's not, this week is also in the next year
Dim thursday = d.AddDays(4 - dow)
If (Me.GetYear(thursday) > year) Then
year += 1
week = 1
End If
End If
Return Tuple.Create(year, week)
End Function
'Get the date from the year, week and DoW, again, using calculation from
'http://en.wikipedia.org/wiki/ISO_week_date#Calculation
Public Function GetDate(year As Integer, week As Integer, Optional day As DayOfWeek = DayOfWeek.Monday) As DateTime
Dim ordinal = (week * 7) + IsoDayOfWeek(day) - (GetIsoDayOfWeek(New Date(year, 1, 4, Me)) + 3)
Return New Date(year, 1, 1, Me).AddDays(ordinal - 1)
End Function
'Get the previous date with the supplied DoW
Public Function GetPrev(d As DateTime, day As DayOfWeek) As DateTime
If (d.DayOfWeek <> day) Then
Return GetPrev(d.AddDays(-1), day)
End If
Return d
End Function
'Get the next date with the supplied DoW
Public Function GetNext(d As DateTime, day As DayOfWeek) As DateTime
If (d.DayOfWeek <> day) Then
Return GetPrev(d.AddDays(1), day)
End If
Return d
End Function
'Get the ISO day of week
Public Function GetIsoDayOfWeek(time As Date) As Integer
Return IsoDayOfWeek(MyBase.GetDayOfWeek(time))
End Function
'Translate .NET DoW to ISO DoW
Public Function IsoDayOfWeek(d As DayOfWeek) As Integer
If (d = DayOfWeek.Sunday) Then Return 7
Return d
End Function
Конец класса
person
Marten Jacobs
schedule
13.11.2014