Lua : vacances, jours chômés et jours fériés

reposFirefox

Indispensable dans une box domotique

Il est souvent utile de savoir si le jour courant est un jour passé à la maison, ou pas, pour planifier la programmation des luminaires ou du thermostat. Ce billet présente un ensemble de fonctions permettant de déterminer si le jour courant est un jours chômé (c’est à dire un jour où au moins un membre de la famille reste à la maison).

Jours chômés

La fonction principale pourrait se résumer à celle-ci :

function josdJourChome()
  local jour=josdGetJourSemaine()
  return jour=="samedi" or jour=="dimanche" or josdJourFerie() or josdJourVacances()
end

Un jour chômé est donc un samedi, un dimanche (à adapter selon votre situation) un jour férié ou un jour de vacances scolaires. Cette fonction fait appel à d’autres fonctions (josdGetJourSemaine(), josdJourFerie() ou josdJourVacances()) que nous détaillerons plus bas.

La fonction josdJourChome() risque d’être appelée souvent au cours de la journée. Or, elle retourne toujours la même valeur booléenne pour une journée donnée. J’ai donc décidé de l’optimiser pour ne pas charger la Vera de calculs inutiles :

-- Retourne true si le jour courant est un jour chômé (passé à la maison)
-- Le calcul effectif n'est fait qu'une fois par jour (ou si la Vera reboot)
josdJourChomeToday="NULL" -- Variable globale (date du dernier calcul) pour ne pas recalculer le résultat à chaque appel
josdJourChomeReturn=false -- Variable globale (résulat du dernier calcul) pour ne pas recalculer le résultat à chaque appel
function josdJourChome()
  local today=os.date("%Y-%m-%d")
  if(today~=josdJourChomeToday) then -- Faut-il refaire le calcul ?
    local jour=josdGetJourSemaine()
    josdJourChomeToday=today
    josdJourChomeReturn=(jour=="samedi" or jour=="dimanche" or josdJourFerie() or josdJourVacances())
  end
  return josdJourChomeReturn
end

Débarrassons-nous tous de suite de la fonction josdGetJourSemaine() qui est toute simple :

-- Retourne le jour de la semaine (lundi...dimanche)
josdGetJourSemaineTab={[0]="dimanche",[1]="lundi",[2]="mardi",[3]="mercredi",[4]="jeudi",[5]="vendredi",[6]="samedi"}
function josdGetJourSemaine()
  return josdGetJourSemaineTab[tonumber(os.date("%w"))]
end

Jours de vacances

Pour la fonction josdJourVacances(), je n’ai rien trouvé d’automatique. Chacun peut poser ses vacances quand il veut. De plus, les vacances scolaires varient en fonction des zones (A, B ou C), des années mais aussi des écoles (les vacances de l’Université ne sont pas les mêmes que celles du primaire par exemple). Bref, voici un modèle correspondant aux vacances scolaires de la zone C (Paris) en 2014 à adapter chaque année selon vos besoins particuliers :

-- Retourne true si le jour courant est un jour de vacances scolaires
function josdJourVacances()
  local today=os.date("%Y-%m-%d")
  local vacances=false
  -- 2013-2014
  if     ("2013-10-19"<=today and today<"2013-11-04") then vacances=true -- Toussaint
  elseif ("2013-12-21"<=today and today<"2014-01-06") then vacances=true -- Noël
  elseif ("2014-02-15"<=today and today<"2014-03-03") then vacances=true -- Hiver Zone C
  elseif ("2014-04-12"<=today and today<"2014-04-28") then vacances=true -- Printemps Zone C
  elseif ("2014-07-05"<=today and today<"2014-09-01") then vacances=true -- Vacances d'été
  -- 2014-2015
  elseif ("2014-10-18"<=today and today<"2014-11-03") then vacances=true -- Toussaint Zones
  elseif ("2014-12-20"<=today and today<"2015-01-05") then vacances=true -- Noël
  elseif ("2015-02-14"<=today and today<"2015-03-02") then vacances=true -- Hiver Zone C
  elseif ("2015-04-18"<=today and today<"2015-05-04") then vacances=true -- Printemps Zone C
  elseif ("2015-07-04"<=today and today<"2015-08-31") then vacances=true -- Vacances d'été
  -- 2015-2016
  elseif ("2015-10-17"<=today and today<"2015-11-02") then vacances=true -- Toussaint
  elseif ("2015-12-19"<=today and today<"2016-01-04") then vacances=true -- Noël
  elseif ("2016-02-20"<=today and today<"2016-03-07") then vacances=true -- Hiver Zone C
  elseif ("2016-04-23"<=today and today<"2016-05-09") then vacances=true -- Printemps Zone C
  elseif ("2016-07-02"<=today and today<"2016-09-01") then vacances=true -- Vacances d'été
  -- 2016-2017
  elseif ("2016-10-19"<=today and today<"2016-11-03") then vacances=true -- Toussaint
  elseif ("2016-12-17"<=today and today<"2017-01-03") then vacances=true -- Noël
  elseif ("2017-02-04"<=today and today<"2017-02-20") then vacances=true -- Hiver Zone C
  elseif ("2017-04-08"<=today and today<"2017-04-24") then vacances=true -- Printemps Zone C
  elseif ("2017-07-06"<=today and today<"2017-09-01") then vacances=true -- Vacances d'été
  end
  return vacances
