Join Now

Juletip #13: Beregn helligdage og opdater din Outlook kalender

by SAS Employee OleSteen on ‎12-12-2014 09:09 PM (573 Views)

Så blev det weekend igen, og jeg fik lige lyst til at dele endnu et weekend-juletip Smiley Happy

Julen falder jo som bekendt altid den 24. december - og varer lige til påske er der en sang der påstår.

Men hvornår er det lige påsken falder?

Påskedag falder altid på den første søndag efter første fuldmåne efter forårsjævndøgn!

Forårsjævndøgnet - dagen, hvor nat og dag har samme længde - er altid den 21. marts. Påsken kan derfor kun falde i perioden fra 22. marts til 25. april.

Påskedag kan for 2015 beregnes i SAS med følgende datastep:

DATA Paaske;

  Aar = 2015;

  format Paaske ddmmyyp10.;

  a = mod(aar,19);

  b = int(aar/100);

  c = mod(aar,100);

  d = int(b/4);

  e = mod(b,4);

  f = int((b+8)/25);

  g = int((b-f+1)/3);

  h = mod((19*a+b-d-g+15),30);

  i = int(c/4);

  k = mod(c,4);

  l = mod((32+2*e+2*i-h-k),7);

  m = int((a+11*h+22*l)/451);

  n = int((h+l-7*m+114)/31);

  p = mod((h+l-7*m+114),31);

  paaske = mdy(n,p+1,aar);

RUN;

En beregning jeg for mange år siden fandt frem til ved at studere månen :smileymischief:

Jeg synes faktisk det er imponerende, og jeg blev da også lidt skuffet da jeg for et stykke tid siden, fandt ud af, at udviklerne hos SAS i Cary har udviklet en HOLIDAY-funktion, så min imponerende beregning kan klares med:

DATA Paaske;

   Aar = 2015;

   format Paaske ddmmyyp10.;

   paaske = holiday('easter',aar);

RUN;

Når jeg altså, mere eller mindre imponerende kan beregne påskedag, kan jeg forholdsvis let også beregne de øvrige helligdage som ikke falder på en lørdag eller søndag:

DATA Helligdage (keep = Dato Helligdag);

  aar = 2015;

  format Dato ddmmyyp10. Helligdag $25.;

  paaske = holiday('easter',aar);

  dato=mdy(06,05,aar);
  Helligdag =
'Grundlovsdag';   

  if weekday(dato) not in (1,7) thenoutput;

  dato=mdy(12,24,aar);

  Helligdag = 'Juleaftensdag';

  if weekday(dato) not in (1,7) then output;

  dato=mdy(12,25,aar);

  Helligdag = 'Juledag';

  if weekday(dato) not in (1,7) then output;

  dato=mdy(12,26,aar);

  Helligdag = '2.Juledag';

  if weekday(dato) not in (1,7) then output;

  dato=mdy(01,01,aar);

  Helligdag = 'Nytårsdag';

  if weekday(dato) not in (1,7) then output;

  dato=paaske-3;

  Helligdag = 'Skærtorsdag';

  output;

  dato=paaske-2;

  Helligdag = 'Langfredag';

  output;

  dato=paaske+1;

  Helligdag = '2. Påskedag';

  output;

  dato=paaske+26;

  Helligdag = 'Store bededag';

  output;

  dato=paaske+39;

  Helligdag = 'Kr. himmelfart';

  output;

  /* Denne dato er ikke en helligdag for alle !!! */

  /* dato=paaske+40;          Helligdag = 'Dag efter Kr. himmelfart'; */

  /*  output; */

  dato=paaske+50;

  Helligdag = '2. Pinsedag';

  output;

RUN;

I Outlook er det muligt at importere helligdage til kalenderen fra calender-options:

Vælger du denne option vil Outlook søge efter en fil i installationsfolderen med navnet OUTLOOK.HOL

Standardindholdet i denne fil kan du overskrive (kopier evt. først ) og dermed selv bestemme hvilke dage du vil markere i kalenderen som helligdage.

På min maksine ligger OUTLOOK.HOL i folderen C:\Program Files (x86)\Microsoft Office\Office15\1033 og med et lille SAS-program kan jeg nu bruge ovenstående kode til at ajourføre filen.

/* Find antal rækker i tabellen helligdage */

%let dsid = %sysfunc(open(Helligdage));

%let Antal = %sysfunc(attrn(&dsid,NOBS));

%let dsid = %sysfunc(close(&dsid));

/* Overskriv standard-filen med helligdage */

data _null_;

  file 'C:\Program Files(x86)\Microsoft Office\Office15\1033\OUTLOOK.HOL';

  set Helligdage;

  if _N_ = 1 then do;

     put "[Dansk helligdag] &antal";

  end;

  put Helligdag +(-1) ', ' dato yymmdds10.;

run;

I Outlook tilføjer jeg de danske helligdage:

og i kalenderen ser jeg nu følgende:

Calender.png

Programmet kan jo let ændres  for andre år, evt. indsat i en macro for de næste mange år.

