| Author |
Topic |
|
gispro
Starting Member
21 Posts |
Posted - 2006-01-18 : 05:04:41
|
| I have a question about calculation of week numbers from dates, generally and in MS/SQL 2000.E.g., what week numbers do January 1st, 2006 and 2005 belong to ?According to the Danish almanac, 1/1/06 belongs to week 52 in 2005, and 1/1/05 belongs to week 53 in 2004. And Danish weeks start on Monday, not Sunday.I'm unable to get the built-in function DATEPART(ww,..) to return this, regardless of how I set the DATEFIRST parameter. It seems MS/SQL only makes a simple division by 7 on the day-in-year, rounding the result up, always considering 1/1 to be in week number 1.Are week numbers caclulated differently in the US, or is something else amiss ? Are there any additional global settings that I need to set ?Or am I forced to build my own function using @@DATEFIRST etc. ??--GisPro |
|
|
TG
Master Smack Fu Yak Hacker
6065 Posts |
Posted - 2006-01-18 : 05:30:39
|
| Sql server's weeks are not really based on business rules. It is more like simply deviding a calendar year into 7 day units. @@Datefirst setting will just define the unit devisions. Any given date will not belong to a week in a different year. So a week that falls at the end and beginning of the year will usually be a "short" week. So you will probably need to either write your own logic or use a "custom" calendar table that includes a weeknumber column.Be One with the OptimizerTG |
 |
|
|
Michael Valentine Jones
Yak DBA Kernel (pronounced Colonel)
7020 Posts |
Posted - 2006-01-18 : 09:32:51
|
| It looks like the week number you are seeing is actually the ISO 8601 week of year. You can use Google to see the exact algorithim for this. Basically, the first week of a year starts with the first Monday on or before January 4th of each year, and can begin anywhere from Dec 29 of the prior year through Jan 4.CODO ERGO SUM |
 |
|
|
druer
Constraint Violating Yak Guru
314 Posts |
Posted - 2006-01-18 : 15:32:20
|
| Why do accountants get to make such complicated/silly rules? If you asked a first grader what January 1, 2006 was they would tell you that it was the first day of the year. It takes a college degree, MBA and passing a test for someone to be able to suggest that January 1, 2006 is in a week for 2005. :)I bought two cans of beans. (Leased 2 cans of beans I should never buy them right.) How would they respond if I said I asked them which can of beans does the first bean belong to that I pull out of the second can? Would they say you need to count how many beans were in the first can first to see if you were a bean short? Here is my thought process, some weeks (like Week 52 in 2005) may be a few days short. January 1, 2006 belongs to the year 2006 and can't be "borrowed" to make up for a short week in 2005. Those accountants have screwed up enough other things, please keep them away from my SQL Server. In SQL us "logical" minded folks get to make the rules. :) |
 |
|
|
Michael Valentine Jones
Yak DBA Kernel (pronounced Colonel)
7020 Posts |
Posted - 2006-01-18 : 15:51:09
|
quote: Originally posted by druerWhy do accountants get to make such complicated/silly rules?...
I don't know that you can blame accountants for this, but if you really want to know about this stuff, be my guest...http://www.iso.org/iso/en/prods-services/popstds/datesandtime.htmlhttp://en.wikipedia.org/wiki/ISO_8601CODO ERGO SUM |
 |
|
|
jsmith8858
Dr. Cross Join
7423 Posts |
Posted - 2006-01-18 : 15:51:28
|
quote: Originally posted by druer Why do accountants get to make such complicated/silly rules? If you asked a first grader what January 1, 2006 was they would tell you that it was the first day of the year. It takes a college degree, MBA and passing a test for someone to be able to suggest that January 1, 2006 is in a week for 2005. :)I bought two cans of beans. (Leased 2 cans of beans I should never buy them right.) How would they respond if I said I asked them which can of beans does the first bean belong to that I pull out of the second can? Would they say you need to count how many beans were in the first can first to see if you were a bean short? Here is my thought process, some weeks (like Week 52 in 2005) may be a few days short. January 1, 2006 belongs to the year 2006 and can't be "borrowed" to make up for a short week in 2005. Those accountants have screwed up enough other things, please keep them away from my SQL Server. In SQL us "logical" minded folks get to make the rules. :)
What does SQL Servers implementation of week number calculations have to do with accounting? |
 |
|
|
X002548
Not Just a Number
15586 Posts |
Posted - 2006-01-18 : 16:03:31
|
Actually, it looks like 1/1/05 belongs to week 52 of 2004.I would consider them weak numbersIt appears that Sundat in SQL Server starts the week, such that the first "week" in 2005 in SQL Server only had 1 daySELECT DATEPART(WW,'1/1/2005') , DATEPART(WW,'1/2/2005') , DATEPART(WW,'1/7/2005') , DATEPART(WW,'1/8/2005') , DATEPART(WW,'12/30/2005') , DATEPART(WW,'12/31/2005') Brett8-)Hint: Want your questions answered fast? Follow the direction in this linkhttp://weblogs.sqlteam.com/brettk/archive/2005/05/25/5276.aspxAdd yourself!http://www.frappr.com/sqlteam |
 |
