2009-09-02 2 views

risposta

10

Date::Calc è il modulo campione qui:

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

Il modulo ha un numero enorme di routine di conversione tempo, in particolare quelli che riguardano delta. DateTime e Date::Manip vale anche la pena di verificare.

1

Vedere perldoc POSIX per la funzione mktime().

Ti aiuterà a convertire date e ore in un numero semplice, che è l'ora di Unix (il numero di secondi dal 1 ° gennaio 1970, credo). Quindi, basta sottrarre 3 (giorni) volte 24 (ore in un giorno) volte 60 (minuti in un'ora) volte 60 (secondi in un minuto) o 259200 secondi da quel numero e utilizzare localtime() per convertire quel numero di secondi indietro a una rappresentazione di stringa.

Questa è probabilmente la soluzione migliore *, poiché gestirà automaticamente le modifiche di mese e anno. Qualsiasi altra soluzione probabilmente finirà per essere più complicata dopo il factoring nel verificare se abbiamo finito i giorni in un mese, o finito i mesi in un anno.


EDIT: * Al di fuori di guardare su CPAN.

+2

Se avete intenzione di fare questo, ho suggerirei di usare un tempo a metà giornata come input per mktime, piuttosto che sec, min, hour = 0 per evitare qualsiasi possibilità di problema con l'ora legale, il balzo dei secondi ecc., quindi butta via il componente orario da locale – Cebjyre

+2

Probabilmente è meglio usare Date :: Calc o comunque qualche altro modulo CPAN, semplicemente non ho la conoscenza del livello Guru di un vero maestro Perl. . –

+1

Ciò non riuscirà in alcune situazioni. Tutti pensano che sia un problema semplice, ma non hanno mai veramente preso in considerazione ciò che serve per farlo bene. –

9

Date::Calc può essere utilizzato per i calcoli:

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

Ci sono così tante opzioni che è moderatamente imbarazzante. Dipende in parte da quali altri calcoli potresti aver bisogno in futuro, e se i tempi ei fusi orari saranno sempre un fattore, e cose simili.

Si potrebbe guardare in qualsiasi di questi

per nominare solo tre (serie di) moduli. Suggerirei Date::Calc o Date::Manip per semplicità - ma se hai bisogno di essere fantasioso in futuro, i moduli DateTime potrebbero essere migliori.

+0

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

+0

@Brad: grazie per le correzioni sugli URL. –

0

La cosa bella di mktime è che gestirà qualsiasi momento di offset. Usa gennaio = 0; e Anno 2009 = 109 in questo schema. Così, stampati mese - 1 e dell'anno - 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 è utile per trovare l'ultimo giorno del mese pure. Vai al giorno 0 del mese successivo.

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

questo è semplice con Date::Simple

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

È possibile aggiornare la risposta per mostrare come convertire la stringa "2009-09-04" alla risposta "2009-09-01"; cioè, invece di usare 'today()', come si converte una data stringa nel formato interno? –

+0

C: \> perl -MDate :: Semplice = data -e "data di stampa ('2009-09-04') - 3" 2009-09-01 –

6

DateTime è il modo canonico per trattare con le date in Perl moderno:

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)