<?php
// Copyright (c) 2001-2014, Björn Victor <Bjorn@Victor.se>
// This work is licensed under the Creative Commons Attribution 2.5
// Sweden License. To view a copy of this license, visit
// http://creativecommons.org/licenses/by/2.5/se/ or send a letter to
// Creative Commons, 444 Castro Street, Suite 900, Mountain View,
// California, 94041, USA.

require_once($_SERVER['DOCUMENT_ROOT']."/../php/init.php");
require_once(
"htlang.php");    // check preferred language
$lang htlang();

$page_title = ($lang == 'sv' 'Allmänna helgdagar' 'Swedish Public Holidays');

if (
$lang == 'sv') {        // set up date printing correctly
  
if (function_exists("version_compare") and version_compare("4.3.0",phpversion()) != 1) {
    
// at least 4.3.0
    
setlocale(LC_TIME,"sv","sv_SE");
  } else {
    
// older
    
setlocale(LC_TIME,"sv_SE");
  }
}

class 
holiDay {
  var 
$date$desc$flag;
  function 
holiDay($mon,$day,$year,$desc,$flag false) {
    
$this->desc $desc;
    
$this->flag $flag;
    
$this->date mktime(12,0,0,$mon,$day,$year);
  }
  function 
is_holiday() {
    return 
true;
  }
  function 
flag() {
    return 
$this->flag;
  }
  function 
startFont() {
    return 
"<font color=\"red\">";
  }
  function 
endFont() {
    return 
"</font>";
  }

  function 
mkrow($flagday,$lang 'sv') {
    if (
$this->date >= 0)
      
$ds strftime("%e %B %Y (%A)",$this->date);
    else
      
$ds "<font color=\"blue\">".($lang == 'sv'?'[felaktigt datum]':'[bad date]')."</font>";
    return 
"<tr><td
class=\"nobg\">"
.$this->startFont().$this->desc[$lang].$this->endFont().
      
"</td><td
class=\"nobg\">"
.$ds."</td>".($flagday "<td>".($this->flag() ? "<img
src=\"fl_sm_SWE.gif\" border=0
alt=\"Flaggdag\">" 
"&nbsp;")."</td>" "")."</tr>";
  }
  function 
compare($a,$b) {
    if (
$a->date $b->date)
      return -
1;
    if (
$a->date == $b->date)
      return 
0//strcmp($a->desc, $b->desc);
    
return 1;
  }
}

class 
flagDay extends holiDay {
  function 
flag() {
    return 
true;
  }
  function 
is_holiday() {
    return 
false;
  }
  function 
startFont() {
    return 
"";
  }
  function 
endFont() {
    return 
"";
  }
}

function 
HDcompare($a,$b) {
    if (
$a->date $b->date)
      return -
1;
    if (
$a->date == $b->date)
      return 
0//strcmp($a->desc, $b->desc);
    
return 1;
}
class 
marchDay extends holiDay{
  function 
marchDay($mon,$day,$year,$desc,$flag false) {
    if (
$day <= 31) {        // mars
      
$mon 3$day $day;
    } elseif (
$day <= 31+30) {
      
$mon 4$day $day-31// april
    
} elseif ($day <= 31+30+31) {
      
$mon 5$day $day - (31+30); // maj
    
} elseif ($day <= 31+30+31+30) {
      
$mon 6$day $day - (31+30+31); // juni
    
} else {
      
$mon 3$day $day;    // hmm...
    
}
    
$p get_parent_class($this);
    
parent::$p($mon,$day,$year,$desc,$flag);
  }
}

function 
easterDay($y) {
  
// Se http://aa.usno.navy.mil/faq/docs/easter.html
  
$c floor($y 100);
  
$n $y 19 floor$y 19 );
  
$k floor(( $c 17 ) / 25);
  
$i $c floor($c 4) - floor(( $c $k ) / 3) + 19 $n 15;
  
$i $i 30 floor$i 30 );
  
$i $i floor$i 28 ) * ( floor$i 28 ) * floor29 / ( $i ) )
                * 
floor( ( 21 $n ) / 11 ) );
  
