2010-08-17 17 views
12

¿Cómo modifico esto para obtener la fecha de ayer usando localtime?¿Cómo obtengo la fecha de ayer usando localtime?

use strict; 

sub spGetCurrentDateTime; 
print spGetCurrentDateTime; 

sub spGetCurrentDateTime { 
my ($sec, $min, $hour, $mday, $mon, $year) = localtime(); 
my @abbr = qw(Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec); 
my $currentDateTime = sprintf "%s %02d %4d", $abbr[$mon], $mday, $year+1900; #Returns => 'Aug 17 2010' 
return $currentDateTime; 
} 

~

Respuesta

11

El problema DST se puede evitar mediante la adopción de 3600s a partir del mediodía de hoy en lugar de la hora actual:

#!/usr/bin/perl 
use strict; 
use warnings; 
use Time::Local; 

sub spGetYesterdaysDate; 
print spGetYesterdaysDate; 

sub spGetYesterdaysDate { 
my ($sec, $min, $hour, $mday, $mon, $year) = localtime(); 
my $yesterday_midday=timelocal(0,0,12,$mday,$mon,$year) - 24*60*60; 
($sec, $min, $hour, $mday, $mon, $year) = localtime($yesterday_midday); 
my @abbr = qw(Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec); 
my $YesterdaysDate = sprintf "%s %02d %4d", $abbr[$mon], $mday, $year+1900; 
return $YesterdaysDate; 
} 

A la luz del comportamiento "no especificado" documentada de la solución strftime sugerido por Chas, este enfoque podría ser mejor si no puede probar los resultados esperados pero no garantizados en múltiples plataformas.

+0

gracias. esto funciona bien con mi rutina existente. – jdamae

1
localtime(time() - 24*60*60) 
+5

Hay una carcasa de borde alrededor de DST. No aconsejo este método si necesita que esto funcione todo el tiempo. –

+3

Votar como se indica arriba. No es una buena respuesta. – daxim

+0

La carcasa de borde DST se puede "solucionar", vea el código de muestra en otra respuesta. – bigiain

6

uso Time::Piece.

use strict; 
use warnings; 
use 5.010; 

# These are core modules in Perl 5.10 and newer 
use Time::Piece; 
use Time::Seconds; 

my $yesterday = localtime() - ONE_DAY; 
say $yesterday->strftime('%b %d %Y'); 

Tenga en cuenta que esto puede fallar en algunos casos límite, como el inicio del horario de verano. La siguiente versión se comporta correcta en estos casos:

use strict; 
use warnings; 
use 5.010; 

# These are core modules in Perl 5.10 and newer 
use Time::Piece; 
use Time::Seconds; 

my $now = localtime(); 
my $yesterday = $now - ONE_HOUR*($now->hour + 12); 
say $yesterday->strftime('%b %d %Y'); 

Alternativamente, se puede utilizar el módulo DateTime como se describe en una respuesta diferente. Sin embargo, ese no es un módulo básico.

+0

El mismo problema de DST se oculta bajo la elegante API. – daxim

+0

Buen punto, daxim. He agregado una versión que no tiene este problema. – mscha

+2

'Time :: Piece' y' Time :: Seconds' no se agregaron al núcleo hasta Perl 5.10 (bien 5.9.5, pero ¿quién usa dev releases?). –

20
use DateTime qw(); 
DateTime->now->subtract(days => 1); 

La expresión en la segunda línea devuelve un objeto DateTime.

+0

No funciona correctamente para la zona horaria de Asia/Kolkata. – user774250

+1

Funciona, acabo de probar. Tal vez simplemente te olvidaste de configurar el atributo 'time_zone' en el constructor, o descuidaste llamar al método [' set_time_zone'] (http://p3rl.org/DateTime#dt-set_time_zone-tz-)? Tal vez tiene una versión obsoleta de la distribución ['DateTime :: TimeZone'] (https://metacpan.org/release/DateTime-TimeZone)? – daxim

18

Por muy tentador que sea restar el valor de segundos de un día de la hora actual, hay momentos en los que esto dará la respuesta incorrecta (segundos intercalares, horario de verano y posiblemente otros). Me resulta más fácil simplemente dejar que strftime (disponible en el módulo central Perl 5 POSIX) se encargue de todo eso por mí.

#!/usr/bin/perl 

use strict; 
use warnings; 

use Time::Local; 
use POSIX qw/strftime/; 

#2010-03-15 02:00:00 
my ($s, $min, $h, $d, $m, $y) = (0, 0, 0, 15, 2, 110); 

my $time  = timelocal $s, $min, $h, $d, $m, $y;  
my $today  = strftime "%Y-%m-%d %T", localtime $time; 
my $yesterday = strftime "%Y-%m-%d %T", $s, $min, $h, $d - 1, $m, $y; 
my $oops  = strftime "%Y-%m-%d %T", localtime $time - 24*60*60; 
print "$today -> $yesterday -> $oops\n"; 
+0

Entonces, si el valor 'día' es menor que 1 'strftime' cuenta hacia atrás el día + 1 día del mes anterior (y posiblemente el año). ¿Es este comportamiento una parte documentada de POSIX o es específico de la plataforma? –

+1

@Grant Mclean Puede no ser estándar en POSIX (o SUS), pero es estándar en Perl 5. La documentación dice 'los argumentos se hacen constantes como si llamaran a" mktime() "antes de llamar al" strftime() "de su sistema '. –

+1

Como un trazador de líneas: 'perl -MPOSIX -le '@ t = tiempo local; - $ t [3]; imprimir tiempo de trama"% Y% m% d ", @ t'' – theglauber

4

¡La solución sugerida por la mayoría de los usuarios es incorrecta!

localtime(time() - 24*60*60) 

Lo peor que puede hacer es asumir que 1 día = 86400 segundos.

Ejemplo: nos Zona horaria es América/New_York, la fecha es Lun Abr 3 00:30:00 2006

timelocal da

hora local (1144038600 - 86400) = Sab Abr 1 23:30:00 EST 2006

¡Uy!

El derecho y la única solución es dejar que valora la función del sistema normalizar

$prev_day = timelocal(0, 0, 0, $mday-1, $mon, $year); 

O dejar que los marcos de fecha y hora (DateTime, Class::Date, etc) hagan lo mismo.

Eso es todo.

-1
This is how I do it. 

#!/usr/bin/perl 

use POSIX qw(strftime); 

$epoc = time(); 
$epoc = $epoc - 24 * 60 * 60; 

$datestring = strftime "%F", localtime($epoc); 

print "Yesterday's date is $datestring \n"; 
+0

Esto puede fallar alrededor del comienzo del horario de verano por los motivos explicados en otras respuestas. –

Cuestiones relacionadas