2012-08-29 21 views
5

Me preguntaba si existe una función Perl incorporada que ajuste la fecha si le toma un mes. P.ej. si la fecha es el día 31, se ajustará para ser el final del mes anterior si no tiene 31 días.¿Cómo remontar meses en Perl teniendo en cuenta los diferentes días del mes?

Lo cambiaría simplemente a 30º fácilmente si no fuera por los meses con 31 días juntos (diciembre/enero, julio/agosto) y febrero. Solo quiero guardar la fecha una cierta cantidad de tiempo fuera de la fecha actual, p.

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

puedo lidiar con la instancia de febrero, ya que sólo se aplica a año, pero si esto fue tomada el 31 de Diciembre 2012 y luego quitándole un mes significaría 31a Nov 2012, que por supuesto no existía. Pensé que iba a preguntar si había una función antes de complicar las cosas por mí mismo ... gracias :)

+2

[DateTime] (https://metacpan.org/module/DateTime) ¿Quizás busques este módulo? (tiene fecha 'matemática) – gaussblurinc

+0

¡Ambas respuestas a continuación son buenas! Date Time parece ser una opción realmente útil, pero como quiero usarlo para una pequeña parte de mi código, creo que podría lanzarme y hacer un montón de cláusulas para ello. Largo aliento, pero me ayudará a aprender ... este es mi primer día usando Perl: P ¡Gracias por su ayuda! – dgBP

Respuesta

8

Otros han sugerido DateTime, pero es bastante grande no básicos, y pueden ser lentos.

Una solución mucho más simple es utilizar la orden interna localtime y POSIX::mktime funciones:

use POSIX qw(mktime); 

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

La función mktime() manijas específicamente valores desnormalizaremos; hará frente al hecho de que Janurary menos 2 meses es noviembre del año anterior, etc. Mantendrá el mismo segundo/minuto/hora del día, y el mismo día del mes.

+0

Esto se ve muy bien, pero no puedo conseguir que imprima la cifra de $ two_months_ago, ya que dice que no está inicializada (luego la inicialicé sin cambios). – dgBP

+0

Funciona para mí: http://pastie.org/4610603 – LeoNerd

+0

con ese otro código que sí lo hace! Tengo que decir que esa es una versión mejor que estaba buscando :) felicitaciones – dgBP

10

DateTime no es un módulo incorporado, pero una vez que lo hayas instalado, lo que hace que este matemáticas triviales:

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

Cuando ejecuto esto hoy (29 Ago de 2012) me da el siguiente resultado:

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

Honestamente, si pudiera dar dos mejores respuestas, lo haría, pero tiene un poco más de información :) ¡gracias! Nunca he visto la función de decir, ¡eso es útil para saber! – dgBP

+0

Esta función depende de la versión de Perl. Debe ser> = 5.10 –

7

Si usted tiene la oportunidad de instalar el módulo DateTime. Te da muchas ventajas cuando tienes un acuerdo con las fechas.

use strict; 
use DateTime; 

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

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

bueno, gracias! :) – dgBP

Cuestiones relacionadas