$j $y floor($y 4) + $i $c floor($c 4);
  
$j $j floor$j );
  
$l $i $j;
  
$m floor(( $l 40 ) / 44); // month
  
$d $l 28 31 floor$m ); // day

  
return ($m == $d $d+31);
}


function 
getHolidays($year,$flagdays false) {
  
// Se http://www.jit.se/lagbok/989253t.html och http://www.jit.se/lagbok/982270t.html
// http://www.riksdagen.se/debatt/bet_yttr/dok.asp?dok_id=GS01KU6
  
$easter easterDay($year);
  
// midsommardagen den lördag som infaller under tiden den 20--26 juni
  
$ms getdate(mktime(0,0,0,6,20,$year));
  
$msd 20 + (6-$ms['wday']);
  
// alla helgons dag den lördag som infaller under tiden den 31
  // oktober--den 6 november
  
$ah getdate(mktime(0,0,0,10,31,$year));
  
$ahd 6-$ah['wday'];

  
$hdays = array(new holiDay(1,1,$year,array('sv'=>"Nyårsdagen",
                         
'en'=>'New Year Day'),true),
         new 
holiDay(1,6,$year,array('sv'=>"Trettondagen",
                         
'en'=>'Epiphany')),
         new 
holiDay(5,1,$year,array('sv'=>"Första maj",
                         
'en'=>'May Day'),true),
         new 
marchDay(3,$easter-2,$year,array('sv'=>"Långfredagen",
                              
'en'=>'Good Friday')),
         new 
marchDay(3,$easter,$year,array('sv'=>"Påskdagen",
                            
'en'=>'Easter Day'),true),
         new 
marchDay(3,$easter+1,$year,array('sv'=>"Annandag påsk",
                              
'en'=>'Easter Monday')),
         new 
marchDay(3,$easter+5*7+4,$year,array('sv'=>"Kristi himmelsfärdsdag",
                              
'en'=>'Ascension Day')),
         new 
marchDay(3,$easter+7*7,$year,array('sv'=>"Pingstdagen",
                            
'en'=>'Pentecost Day'),
                  
true),
         new 
holiDay(6,$msd,$year,array('sv'=>"Midsommardagen",
                        
'en'=>'Midsummer Day'),true),
         (
$ahd == ?
          new 
holiDay(10,31,$year,array('sv'=>"Alla helgons dag",'en'=>"All Saint's Day")) :
          new 
holiDay(11,$ahd,$year,array('sv'=>"Alla helgons dag",'en'=>"All Saints' Day"))),
         new 
holiDay(12,25,$year,array('sv'=>"Juldagen",'en'=>'Christmas Day'),true),
         new 
holiDay(12,26,$year,array('sv'=>"Annandag jul",'en'=>'Boxing Day')));
  if (
$year 2005)
    
$hdays[] = new marchDay(3,$easter+7*7+1,$year,array('sv'=>"Annandag pingst",
                            
'en'=>'Whitmonday'));
  else
    
$hdays[] = new holiDay(6,6,$year,array('sv'=>"Sveriges nationaldag och svenska flaggans dag",
                       
'en'=>"Swedish National Day and the Swedish Flag's Day"),
               
true);

  if (
$flagdays) {
    
$fdays = array(new flagDay(1,28,$year,array('sv'=>"Konungens namnsdag",
                        
'en'=>"The King's Name Day")),
           new 
flagDay(3,12,$year,array('sv'=>"Kronprinsessans namnsdag",
                        
'en'=>"The Crown Princess' Name Day")),
           new 
flagDay(4,30,$year,array('sv'=>"Konungens födelsedag",
                        
'en'=>"The King's Birthday")),
           new 
flagDay(7,14,$year,array('sv'=>"Kronprinsessans födelsedag",
                        
'en'=>"The Crown Princess' Birthday")),
           new 
flagDay(8,8,$year,array('sv'=>"Drottningens namnsdag",
                           
'en'=>"The Queen's Name Day")),
           new 
flagDay(10,24,$year,array('sv'=>"FN-dagen",
                         
'en'=>"UN Day")),
           new 
flagDay(11,6,$year,array('sv'=>"Gustav Adolfsdagen",
                        
'en'=>"The Gustaf Adolf Day")),
           new 
flagDay(12,10,$year,array('sv'=>"Nobeldagen",
                         
'en'=>'Nobel Day')),
           new 
flagDay(12,23,$year,array('sv'=>"Drottningens födelsedag",
                         
'en'=>"The Queen's Birthday")));
    if (
$year 2005)
      
$hdays[] = new flagDay(6,6,$year,array('sv'=>"Sveriges nationaldag och svenska flaggans dag",
                         
'en'=>"Swedish National Day and the Swedish Flag's Day"));
    if (
$year == 2010)
      
$fdays[] = new flagDay(9,19,$year,array('sv'=>'Valdagen',
                          
'en'=>'Election day'));
    
$hdays array_merge($hdays,$fdays);
  }
  
usort($hdays,"HDcompare");
  return 
$hdays;
}

