2009-09-02 19 views

Respuesta

10

Date::Calc es el módulo de campeón aquí:

use strict; 
use warnings; 
use Date::Calc qw(Add_Delta_YMD); 

my $startDate = '2000-01-01'; 
my ($startYear, $startMonth, $startDay) = $startDate =~ m/(\d{4}-(\d{2})-\d{2})/; 

# 1 year, 2 months, 3 days, after startDate 
my $endDate = join('-', Add_Delta_YMD($startYear, $startMonth, $startDay, 1, 2, 3)); 

El módulo dispone de un gran número de rutinas de conversión de tiempo, en particular los relacionados con los deltas. DateTime y Date::Manip también vale la pena echarle un vistazo.

1

Consulte perldoc POSIX para la función mktime().

Te ayudará a convertir fechas y horas a un número simple, que es el tiempo de Unix (el número de segundos desde el 1 de enero de 1970, creo). Luego, solo resta 3 (días) por 24 (horas en un día) por 60 (minutos en una hora) por 60 (segundos en un minuto), o 259200 segundos desde ese número, y usa localtime() para convertir esa cantidad de segundos a una representación de cadena.

Esta es probablemente la mejor solución *, ya que manejará los cambios de mes y año automáticamente. Cualquier otra solución probablemente será más complicada luego de tener en cuenta el verificar si nos quedamos sin días en un mes, o si nos quedamos sin meses en un año.


EDIT: * Fuera de mirar en CPAN.

+2

Si va a hacer esto, sugeriría utilizar un tiempo en el medio del día como entrada a mktime, en lugar de sec, min, hour = 0 para evitar cualquier posibilidad de problema con horario de verano, segundos interminables, etc., y luego descartar el componente de hora del tiempo local – Cebjyre

+2

Probablemente sea mejor utilizar Date :: Calc o algún otro módulo de CPAN de todos modos, simplemente no tengo el conocimiento de CPAN a nivel de gurú de un verdadero maestro de Perl . –

+1

Esto fallará en algunas situaciones. Todos piensan que es un problema simple, pero nunca han considerado realmente lo que se necesita para hacerlo bien. –

9

Date::Calc puede ser utilizado para estos cálculos:

#!/usr/bin/perl 

use strict; 
use warnings; 
use Date::Calc qw(Add_Delta_Days); 

my ($yyyy, $mm, $dd) = (2009, 9, 2); 
my @date = Add_Delta_Days($yyyy, $mm, $dd, -3); 
print join('-', @date); 
4

Hay tantas opciones que es moderadamente embarazoso. Depende en parte de qué otros cálculos pueda necesitar en el futuro, y si las horas y las zonas horarias alguna vez serán un factor, y cosas similares.

Se podría buscar en cualquiera de estos

para nombrar solo tres (conjuntos de) módulos. Sugeriría Date::Calc o Date::Manip por simplicidad, pero si va a necesitar ser elegante en el futuro, los módulos DateTime pueden ser mejores.

+0

http://stackoverflow.com/revisions/bd3f965e-1edb-47b2-bbd0-b4149fd5af18/view-source –

+0

@Brad: gracias por las correcciones en las URL. –

0

Lo bueno de mktime es que se manejará en cualquier momento de la compensación. Utiliza enero = 0; y Año 2009 = 109 en este esquema. Por lo tanto, impreso meses - 1 y el año completo - 1900.

use POSIX qw<mktime>; 

my ($year, $month, $day) = split '-', $date; 
my $three_day_prior = mktime(0, 0, 0, $day - 3, $month - 1, $year - 1900); 

mktime es útil para encontrar el último día del mes también. Solo ve al día 0 del mes siguiente.

mktime(0, 0, 0, 0, $month, $year - 1900); 
0

Esto es sencillo con Date::Simple

C:\>perl -MDate::Simple=today -e "print today()-3" 
 
2009-08-30 
+0

Puede actualizar su respuesta para mostrar cómo convertir la cadena '2009-09-04' a la respuesta '2009-09-01'; es decir, en lugar de usar 'today()', ¿cómo convertir una cadena dada al formato interno? –

+0

C: \> perl -MDate :: Simple = date -e "fecha de impresión ('2009-09-04') - 3" 2009-09-01 –

6

DateTime es la forma canónica para hacer frente a las fechas en Perl moderna:

use DateTime; 

my ($year, $month, $day) = split '-', '2009-09-01'; 

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

$date->subtract(days => 3); 

# $date is now three days earlier (2009-08-29T00:00:00) 
Cuestiones relacionadas