Jeg har fundet det rart selv at kunne bestemme indholdet af helligdagsfilen, istedet for at bruge Microsoft-standarden for Denmark - dels fordi jeg ikke ønsker 1. maj registreret som helligdag, men til gengæld ønsker dagen efter Kr. Himmelfart markeret, og dels fordi jeg ønsker helligdagene skrevet på dansk, og endelig har jeg valgt kun at markere helligdage som ikke falder i en weekend.

Bemærk at når dagene er importeret ser det ikke umiddelbart ud til at der er en let måde at slette dem fra Outlook igen, så afprøv evt. kun for næste år i første omgang.

Du kan iøvrigt godt oprette flere helligdagskalendere i den samme fil, så du f.eks. også reserverer ferie via et SAS-program - man skulle jo nødigt komme til at planlægge et møde midt i ferien Smiley Wink

God jul.

/Ole Steen

Comments
by SAS Employee GeorgMorsing
on ‎12-13-2014 11:56 AM

Super lærerigt. Mens jeg læste det så tænkte jeg, gad vide hvornår Ole propper koden ind i en SAS funktion. Tak Ole. Samt med automatisk i Outlook. Måske skulle du studere månen noget mere og finde på endnu mere smart kode. Smiley Happy

Georg

by New Contributor JanB
on ‎05-28-2015 09:50 AM

Tak til Ole for et super program.

Men man skal lige huske at tage højde for at grundlovsdag kan falde sammen med en af påskedagene.. I 2006 og 2017 falder grundlovsdag og 2. pinsedag sammen på en hverdag, og vi får to rækker for de pågældende dage.

Her vil det nok være best practice at danne to tabeller og Merge/Joine bagefter, så vi har styr på hvad der sker.

Jan Brentved

by Contributor bergsorensen
on ‎06-03-2015 02:08 AM

En anden måde at gøre ovenstående (som format) - med lidt "ekstra" Smiley Happy

** Find helligdage for periode x-x **;

data Fmt_hellig_fridage;

  keep fmtname type start end label hlo;

  retain fmtname 'HDAG' type 'N';

  *****************************************************************;

  ***** Begræns antal år for format...Virker 'kun' til år 2300 ****;

    do aar=1990 to 2100;

      *****************************************************************;

      ******************* INDSÆT FASTE HELLIGDAGE HER *****************;

      start=mdy(01,01,aar);label='NYT01  ';link ud;

      start=mdy(12,24,aar);label='JUL24  ';link ud;

      start=mdy(12,25,aar);label='JUL25  ';link ud;

      start=mdy(12,26,aar);label='JUL26  ';link ud;

      start=mdy(12,31,aar);label='NYT31  ';link ud;

      *****************************************************************;

      ******************* INDSÆT FASTE FRIDAGE HER ********************;

      start=mdy(06,05,aar);label='GLOVDAG ';link ud;

      *****************************************************************;

      if      aar >= 1582 and aar <= 1699 then do; m=22; n=2; end;

      else if aar >= 1700 and aar <= 1799 then do; m=23; n=3; end;

      else if aar >= 1800 and aar <= 1899 then do; m=23; n=4; end;

      else if aar >= 1900 and aar <= 2099 then do; m=24; n=5; end;

      else if aar >= 2100 and aar <= 2199 then do; m=24; n=6; end;

      else if aar >= 2200 and aar <= 2299 then do; m=25; n=0; end;

      else                                    do; m=99; n=9; end;

      *****************************************************************;

      * Find påskedag (var=paaske)                                    ;

      *****************************************************************;

      RestA = mod(aar,19);

      RestB = mod(aar,4);

      RestC = mod(aar,7);

      RestD = mod((((19*RestA)+m)),30);

      RestE = mod(((n+(2*RestB)+(4*RestC)+(6*RestD))),7);

      RestF = RestD+RestE;

      RestG = RestF-9;

      if RestG <= 0 then do;

        paskedd = 22+RestF;

        paaske = mdy(03,paskedd,aar);

      end;

      else do;

        paaskedd = RestG;

        if paaskedd=26 then paaskedd=19;

        if paaskedd=25 and RestD=28 and RestA > 10 then paaskedd=18;

        paaske = mdy(04,paaskedd,aar);

      end;

      *****************************************************************;

      * Find andre forskydelige helligdage på baggrund af påskedag    ;

      *****************************************************************;

      start=paaske-3 ;label='PÅSKET';link ud;

      start=paaske-2 ;label='PÅSKEF';link ud;

      start=paaske+1 ;label='PÅSKEM';link ud;

      start=paaske+26;label='STBEDE';link ud;

      start=paaske+39;label='KRHIMF';link ud;

      start=paaske+50;label='PINSE2';link ud;

      *****************************************************************;

    end;

  start=.;

  end=start;

  hlo='O';

  label=' ';

  link ud;

  stop;

  UD:

  end=start;

  output;

run;

proc sort data=Fmt_hellig_fridage;

by start end descending label;

run;

data Fmt_hellig_fridage;

set Fmt_hellig_fridage;

by start end;

if first.start;

run;

** Lav hdag. format **;

proc format cntlin=Fmt_hellig_fridage;

run;