function 
show_holidays($year,$fromyear,$toyear,$flagdays false$lang 'sv') {
  if (
$fromyear != and $toyear != 0) {
    
$hdays = array();
    for (
$yr $fromyear$yr <= $toyear$yr++) {
      
$hd getHolidays($yr$flagdays);
      
$hdays array_merge($hdays$hd);
    }
  } else
    
$hdays getHolidays($year,$flagdays); // Hämta helgdagarna
  
$rows = array();
  
$hasbad false;
  foreach (
$hdays as $hd) {
    
$rows[] = $hd->mkrow($flagdays,$lang);
    if (
$hd->date <= 0) {
      
$hasbad true;
      break;
    }
  }
  if (
$hasbad) {
    
$last getdate((1<<30)+(1<<29)+((1<<29)-1)); // 2^31-1
    
$lyear $last['year']-1;
    if (
$lang == 'sv')
      return 
'<p style="color: blue">Kanske har du angivit ett för sent
eller för tidigt årtal för detta datorsystem? Prova mellan
'
.date("Y",0).' och '.$lyear.'.</p>';
    else
      return 
'<p style="color: blue">Perhaps you have a too late or too early year for this computer system?  Try one between '.date("Y",0).' and '.$lyear.'.</p>';
  } else {
    return 
'<table border="1" class="nobg">'
      
."<tr><th class=\"nobg\">".($lang == 'sv' ? ($flagdays "Dag":"Helgdag") : ($flagdays 'Day' 'Holiday'))."</th><th
class=\"nobg\">"
.($lang == 'sv' "Datum" 'Date')."</th>".($flagdays ? ($lang == 'sv' "<th>Flaggdag</th>" '<th>Flag day</th>'):"")."</tr>\n"
      
.implode("\n",$rows)
      .
"\n</table>\n";
  }
}

function 
addurlarg($str,$key,$val) {
  if (
preg_match("/(.+)\\?".preg_quote($key)."=([^\\?&]+)(.*)/",$str,$m)) 
    return 
$m[1]."?$key=$val".$m[3];
  elseif (
preg_match("/(.+)&amp;".preg_quote($key)."=([^\\?&]+)(.*)/",$str,$m)) 
    return 
$m[1]."?$key=$val".$m[3];
  elseif (
preg_match("/(.+)&".preg_quote($key)."=([^\\?&]+)(.*)/",$str,$m)) 
    return 
$m[1]."&amp;$key=$val".$m[3];
  elseif (
preg_match("/\\?/",$str))
    return 
$str."&amp;$key=$val";
  else
    return 
$str."?$key=$val";
}

function 
g_or_p($x$default null) {
  if (
array_key_exists($x,$_GET)) // värde från URLen?
    
return $_GET[$x];
  if (
array_key_exists($x,$_POST)) // värde från formulär?
    
return $_POST[$x];
  return 
$default;
}

$yeararg g_or_p('year');
if (empty(
$yeararg) or !checkdate(1,1,$yeararg)) { // inget, eller felaktigt
  
$now getdate(time());
  
$year $now['year'];        // använd innevarande år
} else
  
$year $yeararg;

