--Code SQL 2.5
--Didier Maignan version 1.2
--Indiquer la date de début ci-dessous

DECLARE @DateDébut  date = '20100101';
--Indiquer le nombre d'année où s'arrêter dans NbreAnnée
DECLARE @NbreAnnée  int = '40';

-- Ne pas toucher ci dessous - La Date d'arrêt va se remplir toute seule
DECLARE @DateArrêt date = DATEADD(DAY, -1, DATEADD(YEAR, @NbreAnnée, @DateDébut));

--Indiquer la langue pour les noms de mois et de jour ici
SET LANGUAGE French

;WITH seq(n) AS 
(
  SELECT 0 UNION ALL SELECT n + 1 FROM seq
  WHERE n < DATEDIFF(DAY, @DateDébut, @DateArrêt)
),
d(d) AS 
(
  SELECT DATEADD(DAY, n, @DateDébut) FROM seq
),
src AS
(
  SELECT
    LaDate         = CONVERT(date, d),
    LeJour          = DATEPART(DAY,       d),
    LeNomDuJour      = DATENAME(WEEKDAY,   d),
    LaSemaine         = DATEPART(WEEK,      d),
    LaSemaineISO      = DATEPART(ISO_WEEK,  d),
    LeJourDeLaSemaine    = DATEPART(WEEKDAY,   d),
    LeMois        = DATEPART(MONTH,     d),
    LeNomDuMois    = DATENAME(MONTH,     d),
    LeTrimestre      = DATEPART(Quarter,   d),
    LAnnee         = DATEPART(YEAR,      d),
    LePremierDuMois = DATEFROMPARTS(YEAR(d), MONTH(d), 1),
    LeDernierJourDeLAnnnee   = DATEFROMPARTS(YEAR(d), 12, 31),
    LeJourdeLAnnee    = DATEPART(DAYOFYEAR, d)
  FROM d
),
dim AS
(
  SELECT
    LaDate, 
    LeJour,
    LeNomDuJour,
    LeJourDeLaSemaine,
    LeJourDeLaSemaineDuMois = CONVERT(tinyint, ROW_NUMBER() OVER 
                            (PARTITION BY LePremierDuMois, LeJourDeLaSemaine ORDER BY LaDate)),
    LeJourdeLAnnee,
    EstWeekend           = CASE WHEN LeJourDeLaSemaine IN (CASE @@DATEFIRST WHEN 1 THEN 6 WHEN 7 THEN 1 END,7) 
                            THEN 1 ELSE 0 END,
    LaSemaine,
    LaSemaineISO,
    LePremierDelaSemaine      = DATEADD(DAY, 1 - LeJourDeLaSemaine, LaDate),
    LeDernierDelaSemaine       = DATEADD(DAY, 6, DATEADD(DAY, 1 - LeJourDeLaSemaine, LaDate)),
    LaSemaineDuMois     = CONVERT(tinyint, DENSE_RANK() OVER 
                            (PARTITION BY LAnnee, LeMois ORDER BY LaSemaine)),
    LeMois,
    LeNomDuMois,
    LePremierDuMois,
    LeDernierDuMois      = MAX(LaDate) OVER (PARTITION BY LAnnee, LeMois),
    LePremierDuProchainMois = DATEADD(MONTH, 1, LePremierDuMois),
    LeDernierDuProchainMois  = DATEADD(DAY, -1, DATEADD(MONTH, 2, LePremierDuMois)),
    LeTrimestre,
    LePremierDuTrimestre   = MIN(LaDate) OVER (PARTITION BY LAnnee, LeTrimestre),
    LeDernierDuTrimestre    = MAX(LaDate) OVER (PARTITION BY LAnnee, LeTrimestre),
    LAnnee,
    LAnneeISO          = LAnnee - CASE WHEN LeMois = 1 AND LaSemaineISO > 51 THEN 1 
                            WHEN LeMois = 12 AND LaSemaineISO = 1  THEN -1 ELSE 0 END,      
    LePremierDeLAnnee      = DATEFROMPARTS(LAnnee, 1,  1),
    LeDernierJourDeLAnnnee,
    EstAnneeBisextile          = CONVERT(bit, CASE WHEN (LAnnee % 400 = 0) 
                            OR (LAnnee % 4 = 0 AND LAnnee % 100 <> 0) 
                            THEN 1 ELSE 0 END),
    A53Semaines          = CASE WHEN DATEPART(WEEK,     LeDernierJourDeLAnnnee) = 53 THEN 1 ELSE 0 END,
    A53SemainesISO       = CASE WHEN DATEPART(ISO_WEEK, LeDernierJourDeLAnnnee) = 53 THEN 1 ELSE 0 END,
    MMAAAA              = CONVERT(char(2), CONVERT(char(8), LaDate, 101))
                          + CONVERT(char(4), LAnnee),
    StyleUS            = CONVERT(char(10), LaDate, 1),
    StyleFrUk            = CONVERT(char(10), LaDate, 3),
    StyleGer            = CONVERT(char(8),  LaDate, 4)

  FROM src
)
SELECT * 
INTO Calendrier20102050
FROM dim
  ORDER BY LaDate
  OPTION (MAXRECURSION 0);
