2012-03-30 31 views
9

¿Hay alguna forma de averiguar el primer día del mes (día mínimo) y el último día de un mes (día máximo), dado el mes como entrada, usando DateTime en perl?¿Cómo puedo obtener el primer y último día del mes con DateTime de Perl?

Hasta ahora, he descubierto cómo pasar una primera fecha, la última fecha para darme un rango de días.

Pero lo que quiero hacer ahora es simplemente pasar en un mes como argumento, digamos 201203 y devolver min, maxday.

¿Es posible con DateTime?

Además, deseo cambiar la máscara de formato de fecha de YYYYMMDD a AAAA-MM-DD.

use strict; 
    use warnings; 
    use DateTime; 

    unless(@ARGV==2) 
    { 
     print "Usage: myperlscript first_date last_date\n"; 
     exit(1); 
    } 

    my ($first_date,$last_date)[email protected]; 

    my $date=DateTime->new(
    { 
     year=>substr($first_date,0,4), 
     month=>substr($first_date,4,2), 
     day=>substr($first_date,6,2) 
    }); 


while($date->ymd('') le $last_date) 
{ 
    print $date->ymd('') . "\n"; 
    #$date->add(days=>1); #every day 
    $date->add(days=>30); 
} 

Resultados esperados:

2012-03-01 
2012-03-31 
+3

¡El día mínimo es siempre 1! – theglauber

Respuesta

14

DateTime hace fecha de cálculos por usted. Se puede decir que ymd el carácter que desea utilizar como separador:

use DateTime; 

my($year, $month) = qw(2012 2); 

my $date = DateTime->new(
    year => $year, 
    month => $month, 
    day => 1, 
); 

my $date2 = $date->clone; 

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

say $date->ymd('-'); 
say $date2->ymd('-'); 

Hay muchos ejemplos en "Last day of the month. Any shorter" en Perlmonks, que he encontrado buscando en Google "perl datetime last day of month".


Y aquí hay un ejemplo de Time::Moment. Es un subconjunto más delgado más rápido del Tiempo:

use v5.10; 
use Time::Moment; 

my($year, $month) = qw(2012 2); 

my $tm = Time::Moment->new(
    year => $year, 
    month => $month, 
    day => 1, 
); 

my $tm2 = $tm->plus_months(1)->minus_days(1); 

say $tm->strftime('%Y-%m-%d'); 
say $tm2->strftime('%Y-%m-%d'); 
6

Primer día:

$dt->set_day(1); 

Último día:

$dt->set_day(1)->add(months => 1)->subtract(days => 1); 
+8

No olvides llamar 'clone' si quieres evitar cambiar' $ dt'. – ikegami

8

Como alternativa existe el núcleo módulo de Perl Time::Piece.

Para el mes y el año en curso:

perl -MTime::Piece -wE '$t=localtime;say $t->month_last_day' 
31 

De manera más general, algo así como:

use 5.010; 
use Time::Piece; 
my $MY = shift || die "Month and Year expected\n"; 
my $t = Time::Piece->strptime($MY, "%m%Y"); 
say $t->month_last_day; 

$ ./mycode 022012 
29 
9

Es sorprendente, que ni DateTime ejemplo se utiliza el constructor especial last_day_of_month para que (ejemplo cortesía de Brian D Foy):

use DateTime; 
use strict; 
use 5.010; 

my($year, $month) = qw(2012 2); 

my $date = DateTime->new(
    year => $year, 
    month => $month, 
    day => 1, 
); 

my $date2 = DateTime->last_day_of_month( 
    year => $date->year, 
    month => $date->month, 
); 

say $date->ymd('-'); 
say $date2->ymd('-'); 
0

Mientras que el DateTime class ofrece un constructor para hacer esto, la manera más eficiente de obtener el último día del mes de un objeto DateTime existente es solicitar que el objeto lo calcule. La clase expone un método no documentado _month_length() que calcula el último día del mes de manera muy eficiente. Con el objeto DateTime denominado $ fecha, puede intentar

$date->_month_length($date->year,$date->month); 

es indocumentado Este método, por lo que puede o no puede estar avalado en su versión de DateTime. Usar con precaución.

Cuestiones relacionadas