Norbert: Letzten Monatstag ermitteln

Moinsen!

Ich ermittle so den letzten Tag eines Monats (eine Korrektur für den Dezember habe ich der Übersicht halber weggelassen):

use Time::Local;
  $jahr=2013;
  $monat=3; #Januar=1, Februar=2, ...
  $tagessekunden=24*60*60;
  ($sek,$min,$std,$monatstag,$tempmonat,$tempjahr,$wochentag,$jahrestag,$sommerzeit)=localtime(timelocal(0,0,0,1,$monat,$jahr)-$tagessekunden);
  print $monatstag;

Also

  • Den 1. Tag des Folgemonats, 00:00:00 Uhr an timelocal übergeben (Januar entspricht 0, für den Folgemonat muss also 1 übergeben werden)
  • Vom ermittelten Timestamp 1 Tag (24*60*60 Sekunden) abziehen
  • Ergebnis in Datum/Uhrzeit umwandeln, daraus den Monatstag verwenden

Das Ganze scheint wunderbar zu funktionieren - nur für März 2013 nicht. Der hat angeblich nur 30 Tage.

Wo liegt mein Fehler?

Viele Grüße,
Norbert

  1. Liebe Leute,

    ich habe meinen Fehler gefunden: Der 31.3. ist in diesem Jahr der letzte Sonntag im März und deshalb wegen der Umstellung auf die Sommerzeit nur 23 Stunden lang. Diesen Sonderfall hatte ich nicht berücksichtigt.

    Wenn sich schon jemand Gedanken gemacht hat: Besten Dank dafür!

    Viele Grüße,
    Norbert

    Moinsen!

    Ich ermittle so den letzten Tag eines Monats (eine Korrektur für den Dezember habe ich der Übersicht halber weggelassen):

    use Time::Local;
      $jahr=2013;
      $monat=3; #Januar=1, Februar=2, ...
      $tagessekunden=24*60*60;
      ($sek,$min,$std,$monatstag,$tempmonat,$tempjahr,$wochentag,$jahrestag,$sommerzeit)=localtime(timelocal(0,0,0,1,$monat,$jahr)-$tagessekunden);
      print $monatstag;

    Also

    • Den 1. Tag des Folgemonats, 00:00:00 Uhr an timelocal übergeben (Januar entspricht 0, für den Folgemonat muss also 1 übergeben werden)
    • Vom ermittelten Timestamp 1 Tag (24*60*60 Sekunden) abziehen
    • Ergebnis in Datum/Uhrzeit umwandeln, daraus den Monatstag verwenden

    Das Ganze scheint wunderbar zu funktionieren - nur für März 2013 nicht. Der hat angeblich nur 30 Tage.

    Wo liegt mein Fehler?

    Viele Grüße,
    Norbert

    1. hi,

      ich habe meinen Fehler gefunden: Der 31.3. ist in diesem Jahr der letzte Sonntag im März und deshalb wegen der Umstellung auf die Sommerzeit nur 23 Stunden lang. Diesen Sonderfall hatte ich nicht berücksichtigt.

      Solche Sonderfälle hast Du immer an der Backe, wenn Du Datumsberechnungen über die Sekunden machst.
      Tipp: Rechne mit ganzen Tagen, nutze Date::Calc von Steffen Beyer.

      Hotti

      1. gudn tach!

        Tipp: Rechne mit ganzen Tagen, nutze Date::Calc von Steffen Beyer.

        stimmt, das waere hier wohl am einfachsten umzusetzen (da logischerweise die anzahl der tage eines monats gleich dem letzten tag desselben monats ist):

        #!/usr/bin/perl  
        use strict;  
        use warnings;  
        use Date::Calc qw(Days_in_Month);  
          
        print Days_in_Month(2013, 3),"\n";  
        
        

        prost
        seth

      2. Hallo,

        ich habe meinen Fehler gefunden: Der 31.3. ist in diesem Jahr der letzte Sonntag im März und deshalb wegen der Umstellung auf die Sommerzeit nur 23 Stunden lang. Diesen Sonderfall hatte ich nicht berücksichtigt.
        Solche Sonderfälle hast Du immer an der Backe, wenn Du Datumsberechnungen über die Sekunden machst.

        nicht notwendigerweise: Wenn man schön in UTC bleibt, passt alles.

        Ciao,
         Martin

        --
        Ich habe gerade erfahren, dass Tante Frieda gestorben ist. Der Tod hat sie im Schlaf ereilt. - Schrecklich. Dann weiß sie es also noch gar nicht?
        Selfcode: fo:) ch:{ rl:| br:< n4:( ie:| mo:| va:) de:] zu:) fl:{ ss:) ls:µ js:(
        1. gudn tach!

          Solche Sonderfälle hast Du immer an der Backe, wenn Du Datumsberechnungen über die Sekunden machst.

          nicht notwendigerweise: Wenn man schön in UTC bleibt, passt alles.

          allgemein koennen einem dann aber z.b. bei datumsberechnung schaltjahre noch probleme bereiten. heutzutage sollte man solche berechnungen in der regel von fertigen, getesteten modulen erledigen lassen und nicht raeder neu-erfinden.

          prost
          seth

  2. gudn tach!

    Ich ermittle so den letzten Tag eines Monats[...]:

    use Time::Local;
      $jahr=2013;
      $monat=3; #Januar=1, Februar=2, ...
      $tagessekunden=24*60*60; [...]

    da gibt's besseres:

    #!/usr/bin/perl  
    use strict;  
    use warnings;  
    use DateTime;  
      
    my $date = DateTime->new(  
    	year  => 2013,  
    	month => 3,  
    	day   => 1,  
    );  
    $date->add('months'=>1)->subtract('days'=>1);  
    print $date->day,"\n";  
    
    

    prost
    seth

    1. gudn tach!

      da gibt's besseres: [...]

      aeh, und das geht sogar noch praegnanter und einfacher:

      #!/usr/bin/perl  
      use strict;  
      use warnings;  
      use DateTime;  
        
      print DateTime->last_day_of_month(  
      	year  => 2013,  
      	month => 3,  
      )->day,"\n";  
      
      

      prost
      seth

    2. Tach!

      $date->add('months'=>1)->subtract('days'=>1);

      Gibt es in Perl nichts, das die Anzahl der Tage eines Monats ermitteln kann? Würde mich sehr wundern. Auch das Fehlen des Äquivalents zu PHPs strtotime('last day of 2013-03-04'), würde ich nicht erwarten, zumal das ja auch nur ein Durchreicher an C's asctime() ist.

      dedlfix.