Le calcul du numéro de semaine, TSQL
Par Arian Papillon le jeudi 19 janvier 2012, 18:41 - Lien permanent
Quelle prise en charge de notre mode de calcul à la norme ISO et comment obtenir le bon numéro de semaine à partir d'une date avec TSQL ?
Selon la norme ISO-8601 appliquée en France et adoptée par la plupart des pays européens, la semaine 1 est la première série de 4 jours dans l'année (la semaine commençant le lundi) :
- c’est donc celle qui contient le premier jeudi de l’année et le 4 janvier
- si le jour de l’an arrive après le jeudi, il se situe donc dans la dernière semaine de l’année précédente
- le nombre de semaines de l’année peut être 52 ou 53 - une semaine n’est affectée qu’à une seule année
- cette année 2012, le premier janvier tombant un dimanche faisait donc partie de la semaine 52 de l’an dernier, et la semaine 1 commence le 2 janvier...
Aux US, la semaine commence le dimanche et la semaine 1 est celle contenant le 1er janvier (et aussi le premier samedi de l’année).
- Une semaine peut donc être affectée deux fois, à la nouvelle année et à l’année précédente
- Cette année 2012, le premier janvier tombant un dimanche était donc le premier jour de la semaine 1 ...
D’autres modes de calcul peuvent exister ailleurs, comme par exemple :
- Un jour de début de semaine différent (le samedi), ou bien la semaine 1 est la première semaine entière de l’année
TSQL
En ce qui nous concerne pour calculer nos numéros de semaine ISO-8601, SQL Server 2008 offre l'option utile ISO_WEEK avec la fonction DATEPART :
- SELECT DATEPART (ISO_WEEK, ‘20120101’) renvoie 52
- SELECT DATEPART(ww,’20120101’) renvoie 1
Mais si vous n’êtes pas passé à SQL Server 2008, il faut faire le calcul. Chacun sa méthode, voici la mienne :
CREATE FUNCTION dbo.iso_week ( @thedate DATETIME )
RETURNS INT
AS BEGIN
DECLARE @weeknumber INT
-- cas général
SET @weeknumber = DATEPART(ww, @thedate) -
CASE WHEN
DATEPART(dw,
DATEADD(dd,
-( DATEPART(dy, @thedate) -
1 ), @thedate)) > 4
THEN 1
ELSE 0
END
-- cas des premiers jours de l'année
IF @weeknumber = 0
SET @weeknumber = dbo.iso_week(DATEADD(dd, -1,
@thedate))
-- cas des derniers jours appartenant à l'année
suivante
RETURN CASE WHEN DATEPART(mm, @thedate) = 12 AND
DATEPART(dd, @thedate) - DATEPART(dw, @thedate) >= 28
THEN 1
ELSE @weeknumber
END
END
GO
A voir, cette autre méthode plus élégante que la mienne sur ce blog.
Commentaires
Salut Arian!
Tu pourrais pas nous faire aussi le script pour l'année ISO?
Parce que si la semaine 1-2012 devient la semaine 53, il ne faut pas oublier de changer également l'année, sinon on bascule sur la semaine 53-2012 qui n'est pas vraiment la même :)
En tout cas merci pour l'info!
Un fait intéressant (particulièrement pour les années ou le 1 janvier est un dimanche). Remarquer que la semaine 1 (US) ne comporte que le dimanche, car toute autre jour de semaine tombe dans l'année précédente. Chercher la date du lundi de la semaine 1 n'est pas en 2012, le premier lundi est obligatoirement dans la semaine 2.
Pour la semaine ISO on ne peu avoir plus de 3 jours manquant dans la semaine 1, soit Lu - Ma - Me. Et il ne manque pas puisque le calcul retournera un numéro de semaine de l'an précédent.
Par contre en ISO, les premiers jours de l'an courant peuvent se retrouver dans l'an précédent, chose qui ne peu arriver avec le calendrier US. (Mais vous l'aurez compris tout se calcule, il s'agit d'avoir le bon algorithme).
Le plaisir des calendriers...