$fromarg g_or_p('from');
$toarg g_or_p('to');

// Kolla om användaren vill ha ett intervall av år
$from 0$to 0$fromyear 0$toyear 0;
if (
is_numeric($fromarg)) $from = (int)$fromarg;
if (
is_numeric($toarg)) $to = (int)$toarg;
if (
$from or (($from or $to != 0) and $from 10))
  
$fromyear $year $from;
elseif (
$from 10)
  
$fromyear $from;
if (
$to or (($to or $from != 0) and $to 10))
  
$toyear $year $to;
elseif (
$to 10)
  
$toyear $to;

$flag g_or_p('flagdays');
$flag = !empty($flag);

if (
g_or_p('vcal') == 'yes') {
  
// vill ha det i vCalendar-format!
  
require_once('vcal.php');    // behöver detta bibliotek
  
if ($fromyear != and $toyear != 0) {
    
$hdays = array();
    for (
$yr $fromyear$yr <= $toyear$yr++) {
      
$hd getHolidays($yr$flag);
      
$hdays array_merge($hdays$hd);
    }
  } else
    
$hdays getHolidays($year,$flag); // Hämta helgdagarna
  
$hcat g_or_p('hdaycat');    // kategorier
  
$fcat g_or_p('flagcat');
  
$vcvers g_or_p('vcvers',2);    // vCalendar eller iCalendar?
  
$vc = new vCal($hdays,$hcat,$fcat,$vcvers,$lang); // bygg objektet
  
$vc->show_vcal();        // och visa det
  
exit;                // Klart!
}
if (
g_or_p('csv') == 'yes') {
  require_once(
'csv.php');
  if (
$fromyear != and $toyear != 0) {
    
$hdays = array();
    for (
$yr $fromyear$yr <= $toyear$yr++) {
      
$hd getHolidays($yr$flag);
      
$hdays array_merge($hdays$hd);
    }
  } else
    
$hdays getHolidays($year,$flag); // Hämta helgdagarna
  
$cv = new CSV($hdays,$lang);
  
$cv->show_csv();
  exit;
}
  

include(
"header.php");
?>
<body>
<h1><?php echo ($lang == 'sv' 'Allmänna helgdagar' 'Swedish Public Holidays')?></h1>
<p>
<span style="float: right; background-color: white; border: 1px solid red; margin-left: 10px; padding-left: 2px; padding-right: 2px"><?php echo '<a href="'.addurlarg($_SERVER['REQUEST_URI'],"lang",($lang == 'sv'?'en':'sv')).'">'.($lang == 'sv' 'In English, please' 'På svenska tack')?></a></span>
<?php if ($lang == 'sv'): ?>
Detta formulär beräknar <a
href="http://www.riksdagen.se/sv/Dokument-Lagar/Lagar/Svenskforfattningssamling/Lag-1989253-om-allmanna-hel_sfs-1989-253/">svenska
  helgdagar</a> för ett givet år.  <strong>Notera</strong> att helgdagar och flaggdagar kan ändras i framtiden, och att beräkningen sker efter de regler som gäller just nu (dvs om du väljer ett tidigare eller senare år stämmer datumen inte säkert).
</p>
  <p><strong>Nytt:</strong> du kan du ange ett intervall av år, eventuellt relativt det valda året, och få helgdagar för flera år i taget. 
<ul><li>Exempel: lämna fältet för år <strong>tomt</strong>, ange "0" och "2" som intervall - resultatet är helgdagar från år nu+0 till nu+2.</li>
  <li>Exempel: ange år "2011", och "-1" och "3" som intervall - resultatet är helgdagar från 2011-1 till 2011+3.</li>
  <li>Exempel: ange "2011" och "2020" som intervall - resultatet är helgdagar från år 2011 till 2020.</li>
</ul>
  <?php else: ?>
This form calculates 
  <a href="http://www.riksdagen.se/sv/Dokument-Lagar/Lagar/Svenskforfattningssamling/Lag-1989253-om-allmanna-hel_sfs-1989-253/">Swedish holidays</a> for a given year.  <strong>Please note</strong> that holidays and flag days may change in the future, and that the calculations are done according to the present rules (so if you select an earlier or later year the dates might not be correct).
  <?php endif; ?>