end

Jours fériés

Là, c’est plus compliqué. Certains jours fériés ont une date fixe, mais d’autres sont calés sur la date de Pâques qui est complexe à déterminer. Voici une fonction qui calcule et retourne la date de Pâques au format epoch en fonction de l’année passée en paramètre. Cette fonction stocke le résultat du calcul pour pouvoir retourner immédiatement le résultat si elle est appelée une nouvelle fois avec la même année que l’appel précédent.

-- Retourne le jour de Pâques au format epoch
-- annee : année (Integer) dont on désire connaître le jour de Pâques (ex : 2014)
-- La fonction n'effectue le calcul que si l'année a changée depuis son dernier appel
josdGetJourPaquesAnnee=0      -- Variable globale (année du dernier calcul) pour ne pas recalculer le jour de Pâques à chaque appel
josdGetJourPaquesEpochPaque=0 -- Variable globale (jour de Pâques au format epoch) pour ne pas recalculer le jour de Pâques à chaque appel
function josdGetJourPaques(annee)
  if(josdGetJourPaquesAnnee~=annee or josdGetJourPaquesEpochPaque==0) then
    local a=math.floor(annee/100)
    local b=math.fmod(annee,100)
    local c=math.floor((3*(a+25))/4)
    local d=math.fmod((3*(a+25)),4)
    local e=math.floor((8*(a+11))/25)
    local f=math.fmod((5*a+b),19)
    local g=math.fmod((19*f+c-e),30)
    local h=math.floor((f+11*g)/319)
    local j=math.floor((60*(5-d)+b)/4)
    local k=math.fmod((60*(5-d)+b),4)
    local m=math.fmod((2*j-k-g+h),7)
    local n=math.floor((g-h+m+114)/31)
    local p=math.fmod((g-h+m+114),31)
    local jour=p+1
    local mois=n
    josdGetJourPaquesAnnee=annee
    josdGetJourPaquesEpochPaque=os.time{year=annee,month=mois,day=jour,hour=12,min=0}
  end
  return josdGetJourPaquesEpochPaque
end

Il est maintenant possible d’implémenter la fonction qui permet de déterminer si le jour courant est un jour férié.

-- Retourne true si le jour courant est un jour férié
-- Le calcul des jours férié n'est fait qu'un fois par an (ou si la Vera reboot)
josdJourFerieAnnee=0  -- Variable globale (année du dernier calcul) pour ne pas recalculer le tableau à chaque appel
josdJourFerieTab = {} -- Variable globale (tableau des jours fériés) pour ne pas recalculer le tableau à chaque appel
function josdJourFerie()
  local today=os.date("%m-%d")
  local annee=tonumber(os.date("%Y"))
  if(annee~=josdJourFerieAnnee) then
    josdJourFerieAnnee=annee
    -- Dates fixes
    josdJourFerieTab["01-01"] = true -- 1er janvier
    josdJourFerieTab["05-01"] = true -- Fête du travail
    josdJourFerieTab["05-08"] = true -- Victoire des alliés
    josdJourFerieTab["07-14"] = true -- Fête nationale
    josdJourFerieTab["08-15"] = true -- Assomption
    josdJourFerieTab["11-01"] = true -- Toussaint
    josdJourFerieTab["11-11"] = true -- Armistice
    josdJourFerieTab["12-25"] = true -- Noël
    -- Dates variables
    local epochPaques=josdGetJourPaques(annee)
    josdJourFerieTab[os.date("%m-%d",epochPaques)] = true             -- Pâques
    josdJourFerieTab[os.date("%m-%d",epochPaques+24*60*60)] = true    -- Lundi de Pâques = Pâques + 1 jour
    josdJourFerieTab[os.date("%m-%d",epochPaques+24*60*60*39)] = true -- Ascension = Pâques + 39 jours
    josdJourFerieTab[os.date("%m-%d",epochPaques+24*60*60*49)] = true -- Pentecôte = Ascension + 49 jours
  end
  return josdJourFerieTab[today] -- (nldr : Both nil and false make a condition false)
end

Produits

VeraLite

Informations et sources

Cette entrée a été publiée dans Domotique, Tutoriels and taguée . Placez un signet sur le permalien.

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *