5 votes

Comment remonter les mois en Perl en tenant compte des différents jours du mois ?

Je me demandais s'il existe une fonction Perl intégrée qui ajuste la date si l'on enlève un mois. Par exemple, si la date est le 31, elle sera ajustée à la fin du mois précédent si celui-ci ne compte pas 31 jours.

Je passerais facilement au 30e si ce n'était pour les mois avec 31 jours côte à côte (décembre/janv., juillet/août) et février. Je veux juste stocker la date à une certaine distance de la date actuelle, par exemple.

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);

Je peux m'occuper de l'exemple de février car il ne s'applique qu'aux années, mais s'il avait été pris le 31 décembre 2012, le fait d'enlever un mois signifierait le 31 novembre 2012, qui n'existait évidemment pas. Je pensais demander s'il existait une fonction avant de me compliquer la vie... merci :)

10voto

oalders Points 1861

DateTime n'est pas un module intégré, mais une fois que vous l'avez installé, il rend ces calculs triviaux :

#!/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;
} 

Lorsque je l'exécute aujourd'hui (29 août 2012), j'obtiens le résultat suivant :

[~] $ 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

9voto

LeoNerd Points 3940

D'autres ont suggéré DateTime mais il est assez gros, non essentiel, et peut être lent.

Une solution beaucoup plus simple consiste à utiliser la fonction intégrée localtime et POSIX::mktime fonctions :

use POSIX qw( mktime );

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

Le site mktime() gère spécifiquement les valeurs dénormalisées ; elle s'occupera du fait que janvier moins 2 mois est novembre de l'année précédente, etc. Elle gardera la même seconde/minute/heure du jour, et le même jour du mois.

8voto

Pavel Vlasov Points 2699

Si vous avez l'occasion d'installer le module DateTime . Cela vous donne beaucoup d'avantages, lorsque vous avez affaire à des dates.

use strict;
use DateTime;

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

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

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X