</p>
<?php
    $now 
getdate();
if ((
$now['year'] == 2008 and ($now['mon'] == and $now['mday'] < 17))) {
 if (
$lang == 'sv') {
 echo 
"<center><a href='http://frapedia.se/wiki/Demonstrationerna_i_Stockholm_den_16_september_2008'><img src='http://stoppafralagen.nu/sites/default/files/banner-16sep.png' alt='Demonstrera mot FRA-lagen 16 september' width='468' height='60'></a></center>";
 }
}
 else if ((
$now['year'] == 2008 and ($now['mon'] == or ($now['mon'] == 10 and $now['mday'] < 12)))) {
   echo 
'<center><a href="http://www.freedom-not-fear.eu/"><img src="http://wiki.vorratsdatenspeicherung.de/images/Webbanner-b_rgb_468x60px.gif" alt="Freedom, not fear!" width="468" height="60"></a></center>';
}
else if ((
$now['year'] == 2005 and ($now['mon'] < 11 or ($now['mon'] == 11 and $now['mday'] < 12)))) {
  if (
$lang == 'sv') {
    echo 
"<span style='float: right'><a href='http://www.nosoftwarepatents.com/se/m/ev50/index.html'><img src='http://www.nosoftwarepatents.com/banners/ev50_2_se.jpg' alt='Rösta för rätten att skriva datorprogram' width='468' height='60'></a></span>";
  } else {
    echo 
"<span style='float: right'><a href='http://www.nosoftwarepatents.com/en/m/ev50/index.html'><img src='http://www.nosoftwarepatents.com/banners/ev50_2_en.jpg' alt='Vote for the right to program' width='468' height='60'></a></span>";
  }
 }
?>
<form action="" method="GET">
<input type="hidden" name="lang" value="<?php echo $lang ?>">
<input type="submit" value="<?php echo ($lang == 'sv' 'Beräkna helgdagar för år' 'Calculate holidays for year')?>">
<input type="text" size="6" name="year" value="<?php echo $yeararg ?>">
  (<?php  echo (($lang == 'sv') ? "eller: mellan åren " "or: between year "); ?>
<input type="text" size="6" name="from" value="<?php echo $fromarg ?>">
  <?php  echo (($lang == 'sv') ? " och " " and "); ?>
<input type="text" size="6" name="to" value="<?php echo $toarg ?>">
   <?php  echo (($lang == 'sv') ? ", ev. relativt i år" ", optionally relative to current year"); ?>)
<span class="nobg">
  <?php if ($lang == 'sv'): ?>
Visa <a
href="http://www.riksdagen.se/webbnav/index.aspx?nid=3911&amp;bet=1982:270">flaggdagar</a>:&nbsp;
<?php else: ?>
Show <a
href="http://www.riksdagen.se/webbnav/index.aspx?nid=3911&amp;bet=1982:270">flag days</a>:&nbsp;
  <?php endif; ?>
</span><input
type="checkbox" name="flagdays" <?php if ($flag) echo " checked"?>>
</form>

<?php
    
echo show_holidays($year,$fromyear,$toyear,$flag,$lang);
?>
<p>
<?php if ($lang == 'sv'): ?>
   Du kan också få helgdagarna i <a href="http://en.wikipedia.org/wiki/Comma-separated_values">CSV</a>-, <a href="http://www.imc.org/pdi/">vCalendar</a>- eller <a href="http://www.imc.org/pdi/">iCalendar</a>-format att ladda ner till din PDA eller telefon! <br />[Är du osäker på formatet, välj iCalendar.]
   <?php else: ?>
      You can get the holidays in <a href="http://en.wikipedia.org/wiki/Comma-separated_values">CSV</a>,  <a href="http://www.imc.org/pdi/">vCalendar</a>, or <a href="http://www.imc.org/pdi/">iCalendar</a> format, to download to your PDA or telephone! <br />[If you are unsure of the format, choose iCalendar.]
   <?php endif; ?>
