2012-08-29 3 views
5

Ich frage mich, ob es eine eingebaute Perl-Funktion gibt, die das Datum anpasst, wenn Sie einen Monat davon brauchen. Z.B. Wenn das Datum der 31. ist, wird es an das Ende des vorherigen Monats angepasst, wenn es keine 31 Tage hat.Wie Monate in Perl unter Berücksichtigung der verschiedenen Tage im Monat zurückgehen?

Ich würde es einfach auf 30 ändern, wenn es nicht für die Monate mit 31 Tagen nebeneinander (Dez/Jan, Jul/Aug) und Februar wäre. Ich möchte nur das Datum eine bestimmte Zeit von dem aktuellen Datum, z.

my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time); 

$current_date = join("-", (1900+$year), ($mon+1), $mday); 
$one_month_ago = join("-", (1900+$year), ($mon), $mday); 
$one_year_ago = join("-", (1899+$year), ($mon+1), $mday); 

ich mit der Februar-Instanz umgehen können, da es nur auf die Jahre gilt, aber wenn dies im Monat am 31. Dezember 2012 dann 2012, die natürlich 31. November gab es nicht bedeuten würde, Wegnehmen genommen wurde. Ich dachte, ich würde fragen, ob es eine Funktion war, bevor die Dinge für mich zu verkomplizieren ... danke :)

+2

[DateTime] (https://metacpan.org/module/DateTime) vielleicht suchen Sie dieses Modul? (es hat Datum 'Mathe) – gaussblurinc

+0

Beide Antworten unten gut! Date Time sieht wie eine wirklich nützliche Option aus, aber da ich es für einen kleinen Teil meines Codes verwenden möchte, denke ich, dass ich einfach einsteigen und eine Reihe von Klauseln dafür machen könnte. Lange wehend, aber es wird mir helfen zu lernen ... das ist mein erster Tag mit Perl: P Danke für Ihre Hilfe! – dgBP

Antwort

8

Andere haben DateTime vorgeschlagen, aber es ist recht groß, Nicht-Kern, und langsam sein kann.

Eine einfachere Lösung ist die eingebauten localtime und POSIX::mktime Funktionen zu verwenden:

use POSIX qw(mktime); 

my @t = localtime $epoch; 
$t[4] -= 2; # $t[4] is tm_mon 
my $two_months_ago = mktime @t; 

Die mktime() Funktion denormalised Werte speziell behandelt; es wird mit der Tatsache fertig werden, dass Januar minus 2 Monate November des vorherigen Jahres usw. ist. Es wird die gleiche Sekunde/Minute/Stunde des Tages, und derselbe Tag des Monats behalten.

+0

Das sieht sehr gut aus, aber ich kann es nicht bekommen, um die $ zwei_months_ago-Zahl auszudrucken, da es sagt, dass es nicht initialisiert ist (ich initialisierte es dann ohne Änderung). – dgBP

+0

Funktioniert für mich: http://pastie.org/4610603 – LeoNerd

+0

mit dem anderen Code tut es tatsächlich! Ich muss sagen, dass das eine bessere Version ist, nach der ich gesucht habe :) kudos – dgBP

10

Datetime ist kein eingebautes Modul, aber wenn Sie es installiert haben, macht es diese Mathe trivial:

#!/usr/bin/perl 
use strict; 
use warnings; 

use feature qw(say); 
use DateTime; 

my $dt = DateTime->now; 
say $dt->ymd; 

$dt->truncate(to => month); 

say $dt->ymd; 

$dt->add(days => -1); 
say $dt->ymd; 

foreach (1 .. 12) { 
    $dt->add(months => -1); 
    say $dt->ymd; 
} 

Wenn ich laufen diese heute (29. August 2012) bekomme ich folgende Ausgabe:

[~] $ perl dt.pl 
2012-08-29 
2012-08-01 
2012-07-31 
2012-06-30 
2012-05-31 
2012-04-30 
2012-03-31 
2012-02-29 
2012-01-31 
2011-12-31 
2011-11-30 
2011-10-31 
2011-09-30 
2011-08-31 
2011-07-31 
+0

Ehrlich, wenn ich zwei beste Antworten geben könnte, würde ich, aber Sie haben ein bisschen mehr Informationen :) Danke! Ich habe noch nie die sagen-Funktion gesehen - das ist nützlich zu wissen! – dgBP

+0

Diese Funktion hängt von der Perl-Version ab. Es sollte> = 5.10 sein –

7

Wenn Sie eine Chance haben DateTime zu installieren Modul. Es gibt Ihnen viele Vorteile, wenn Sie mit Daten fertig sind.

use strict; 
use DateTime; 

my $epoch = ...; 
my $dt = DateTime->from_epoch(epoch => $epoch); 
$dt->subract(months => 1); 

printf "%s", $dt->datetime(); 
+0

gut, danke! :) – dgBP

Verwandte Themen