|
|
Michael Valentine Jones
Yak DBA Kernel (pronounced Colonel)
7020 Posts |
Posted - 2006-01-18 : 16:34:42
|
quote: Originally posted by X002548Actually, it looks like 1/1/05 belongs to week 52 of 2004.
The ISO 8601 beginning of year for 2004 is the first Monday on or before 2004-1-4, which is 2003-12-29. The difference in days between 2003-12-29 and 2005-1-1 = 369. Dividing 369 by 7 gives you 52. Adding 1 to 52 = 53 to allow for starting the week number at 1 instead of zero. So 2005-1-1 is in week 53 of year 2004, just like gispro saw in his Danish almanac.CODO ERGO SUM |
 |
|
|
gispro
Starting Member
21 Posts |
Posted - 2006-01-18 : 16:51:05
|
| What day starts the week differs from country to country afaik, and SQL Server has the DATEFIRST to account for it. If you set DATEFIRST to 4 (= Thursday starts the week), DATEPART(dw,'some Friday') will return 2 as it should.In any case, I ended up building my own function. I've done it in php previously, so I had the quirks ironed out already. I did look at a few algorithms I found via Google as suggested by Michael, but they were too general and off-mark for my taste.Thanks for the help guys. I didn't even know that ISO-8601 existed :-)--GisPro |
 |
|
|
Michael Valentine Jones
Yak DBA Kernel (pronounced Colonel)
7020 Posts |
Posted - 2006-01-18 : 17:01:11
|
| If you are using the ISO standard, then the day that starts the week does not vary from country to country. It is always Monday.In the US, most people think of the week as starting on Sunday, but that can vary. It is very common to use the ISO week for manufacturing, since the work week starts on Monday also, and it gives each week a unique number that is the same world wide.CODO ERGO SUM |
 |
|
|
Michael Valentine Jones
Yak DBA Kernel (pronounced Colonel)
7020 Posts |
|
|
gispro
Starting Member
21 Posts |
Posted - 2006-01-19 : 08:34:16
|
| Very slick Michael, respect ! :-) Mine's way more clunky.My next task is a function that'll return the start of a week (as datetime) given as year + week number. Can you conjure up a similar slick function for that too ? ;-)It's for generating weekly reports with Reporting Services, btw, of time stamped data.--GisPro |
 |
|
|
jsmith8858
Dr. Cross Join
7423 Posts |
Posted - 2006-01-19 : 10:01:58
|
| I think that, by far, the easiest way to do this is to create a permanent table of Weeks in your database, covering a wide range of years (say, up to 2050 or something) and to put in there date ranges and anything else that you need. This will make your SQL statements more efficient by allowing the use of indexes, rather than using a UDF. In addition, you will be able to use this table to drive SELECT's that return 1 row per week or anything like that, in addition to quickly returning information such as the date range of week x of year y.The best thing about a table is that you can manually edit any percular rules that you need to enforce about how your weeks are calculated; you might use a UDF like Michaels to initially build it, but once it is there you can implement whatever business rules you need without worrying about writing the proper calculations for it. |
 |
|
|
Michael Valentine Jones
Yak DBA Kernel (pronounced Colonel)
7020 Posts |
Posted - 2006-01-19 : 10:34:05
|
You can turn this into a function:-- Script to find first day of week for an ISO year and weekdeclare @year intdeclare @week int-- Pick a year and weekselect @year = 2005select @week = 52select StartOfYearWeek = -- If it is in the year passed, -- return start of week, -- otherwise, return null. case when @week < 1 then null when dateadd(dd,(@week-1)*7,CurrYrStart) < NextYrStart then dateadd(dd,(@week-1)*7,CurrYrStart) else null endfrom(select -- First day of first week of current year CurrYrStart = dateadd(dd,(datediff(dd,-53690,aa.Jan4)/7)*7,-53690), -- First day of first week of next year NextYrStart = dateadd(dd,(datediff(dd,-53690,dateadd(yy,1,aa.Jan4))/7)*7,-53690)from(select --Find Jan 4 for input year Jan4 = case when @year between 1753 and 9998 then dateadd(dd,3,dateadd(yy,@year-1900,0)) -- Null if not in valid year range else null end) aa) a CODO ERGO SUM |
 |
|
|
Michael Valentine Jones
Yak DBA Kernel (pronounced Colonel)
7020 Posts |
Posted - 2006-01-19 : 10:38:41
|
quote: Originally posted by jsmith8858 I think that, by far, the easiest way to do this is to create a permanent table of Weeks in your database,...
I agree with that, although our table is for individual dates. I actually pulled the logic for the UDF from the stored procedure I use to load our table.CODO ERGO SUM |
 |
|
|
jsmith8858
Dr. Cross Join
7423 Posts |
Posted - 2006-01-19 : 10:44:26
|
quote: Originally posted by Michael Valentine Jones
quote: Originally posted by jsmith8858 I think that, by far, the easiest way to do this is to create a permanent table of Weeks in your database,...
I agree with that, although our table is for individual dates. I actually pulled the logic for the UDF from the stored procedure I use to load our table.CODO ERGO SUM
That's probably even better and more efficient; also, it will help you with SELECT's that need to return 1 row per day if those are required. |
 |
|
|
|