<ul class="nobg">
<li>
<?php if ($lang == 'sv'): ?>
Klicka <a href="<?php echo addurlarg($_SERVER['REQUEST_URI'],'csv','yes')?>">här</a> för att få helgdagarna i CSV-format,
  <?php else: ?>
Click <a href="<?php echo addurlarg($_SERVER['REQUEST_URI'],'csv','yes')?>">here</a> to get the holidays in CSV format,
  <?php endif; ?>
</li>
<li>
<?php if ($lang == 'sv'): ?>
Klicka <a href="<?php echo addurlarg($_SERVER['REQUEST_URI'],'vcal','yes')?>">här</a> för att få helgdagarna utan "kategorier" i iCalendar-format,
  <?php else: ?>
Click <a href="<?php echo addurlarg($_SERVER['REQUEST_URI'],'vcal','yes')?>">here</a> to get the holidays without "categories",
  <?php endif; ?>
</li>
<li>
<?php if ($lang == 'sv'): ?>
  eller fyll i vilka kategorier du vill använda och klicka "OK":
<?php else: ?>
    or fill in which categories you want to use, and click "OK":
<?php endif; ?>
<form method="post" action="<?php echo preg_replace("/\\?.*$/","",$_SERVER['REQUEST_URI'])?>">
<input type="hidden" name="lang" value="<?php echo $lang ?>" />
<input type="hidden" name="vcal" value="yes" />
<input type="hidden" name="year" value="<?php echo $yeararg ?>" />
<input type="hidden" name="from" value="<?php echo $fromarg ?>" />
<input type="hidden" name="to" value="<?php echo $toarg ?>" />
  <label for="hdaycat"><?php echo ($lang == 'sv' 'Kategori för helgdagar' 'Category for holidays')?>: </label><input type="text" name="hdaycat" id="hdaycat" />
<?php if ($flag): ?>
<input type="hidden" name="flagdays" value="on" />
   <label for="flagcat"><?php echo ($lang == 'sv' 'Kategori för flaggdagar' 'Category for flag days')?>: </label><input type="text" name="flagcat" id="flagcat" />
<?php endif; ?>
<label for="vcvers">Format: </label>
<select name="vcvers" id="vcvers">
  <option value="1">vCalendar (1.0)</option>
  <option value="2" selected="selected">iCalendar (2.0)</option>
</select>
<input type="submit" value="OK" />
</form>
</li>
</ul>
<p>
<?php
if ($lang == 'sv')
  echo 
'<strong>Nytt:</strong> Se också <a href="weekno.php">en sida för göra ett iCal-flöde för veckonummer</a>.';
else
  echo 
'<strong>New:</strong> See also <a href="weekno.php">a page to make an iCal flow for week numbers</a>.';
?>
</p>
<p>
<?php
$rq 
strpos($_SERVER['REQUEST_URI'],'?') === false $_SERVER['REQUEST_URI'] : substr($_SERVER['REQUEST_URI'],0,strpos($_SERVER['REQUEST_URI'],'?'));
$src basename($rq,".php")."-source.php";

if (
$lang == 'sv') {
  echo 
"(Du kan titta på <a href='".$src."'>källkoden</a> om du vill se hur beräkningarna går till.)";
  echo 
'<span style="float:right"><a rel="license" href="http://creativecommons.org/licenses/by/2.5/se/"><img alt="Creative Commons-licens" style="border-width:0" src="http://i.creativecommons.org/l/by/2.5/se/88x31.png" title="Detta verk är licensierat under en Creative Commons Erkännande 2.5 Sverige Licens" /></a></span>';
 }
 else {
  echo 
"(You can have a look at the <a href='".$src."'>source code</a> if you want to see how the calculations are done.)";
  echo 
'<span style="float:right"><a rel="license" href="http://creativecommons.org/licenses/by/2.5/se/"><img alt="Creative Commons License" style="border-width:0" src="http://i.creativecommons.org/l/by/2.5/se/88x31.png" title="This work is licensed under a Creative Commons Attribution 2.5 Sweden License" /></a></span>';
 }

include(
"footer.php");
?>
</body>
</html>