.net - Incorrect ISO8601 Week Number using DatePart() -
i have following sub within class. have no errors results not match iso-8601 standards
private sub calculateallproperties(byval dt date) select case dt.dayofweek case dayofweek.monday m_currentweekstartdate = dt case dayofweek.tuesday m_currentweekstartdate = dateadd(dateinterval.day, -1, dt) case dayofweek.wednesday m_currentweekstartdate = dateadd(dateinterval.day, -2, dt) case dayofweek.thursday m_currentweekstartdate = dateadd(dateinterval.day, -3, dt) case dayofweek.friday m_currentweekstartdate = dateadd(dateinterval.day, -4, dt) case dayofweek.saturday m_currentweekstartdate = dateadd(dateinterval.day, -5, dt) case dayofweek.sunday m_currentweekstartdate = dateadd(dateinterval.day, -6, dt) end select 'now have our start point of m_currentweekstartdate can calculate other properties. m_currentweekstartyear = datepart(dateinterval.year, m_currentweekstartdate) m_currentweekno = datepart(dateinterval.weekofyear, m_currentweekstartdate, microsoft.visualbasic.firstdayofweek.monday, firstweekofyear.firstfourdays) m_currentweeknoyear = currentweekno.tostring("d2") & "-" & currentweekstartyear.tostring m_currentyearweekno = currentweekstartyear.tostring & "-" & currentweekno.tostring("d2") m_previousweekstartdate = dateadd(dateinterval.day, -7, m_currentweekstartdate) m_previousweekstartyear = datepart(dateinterval.year, m_previousweekstartdate) m_previousweekno = datepart(dateinterval.weekofyear, m_previousweekstartdate, microsoft.visualbasic.firstdayofweek.monday, firstweekofyear.firstfourdays) m_previousweeknoyear = previousweekno.tostring("d2") & "-" & previousweekstartyear.tostring m_previousyearweekno = previousweekstartyear.tostring & "-" & previousweekno.tostring("d2") end sub
some example of values returned m_currentweeknoyear given date dt
- 20/07/2015 -> 30-2015 correct
- 09/03/2015 -> 11-2015 correct
- 29/12/2014 -> 53-2014 incorrect should 01-2015... using 02/01/2015 gave 53-2014
- 05/01/2015 -> 01-2015 incorrect should 02-2015... using 09/01/2015 gave 01-2015
- 30/12/2013 -> 53-2013 incorrect should 01-2014... using 04/01/2014 gave 53-2013
- 06/01/2014 -> 02-2014 correct
then when got year has 53 weeks works.
- 28/12/2009 -> 53-2009 correct
- 04/01/2010 -> 01-2010 correct
any ideas i've gone wrong?
using dateadd , datepart notoriously bad @ sort of thing, issue there (bug) inconsistency in way .net calculates week number.
see page more info iso 8601 week of year format in microsoft .net
"specifically iso 8601 has 7 day weeks. if first partial week of year doesn't contain thursday, counted last week of previous year. likewise, if last week of previous year doesn't contain thursday its[sic] treated first week of next year. getweekofyear() has first behavior, not second"
this code wrote iso 8601 week number based on definition:
"week number according iso-8601 standard, weeks starting on monday. first week of year week contains year's first thursday (='first 4-day week'). highest week number in year either 52 or 53."
''' <summary> ''' finds iso 8601 week number based on given date ''' </summary> ''' <param name="datevalue"></param> ''' <returns></returns> ''' <remarks>iso 8601 specifies monday first day of week , week 1 defined first 4 day week</remarks> public shared function getiso8601weekofyear(byval datevalue datetime) integer return getweekofyear(datevalue, dayofweek.sunday, calendarweekrule.firstfourdayweek) end function
it uses following more generic methods find week of year using specifics of iso standard:
'need calendar - culture's irrelevent since specify start day of week private shared cal calendar = cultureinfo.invariantculture.calendar ''' <summary> ''' returns week number of year based on last day of week , week 1 rule ''' </summary> ''' <param name="datevalue">the date find week number for</param> ''' <param name="lastdayofweek">the last day of week</param> ''' <param name="rule">the definition of week one</param> ''' <returns>an integer specifying week number in year</returns> ''' <remarks></remarks> public shared function getweekofyear(byval datevalue datetime, byval lastdayofweek dayofweek, byval rule calendarweekrule) integer 'there bug in .net framework dates @ end of year return incorrect week number find correct value need cheat. 'find dayofweek represents first day based on last day dim firstdayofweek dayofweek = lastdayofweek.increment 'find date of last day of week, ensures correct week number value datevalue = getweekendingdate(datevalue, lastdayofweek) 'return value of week last day of week return cal.getweekofyear(datevalue, rule, firstdayofweek) end function ''' <summary> ''' finds week ending date specified date value ''' </summary> ''' <param name="datevalue">the date find week ending date for</param> ''' <param name="lastdayofweek">the last day of week</param> ''' <returns>a date value last day of week contains specified datevalue</returns> ''' <remarks></remarks> public shared function getweekendingdate(byval datevalue datetime, byval lastdayofweek dayofweek) datetime 'find out how many days difference date testing end of week dim dayoffset integer = lastdayofweek - cal.getdayofweek(datevalue) if dayoffset < 0 dayoffset += 7 'add days test date last day of week return datevalue.adddays(dayoffset) end function
this code uses extension method quick lookup find next day of week:
<extension()> public function increment(byval aday dayofweek) dayofweek select case aday case dayofweek.sunday : return dayofweek.monday case dayofweek.monday : return dayofweek.tuesday case dayofweek.tuesday : return dayofweek.wednesday case dayofweek.wednesday : return dayofweek.thursday case dayofweek.thursday : return dayofweek.friday case dayofweek.friday : return dayofweek.saturday case dayofweek.saturday : return dayofweek.sunday case else : return nothing end select end function
i tried test cases , got following:
debug.writeline(getiso8601weekofyear(date.parse("20/07/2015"))) '30 debug.writeline(getiso8601weekofyear(date.parse("09/03/2015"))) '11 debug.writeline(getiso8601weekofyear(date.parse("29/12/2014"))) '1 debug.writeline(getiso8601weekofyear(date.parse("05/01/2015"))) '2 debug.writeline(getiso8601weekofyear(date.parse("30/12/2013"))) '1 debug.writeline(getiso8601weekofyear(date.parse("06/01/2014"))) '2
Comments
Post a Comment