Date::Calc
Handbuch-Seite



NAME

Date::Calc - Datumsberechnungen nach dem Gregorianischen Kalender


VORWORT

Dieses Paket besteht aus einer C-Bibliothek und einem Perl-Modul (das die C-Bibliothek intern nutzt). Damit können, basierend auf dem Gregorianischen Kalender (der heutzutage in allen westlichen Ländern verwendet wird), alle Arten von Datumsberechnungen durchgeführt werden. Alle relevanten Normen und Standards werden dabei berücksichtigt: ISO/R 2015-1971, DIN 1355 und, bis zu einem gewissen Grad, ISO 8601 (wo anwendbar).

(Sie finden einen Teil des "DIN 1355"-Dokuments (auf Deutsch) unter der URL http://sb.fluomedia.org/download/Date-Calc/DIN1355/.)

Das Modul kann natürlich auch Jahreszahlen von 2000 und danach korrekt verarbeiten ("Year 2000"- oder "Y2K"-Compliance) - tatsächlich können alle Jahreszahlen von 1 bis zum größten ganzzahligen, auf Ihrem System noch darstellbaren positiven Wert (also mindestens bis 32767) verarbeitet werden.

Beachten Sie, daß dieses Paket den Gregorianischen Kalender bis ins Jahr 1 n. Chr. EXTRAPOLIERT, obwohl der Gregorianische Kalender erst 1582 von den meisten (nicht allen) europäischen Ländern übernommen wurde, dem Dekret von Papst Gregor I. aus diesem Jahr entsprechend.

Einige (hauptsächlich protestantische) Länder haben den (bis dahin geltenden) Julianischen Kalender weiterverwendet, zum Teil sogar bis zum Beginn des 20. Jahrhunderts.

Beachten Sie schließlich auch, daß dieses Paket nicht dazu gedacht ist, alle nur vorstellbaren Aufgaben automatisch für Sie zu übernehmen. Es ist vielmehr als Werkzeugkasten (in bester UNIX-Tradition) gedacht, die Sie überall hinbringt, wo Sie hin wollen.

Wenn es Ihnen dennoch nicht gelingen sollte, ein bestimmtes Problem zu lösen, lassen Sie es mich wissen! (Die E-Mail-Adresse finden Sie am Ende dieses Dokuments.)


ÜBERSICHT

  use Date::Calc qw(
      Days_in_Year
      Days_in_Month
      Weeks_in_Year
      leap_year
      check_date
      check_business_date
      Day_of_Year
      Date_to_Days
      Day_of_Week
      Week_Number
      Week_of_Year
      Monday_of_Week
      Nth_Weekday_of_Month_Year
      Standard_to_Business
      Business_to_Standard
      Delta_Days
      Delta_DHMS
      Add_Delta_Days
      Add_Delta_DHMS
      Add_Delta_YMD
      System_Clock
      Today
      Now
      Today_and_Now
      Easter_Sunday
      Decode_Month
      Decode_Day_of_Week
      Decode_Language
      Decode_Date_EU
      Decode_Date_US
      Compress
      Uncompress
      check_compressed
      Compressed_to_Text
      Date_to_Text
      Date_to_Text_Long
      Calendar
      Month_to_Text
      Day_of_Week_to_Text
      Day_of_Week_Abbreviation
      Language_to_Text
      Language
      Languages
      Decode_Date_EU2
      Decode_Date_US2
      Parse_Date
  );

  use Date::Calc qw(:all);

  Days_in_Year
      $days = Days_in_Year($year,$month);

  Days_in_Month
      $days = Days_in_Month($year,$month);

  Weeks_in_Year
      $weeks = Weeks_in_Year($year);

  leap_year
      if (leap_year($year))

  check_date
      if (check_date($year,$month,$day))

  check_business_date
      if (check_business_date($year,$week,$dow))

  Day_of_Year
      $doy = Day_of_Year($year,$month,$day);

  Date_to_Days
      $days = Date_to_Days($year,$month,$day);

  Day_of_Week
      $dow = Day_of_Week($year,$month,$day);

  Week_Number
      $week = Week_Number($year,$month,$day);

  Week_of_Year
      ($week,$year) = Week_of_Year($year,$month,$day);

  Monday_of_Week
      ($year,$month,$day) = Monday_of_Week($week,$year);

  Nth_Weekday_of_Month_Year
      if (($year,$month,$day) =
      Nth_Weekday_of_Month_Year($year,$month,$dow,$n))

  Standard_to_Business
      ($year,$week,$dow) =
      Standard_to_Business($year,$month,$day);

  Business_to_Standard
      ($year,$month,$day) =
      Business_to_Standard($year,$week,$dow);

  Delta_Days
      $Dd = Delta_Days($year1,$month1,$day1,
                       $year2,$month2,$day2);

  Delta_DHMS
      ($Dd,$Dh,$Dm,$Ds) =
      Delta_DHMS($year1,$month1,$day1, $hour1,$min1,$sec1,
                 $year2,$month2,$day2, $hour2,$min2,$sec2);

  Add_Delta_Days
      ($year,$month,$day) =
      Add_Delta_Days($year,$month,$day, $Dd);

  Add_Delta_DHMS
      ($year,$month,$day, $hour,$min,$sec) =
      Add_Delta_DHMS($year,$month,$day, $hour,$min,$sec,
                     $Dd,$Dh,$Dm,$Ds);

  Add_Delta_YMD
      ($year,$month,$day) =
      Add_Delta_YMD($year,$month,$day,
                    $Dy,$Dm,$Dd);

  System_Clock
      ($year,$month,$day, $hour,$min,$sec, $doy,$dow,$dst) =
      System_Clock();

  Today
      ($year,$month,$day) = Today();

  Now
      ($hour,$min,$sec) = Now();

  Today_and_Now
      ($year,$month,$day, $hour,$min,$sec) = Today_and_Now();

  Easter_Sunday
      ($year,$month,$day) = Easter_Sunday($year);

  Decode_Month
      if ($month = Decode_Month($string))

  Decode_Day_of_Week
      if ($dow = Decode_Day_of_Week($string))

  Decode_Language
      if ($lang = Decode_Language($string))

  Decode_Date_EU
      if (($year,$month,$day) = Decode_Date_EU($string))

  Decode_Date_US
      if (($year,$month,$day) = Decode_Date_US($string))

  Compress
      $date = Compress($year,$month,$day);

  Uncompress
      if (($century,$year,$month,$day) = Uncompress($date))

  check_compressed
      if (check_compressed($date))

  Compressed_to_Text
      $string = Compressed_to_Text($date);

  Date_to_Text
      $string = Date_to_Text($year,$month,$day);

  Date_to_Text_Long
      $string = Date_to_Text_Long($year,$month,$day);

  Calendar
      $string = Calendar($year,$month);

  Month_to_Text
      $string = Month_to_Text($month);

  Day_of_Week_to_Text
      $string = Day_of_Week_to_Text($dow);

  Day_of_Week_Abbreviation
      $string = Day_of_Week_Abbreviation($dow);

  Language_to_Text
      $string = Language_to_Text($lang);

  Language
      $lang = Language();
      Language($lang);
      $oldlang = Language($newlang);

  Languages
      $max_lang = Languages();

  Decode_Date_EU2
      if (($year,$month,$day) = Decode_Date_EU2($string))

  Decode_Date_US2
      if (($year,$month,$day) = Decode_Date_US2($string))

  Parse_Date
      if (($year,$month,$day) = Parse_Date($string))

  Version
      $string = Date::Calc::Version();


WICHTIGE HINWEISE


BESCHREIBUNG


BEISPIELE

  1. Wie kann ich zwei Datumsangaben miteinander vergleichen?

    Lösung 1:

      use Date::Calc qw( Date_to_Days );
    
      if (Date_to_Days($year1,$month1,$day1)  <
          Date_to_Days($year2,$month2,$day2))
    
      if (Date_to_Days($year1,$month1,$day1)  <=
          Date_to_Days($year2,$month2,$day2))
    
      if (Date_to_Days($year1,$month1,$day1)  >
          Date_to_Days($year2,$month2,$day2))
    
      if (Date_to_Days($year1,$month1,$day1)  >=
          Date_to_Days($year2,$month2,$day2))
    
      if (Date_to_Days($year1,$month1,$day1)  ==
          Date_to_Days($year2,$month2,$day2))
    
      if (Date_to_Days($year1,$month1,$day1)  !=
          Date_to_Days($year2,$month2,$day2))
    
      $cmp = (Date_to_Days($year1,$month1,$day1)  <=>
              Date_to_Days($year2,$month2,$day2));
    

    Lösung 2:

      use Date::Calc qw( Delta_Days );
    
      if (Delta_Days($year1,$month1,$day1,
                     $year2,$month2,$day2) > 0)
    
      if (Delta_Days($year1,$month1,$day1,
                     $year2,$month2,$day2) >= 0)
    
      if (Delta_Days($year1,$month1,$day1,
                     $year2,$month2,$day2) < 0)
    
      if (Delta_Days($year1,$month1,$day1,
                     $year2,$month2,$day2) <= 0)
    
      if (Delta_Days($year1,$month1,$day1,
                     $year2,$month2,$day2) == 0)
    
      if (Delta_Days($year1,$month1,$day1,
                     $year2,$month2,$day2) != 0)
    

  2. Wie kann ich prüfen, ob ein gegebenes Datum innerhalb eines bestimmten Datumsbereichs liegt?

      use Date::Calc qw( Date_to_Days );
    
      $lower = Date_to_Days($year1,$month1,$day1);
      $upper = Date_to_Days($year2,$month2,$day2);
    
      $date = Date_to_Days($year,$month,$day);
    
      if (($date >= $lower) && ($date <= $upper))
      {
          # OK
      }
      else
      {
          # nicht OK
      }
    

  3. Wie kann ich prüfen, ob jemand ein bestimmtes Alter hat?

      use Date::Calc qw( Decode_Date_EU Today leap_year Delta_Days );
    
      $date = <STDIN>; # Geburtstag einlesen
    
      ($year1,$month1,$day1) = Decode_Date_EU($date);
    
      ($year2,$month2,$day2) = Today();
    
      if (($month1 == 2) && ($day1 == 29) && !leap_year($year2))
          { $day1--; }
    
      if ( (($year2 - $year1) >  18) ||
         ( (($year2 - $year1) == 18) &&
         (Delta_Days($year2,$month1,$day1, $year2,$month2,$day2) >= 0) ) )
      {
          print "Ok - Sie sind über 18.\n";
      }
      else
      {
          print "Sorry - Du bist noch keine 18!\n";
      }
    

  4. Wie kann ich die Nummer der Woche innerhalb des Monats berechnen, in der das aktuelle Datum liegt?

    Beispiel:

                April 1998
        Mon Tue Wed Thu Fri Sat Sun
                  1   2   3   4   5  =  1. Woche
          6   7   8   9  10  11  12  =  2. Woche
         13  14  15  16  17  18  19  =  3. Woche
         20  21  22  23  24  25  26  =  4. Woche
         27  28  29  30              =  5. Woche
    

    Lösung:

      use Date::Calc qw( Today Day_of_Week );
    
      ($year,$month,$day) = Today();
    
      $week = int(($day + Day_of_Week($year,$month,1) - 2) / 7) + 1;
    

  5. Wie kann ich berechnen, ob ein bestimmtes Datum der 1., 2., 3., 4. oder 5. Wochentag innerhalb des gegebenen Monats ist?

    Beispiel:

               October 2000
        Mon Tue Wed Thu Fri Sat Sun
                                  1
          2   3   4   5   6   7   8
          9  10  11  12  13  14  15
         16  17  18  19  20  21  22
         23  24  25  26  27  28  29
         30  31
    

    Ist Sonntag, der 15. Oktober 2000, der erste, zweite, dritte, vierte oder fünfte Sonntag dieses Monats?

    Lösung:

      use Date::Calc qw( Delta_Days Nth_Weekday_of_Month_Year
                         Day_of_Week Day_of_Week_to_Text
                         Date_to_Text_Long Month_to_Text );
    
      %ordinal = ( 1 => 'st', 2 => 'nd', 3 => 'rd' );
    
      ($year,$month,$day) = (2000,10,15);
    
      $dow = Day_of_Week($year,$month,$day);
    
      $n = int( Delta_Days(
                Nth_Weekday_of_Month_Year($year,$month,$dow,1),
                $year,$month,$day)
                / 7) + 1;
    
      printf("%s is the %s %s in %s %d.\n",
          Date_to_Text_Long($year,$month,$day),
          $n . ($ordinal{$n} || 'th'),
          Day_of_Week_to_Text($dow),
          Month_to_Text($month),
          $year);
    

    Ausgabe:

      Sunday, 15 October 2000 is the 3rd Sunday in October 2000.
    

  6. Wie berechne ich das Datum des Mittwochs in derselben Woche wie das aktuelle Datum?

    Lösung 1:

      use Date::Calc qw( Today Day_of_Week Add_Delta_Days );
    
      $searching_dow = 3; # 3 = Mittwoch
    
      @today = Today();
    
      $current_dow = Day_of_Week(@today);
    
      @date = Add_Delta_Days(@today, $searching_dow - $current_dow);
    

    Lösung 2:

      use Date::Calc qw( Today Monday_of_Week
                         Week_of_Year Add_Delta_Days );
    
      $searching_dow = 3; # 3 = Mittwoch
    
      @today = Today();
    
      @date = Add_Delta_Days( Monday_of_Week( Week_of_Year(@today) ),
                              $searching_dow - 1 );
    

    Lösung 3:

      use Date::Calc qw( Today Standard_to_Business
                               Business_to_Standard );
    
      @business = Standard_to_Business(Today());
    
      $business[2] = 3; # 3 = Mittwoch
    
      @date = Business_to_Standard(@business);
    

  7. Wie kann ich einen Wochen-Offset zu einem Geschäftsdatum hinzuaddieren (mit korrekter Berücksichtigung von Jahresgrenzen)?

      use Date::Calc qw( Standard_to_Business Business_to_Standard );
    
      @temp = Business_to_Standard($year,$week,$dow);
    
      @temp = Add_Delta_Days(@temp, $week_offset * 7);
    
      ($year,$week,$dow) = Business_to_Standard(@temp);
    

  8. Wie kann ich den vorhergehenden und den nächsten Samstag für ein gegebenes Datum ermitteln?

      use Date::Calc qw( Today Day_of_Week Add_Delta_Days
                         Day_of_Week_to_Text Date_to_Text );
    
      $searching_dow = 6; # 6 = Samstag
    
      @today = Today();
    
      $current_dow = Day_of_Week(@today);
    
      if ($searching_dow == $current_dow)
      {
          @prev = Add_Delta_Days(@today,-7);
          @next = Add_Delta_Days(@today,+7);
      }
      else
      {
          if ($searching_dow > $current_dow)
          {
              @next = Add_Delta_Days(@today,
                        $searching_dow - $current_dow);
              @prev = Add_Delta_Days(@next,-7);
          }
          else
          {
              @prev = Add_Delta_Days(@today,
                        $searching_dow - $current_dow);
              @next = Add_Delta_Days(@prev,+7);
          }
      }
    
      $dow = Day_of_Week_to_Text($searching_dow);
    
      print "Today is:      ", ' ' x length($dow),
                                   Date_to_Text(@today), "\n";
      print "Last $dow was:     ", Date_to_Text(@prev),  "\n";
      print "Next $dow will be: ", Date_to_Text(@next),  "\n";
    

    Ausgabe:

      Today is:              Sun 12-Apr-1998
      Last Saturday was:     Sat 11-Apr-1998
      Next Saturday will be: Sat 18-Apr-1998
    

  9. Wie kann ich den letzten Werktag (Zahltag!) eines Monats bestimmen?

    Lösung 1 (OHNE Berücksichtigung von Feiertagen):

      $day = Days_in_Month($year,$month);
      $dow = Day_of_Week($year,$month,$day);
      if ($dow > 5)
      {
          ($year,$month,$day) =
              Add_Delta_Days($year,$month,$day, 5-$dow);
      }
    

    Lösung 2 (MIT Berücksichtigung von Feiertagen):

    Diese Lösung verlangt ein mehrdimensionales Array "@holiday", das alle Feiertage in der Form "$holiday[$year][$month][$day] = 1;" enthält.

    (Die Berechnung der beweglichen christlichen Feiertage finden Sie unter der Funktion "Easter_Sunday()" beschrieben.)

    Tage, die keine Feiertage sind, sollten in diesem Array undefiniert bleiben oder den Wert null besitzen.

      $day = Days_in_Month($year,$month);
      while (1)
      {
          while ($holiday[$year][$month][$day])
          {
              ($year,$month,$day) =
                  Add_Delta_Days($year,$month,$day, -1);
          }
          $dow = Day_of_Week($year,$month,$day);
          if ($dow > 5)
          {
              ($year,$month,$day) =
                  Add_Delta_Days($year,$month,$day, 5-$dow);
          }
          else { last; }
      }
    

  10. Wie kann ich einen "DATETIME"-Wert aus MS Visual Basic in seine Datums- und Zeitkomponenten zerlegen?

      use Date::Calc qw( Add_Delta_DHMS Date_to_Text );
    
      $datetime = "35883.121653";
    
      ($Dd,$Dh,$Dm,$Ds) = ($datetime =~ /^(\d+)\.(\d\d)(\d\d)(\d\d)$/);
    
      ($year,$month,$day, $hour,$min,$sec) =
          Add_Delta_DHMS(1900,1,1, 0,0,0, $Dd,$Dh,$Dm,$Ds);
    
      printf("The given date is %s %02d:%02d:%02d\n",
          Date_to_Text($year,$month,$day), $hour, $min, $sec);
    

    Ausgabe:

      The given date is Tue 31-Mar-1998 12:16:53
    

  11. Wie kann ich am Tag vor einem Treffen, das jeden ersten Freitag im Monat stattfindet, eine Erinnerungs-Mail an die Mitglieder der Gruppe schicken?

      use Date::Calc qw( Today Date_to_Days Add_Delta_YMD
                         Nth_Weekday_of_Month_Year );
    
      ($year,$month,$day) = Today();
    
      $tomorrow = Date_to_Days($year,$month,$day) + 1;
    
      $dow = 5; # 5 = Freitag
      $n   = 1; # 1 = erster Wochentag
    
      $meeting_this_month = Date_to_Days(
          Nth_Weekday_of_Month_Year($year,$month,$dow,$n) );
    
      ($year,$month,$day) = Add_Delta_YMD($year,$month,$day, 0,1,0);
    
      $meeting_next_month = Date_to_Days(
          Nth_Weekday_of_Month_Year($year,$month,$dow,$n) );
    
      if (($tomorrow == $meeting_this_month) ||
          ($tomorrow == $meeting_next_month))
      {
          # Mail an die Mitglieder der Gruppe schicken!
      }
    

  12. Wie kann ich ein Datum in einem Format ausgeben, das nicht von den Funktionen "Date_to_Text()", "Date_to_Text_Long()" oder "Compressed_to_Text()" unterstützt wird?

      use Date::Calc qw( Day_of_Week Day_of_Week_to_Text
                         Month_to_Text Today );
    
      ($year,$month,$day) = Today();
    

    Beispielsweise mit führenden Nullen für den Tag: "Fri 03-Jan-1964"

      printf("%.3s %02d-%.3s-%d\n",
          Day_of_Week_to_Text(Day_of_Week($year,$month,$day)),
          $day,
          Month_to_Text($month),
          $year);
    

    Beispielsweise im US-amerikanischen Format: "April 12th, 1998"

      %ordinal = ( 1 => 'st', 2 => 'nd', 3 => 'rd' );
    
      sub ordinal
      {
          return( $_[0] .
              ( (substr($_[0],-2,1) ne '1') &&
                $ordinal{substr($_[0],-1)} ||
                'th' ) );
      }
    
      $string = sprintf("%s %s, %d",
                    Month_to_Text($month),
                    ordinal($day),
                    $year);
    

    (Siehe dazu auch den Eintrag über "printf()" und/oder "sprintf()" in perlfunc(1)!)


SIEHE AUCH

perl(1), perlfunc(1), perlsub(1), perlmod(1), perlxs(1), perlxstut(1), perlguts(1).

news:news.answers "Calendar FAQ, v. 1.9 (modified 25 Apr 1998) Part 1/3"

news:news.answers "Calendar FAQ, v. 1.9 (modified 25 Apr 1998) Part 2/3"

news:news.answers "Calendar FAQ, v. 1.9 (modified 25 Apr 1998) Part 3/3"

http://www.math.uio.no/faq/calendars/faq.html

http://www.pip.dknet.dk/~pip10160/calendar.html

(Alle von Claus Tondering mailto:c-t@pip.dknet.dk)


EINSCHRÄNKUNGEN

In der aktuellen Implementierung des Pakets wird die gewählte Sprache in einer globalen Variable gespeichert.

Aus diesem Grund kann es zu unerwünschten Nebeneffekten kommen, wenn das Modul "Date::Calc" in Form einer Shared-Library genutzt oder sobald Perl Multithreading unterstützen wird. (Das Problem ist, daß ein Prozeß oder Thread immer die Sprache für ALLE ANDEREN Prozesse oder Threads mit wählt.)


VERSION

Diese Manual Page dokumentiert "Date::Calc" in der Version 4.2.


AUTOR

  Steffen Beyer
  mailto:sb@fluomedia.org
  http://sb.fluomedia.org/download/


URHEBERRECHTE

Copyright © 1995 - 1998 by Steffen Beyer. Alle Rechte vorbehalten.


ÜBERSETZUNG

Deutsche Übersetzung von Peter Klicman,
© 1998 by O'Reilly Verlag, Köln

(Vom Modulautor gegengelesen und überarbeitet)

Erschienen in: "Programmieren mit Perl-Modulen", O'Reilly Verlag Köln, 1999.

Verwendung hier mit freundlicher Genehmigung des O'Reilly Verlag, Köln.


LIZENZ

Dieses Paket ist Freie Software und kann unter denselben Lizenzbedingungen benutzt, modifiziert und weitergegeben werden wie Perl, d.h. es gelten die Bestimmungen der "Artistic License" oder (wahlweise) der "GNU General Public License".

Die C-Bibliothek, die den Kern dieses Perl-Moduls bildet, kann darüber hinaus auch unter den Lizenzbedingungen der "GNU Library General Public License" benutzt, modifiziert und weitergegeben werden.

Bitte beachten Sie die Dateien "Artistic.txt", "GNU_GPL.txt" und "GNU_LGPL.txt" in dieser Distribution für die entsprechenden Details!


HAFTUNGSAUSSCHLUSS

Die vorliegende Software wird so zur Verfügung gestellt wie sie ist, es werden keinerlei Garantien für ihre Eignung für welche Zwecke auch immer abgegeben, und es wird auch keine Haftung für die durch ihre Verwendung oder Nichtverwendbarkeit möglicherweise verursachten Schäden oder Ausfälle oder dergleichen übernommen, selbst wenn dem Autor solche möglichen Folgen bekannt sein oder bekannt gemacht werden sollten.

Siehe dazu auch die "GNU General Public License" für weitere Details.