2012-08-29 12 views
5

Mi chiedevo se esiste una funzione Perl incorporata che regola la data se ci si prende un mese da essa. Per esempio. se la data è il 31, si regolerà per essere la fine del mese precedente se non ha 31 giorni.Come tornare indietro di mesi in Perl tenendo conto di diversi giorni nel mese?

Vorrei solo cambiarlo facilmente al 30 ° se non fosse stato per i mesi con 31 giorni l'uno accanto all'altro (Dic/Jan, Jul/Aug) e febbraio. Voglio solo memorizzare la data una certa quantità di tempo lontano dalla data corrente, ad es.

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

posso affrontare l'istanza di febbraio come si applica solo per anni, ma se questo è stata presa il 31 DICEMBRE 2012 poi togliendo un mese significherebbe 31 novembre 2012, che ovviamente non esisteva. Ho pensato di chiedere se c'era una funzione prima di complicare le cose per me ... grazie :)

+2

[DateTime] (https://metacpan.org/module/DateTime) forse si cerca questo modulo? (ha data 'matematica) – gaussblurinc

+0

Entrambe le risposte sono al di sotto del buono! Data Ora sembra un'opzione davvero utile, ma siccome voglio usarlo per una piccola parte del mio codice penso che potrei semplicemente tuffarmi e fare un sacco di clausole per questo. Lungo tempo, ma mi aiuterà a imparare ... questo è il mio primo giorno con Perl: P Grazie per il tuo aiuto! – dgBP

risposta

8

Altri hanno suggerito DateTime, ma è abbastanza grande, non-core, e può essere lento.

Una soluzione molto più semplice è quello di utilizzare la funzione interna localtime e POSIX::mktime funzioni:

use POSIX qw(mktime); 

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

La funzione mktime() maniglie specificamente valori denormalizzati; farà fronte al fatto che Janurary meno 2 mesi è novembre dell'anno precedente, ecc. Conserverà lo stesso secondo/minuto/ora del giorno e lo stesso giorno del mese.

+0

Questo sembra molto buono, ma non riesco a farlo stampare la cifra $ two_months_ago perché dice che non è inizializzata (l'ho quindi inizializzata senza modifiche). – dgBP

+0

Lavora per me: http://pastie.org/4610603 – LeoNerd

+0

con quell'altro codice lo fa davvero! Devo dire che questa è una versione migliore che stavo cercando :) kudos – dgBP

10

DateTime non è un modulo predefinito, ma una volta installato, rende banale questo calcolo:

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

Quando ho eseguito questo oggi (29 ago 2012) ottengo il seguente output:

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

Onestamente, se potessi dare due risposte migliori lo farei, ma hai qualche informazione in più :) grazie! Non ho mai visto la funzione di dire - che è utile sapere! – dgBP

+0

Questa funzione dipende dalla versione di Perl. Dovrebbe essere> = 5.10 –

7

Se avete la possibilità di installare il modulo DateTime. Ti dà un sacco di vantaggi, quando hai a che fare con le date.

use strict; 
use DateTime; 

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

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

bene, grazie! :) – dgBP

Problemi correlati