2009-11-29 11 views
54

Al escribir scripts de Perl con frecuencia encuentro la necesidad de obtener la hora actual representado como una cadena con formato de YYYY-mm-dd HH:MM:SS (digamos 2009-11-29 14:28:29).llegar rápidamente a AAAA-MM-DD HH: MM: SS en Perl

Al hacer esto, me encuentro tomando este camino bastante engorroso:

  • man perlfunc
  • /localtime para buscar localtime - Repetir cinco veces (/ + \n) para llegar a la sección correspondiente de la página de manual
  • Copie la cadena ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time); de la página de manual a mi script.
  • Probar con my $now = sprintf("%04d-%02d-%02d %02d:%02d:%02d", $year, $mon, $mday, $hour, $min, $sec);
  • Recuerde gotcha # 1: Debe agregar 1900 a $ year para obtener el año actual.
  • Probar con my $now = sprintf("%04d-%02d-%02d %02d:%02d:%02d", $year+1900, $mon, $mday, $hour, $min, $sec);
  • Recuerde gotcha # 2: Debe agregar 1 a $ mon para obtener el mes actual.
  • Probar con my $now = sprintf("%04d-%02d-%02d %02d:%02d:%02d", $year+1900, $mon+1, $mday, $hour, $min, $sec);
  • Parece correcto. ¡Hecho!

Mientras que el proceso descrito anteriormente funciona está lejos de ser óptima. Estoy seguro de que hay una manera más inteligente, así que mi pregunta es simple:

¿Cuál es la forma más fácil de obtener un YYYY-mm-dd HH:MM:SS de la fecha/hora actual en Perl?

Donde "fácil" abarca tanto "fácil de escribir" como "fácil de recordar".

+0

Usted ¡debería haber escrito una subrutina para buscar el perlfunc y recordar los errores para usted, por supuesto! – AmbroseChapel

Respuesta

64

Uso strftime en el módulo estándar POSIX:

$ perl -MPOSIX -le 'print strftime "%F %T", localtime $^T' 

Los argumentos a strftime en Perl de unión fueron diseñados para alinearse con los valores de retorno de localtime y gmtime.

+13

Gracias. Y en un formato que no es de una sola línea: use POSIX; print strftime ("% Y-% m-% d% H:% M:% S \ n", hora loca (hora)); – Mike

+0

También hay tiempo de ejecución en Time :: Piece (núcleo desde 5.10) que le permite usar una forma más orientada a objetos (vea mi respuesta a continuación). Además, $^T (tiempo desde el inicio del programa) no es lo que desea. – MkV

+3

usando 5.20.2 en Windows, tanto '% F' como'% T' no son compatibles.Necesito especificar el formato entero '% Y-% m-% d% H:% M:% S' – Seki

30

¿Qué no utiliza el módulo DateTime para hacer el trabajo sucio por usted? ¡Es fácil escribir y recordar!

use strict; 
use warnings; 
use DateTime; 

my $dt = DateTime->now; # Stores current date and time as datetime object 
my $date = $dt->ymd; # Retrieves date as a string in 'yyyy-mm-dd' format 
my $time = $dt->hms; # Retrieves time as a string in 'hh:mm:ss' format 

my $wanted = "$date $time"; # creates 'yyyy-mm-dd hh:mm:ss' string 
print $wanted; 

Una vez que sepa lo que está pasando, usted puede deshacerse de las temperaturas y guardar unas pocas líneas de código:

use strict; 
use warnings; 
use DateTime; 

my $dt = DateTime->now; 
print join ' ', $dt->ymd, $dt->hms; 
+3

'$ var-> method' está * no * interpolado en una cadena. '" $ {\ $ var-> method} "' o '" @ {[$ var-> method]} "' si realmente quieres alinearlo, pero eso es feo. Simplemente escriba 'join $', $ dt-> ymd, $ dt-> hms' o algo así. – ephemient

+2

@ephemient: debidamente actualizado. Gracias por la información. – Zaid

28

Prueba esto:

use POSIX qw/strftime/; 
print strftime('%Y-%m-%d',localtime); 

el método strftime hace el trabajo efectivamente para mi. Muy simple y eficiente.


13

Time::Piece (en el núcleo desde Perl 5.10) también tiene una función strftime y por defecto sobrecargas localtime y gmtime a devolver los objetos Tiempo :: Piece:

use Time::Piece; 
print localtime->strftime('%Y-%m-%d'); 

o sin la hora local reemplazado:

+1

+1 por la mención de un módulo principal y el uso - dado que la gran cantidad de módulos disponibles es una de las principales razones por la que la mayoría de nosotros usamos Perl en primer lugar – osirisgothra

2

Time::Piece::datetime() puede eliminar T.

use Time::Piece; 
print localtime->datetime(T => q{ }); 
+0

, otra mención de Time :: Piece debería hacer que lo recuerde ahora; no es exactamente el módulo más fácil de recordar si no se usa diariamente :) – osirisgothra

3

si lo que desea es una cadena legible tiempo y no ese formato exacto:

$t = localtime; 
print "$t\n"; 

impresiones

Mon Apr 27 10:16:19 2015 

o lo que está configurado para su ubicación.

3

I hizo una pequeña prueba (Perl v5.20.1 bajo FreeBSD en VM) llamando a los siguientes bloques de 1.000.000 veces cada uno:

A

my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time); 
my $now = sprintf("%04d-%02d-%02d %02d:%02d:%02d", $year+1900, $mon+1, $mday, $hour, $min, $sec); 

B

my $now = strftime('%Y%m%d%H%M%S',localtime); 

C

my $now = Time::Piece::localtime->strftime('%Y%m%d%H%M%S'); 

con los siguientes resultados:

A: 2 segundos

B: 11 segundos

C: 19 segundos

Esto es por supuesto no una prueba completa o punto de referencia, pero al menos es reproducible para mí, así que, aunque es más complicado, preferiría el primer método si se requiere generar una marca de fecha y hora con mucha frecuencia.

de llamada (por ejemplo. En FreeBSD 10,1)

my $now = `date "+%Y%m%d%H%M%S" | tr -d "\n"`; 

podría no ser una buena idea porque no es independiente del sistema operativo y toma bastante tiempo.

Saludos, Holger

0

corto y dulce, no hay módulos adicionales necesarios:

my $toDate = `date +%m/%d/%Y" "%l:%M:%S" "%p`; 

de salida, por ejemplo, sería: 25/04/2017 09:30:33 AM

Cuestiones relacionadas