Pregunta

Los registros de log4j que tengo contienen marcas de tiempo en el siguiente formato:

2009-05-10 00:48:41,905

Necesito convertirlo en perl a milisegundos desde la época, que en este caso sería 124189673005 , utilizando la siguiente función gawk. ¿Cómo lo hago en perl?

Tengo poca o ninguna experiencia en perl, así que agradezco si alguien puede publicar un script completo que lo haga

function log4jTimeStampToMillis(log4jts) {
    # log4jts is of the form 2009-03-02 20:04:13,474
    # extract milliseconds that is after the command
    split(log4jts, tsparts, ",");
    millis = tsparts[2];

    # remove - : from tsstr
    tsstr = tsparts[1];
    gsub("[-:]", " ", tsstr);
    seconds = mktime(tsstr);
    print log4jts;
    return seconds * 1000 + millis;
}
¿Fue útil?

Solución

No lo he usado, pero es posible que desee consultar Time :: ParseDate .

Otros consejos

Aunque casi siempre le digo a la gente que use uno de los muchos módulos excelentes del CPAN para esto, la mayoría de ellos tienen un inconveniente importante: la velocidad. Si analiza una gran cantidad de archivos de registro en tiempo real, eso a veces puede ser un problema. En esos casos, rodar la suya a menudo puede ser una solución más adecuada, pero hay muchas trampas y matices que deben considerarse y manejarse adecuadamente. De ahí la preferencia por usar un módulo conocido, correcto, probado y confiable escrito por otra persona. :)

Sin embargo, antes de siquiera considerar mi consejo anterior, miré su código y lo convertí en perl en mi cabeza ... por lo tanto, aquí hay una conversión más o menos directa de su código gawk en perl. Traté de escribirlo de la manera más simple posible, para resaltar algunas de las partes más delicadas de lidiar con fechas y horas en perl a mano.

# import the mktime function from the (standard) POSIX module
use POSIX qw( mktime );

sub log4jTimeStampToMillis {
    my ($log4jts, $dst) = @_;

    # extract the millisecond field
    my ($tsstr, $millis) = split( ',', $log4jts );

    # extract values to pass to mktime()
    my @mktime_args = reverse split( '[-: ]', $tsstr );

    # munge values for posix compatibility (ugh)
    $mktime_args[3] -= 1;
    $mktime_args[4] -= 1;
    $mktime_args[5] -= 1900;
    # print Dumper \@mktime_args; ## DEBUG

    # convert, make sure to account for daylight savings
    my $seconds = mktime( @mktime_args, 0, 0, $dst );

    # return that time as milliseconds since the epoch
    return $seconds * 1000 + $millis;
}

Una diferencia importante entre mi código y el suyo: mi subrutina log4jTimeStampToMillis toma dos parámetros:

  1. la cadena de marca de tiempo de registro
  2. si esa marca de tiempo usa o no el horario de verano (1 para verdadero, 0 para falso)

Por supuesto, podría agregar código para detectar si ese tiempo cae en horario de verano o no y ajustarlo automáticamente, pero estaba tratando de mantenerlo simple. :)

NOTA: Si descomenta la línea marcada como DEBUG, asegúrese de agregar " use Data :: Dumper; " antes de esa línea en su programa para que funcione.

Aquí hay un ejemplo de cómo podría probar esa subrutina:

my $milliseconds = log4jTimeStampToMillis( "2009-05-10 00:48:41,905", 1 );    
my $seconds = int( $milliseconds / 1000 );
my $local = scalar localtime( $seconds );

print "ms:    $milliseconds\n"; # ms:    1241844521905
print "sec:   $seconds\n";      # sec:   1241844521
print "local: $local\n";        # local: Sat May  9 00:48:41 2009

Debe aprovechar el excelente DateTime , use específicamente DateTime :: Format :: Strptime :

use DateTime;
use DateTime::Format::Strptime;

sub log4jTimeStampToMillis {
    my $log4jts=shift(@_);

    #see package docs for how the pattern parameter works
    my $formatter= new DateTime::Format::Strptime(pattern => '%Y-%m-%d %T,%3N');
    my $dayObj = $formatter->parse_datetime($log4jts);

    return $dayObj->epoch()*1000+$dayObj->millisecond();
}

print log4jTimeStampToMillis('2009-05-10 10:48:41,905')."\n";
#prints my local version of the TS: 1241952521905

Esto le ahorra la molestia de calcular el horario de verano usted mismo (aunque tendrá que pasar la TZ de su servidor a Strptime a través del parámetro time_zone). También le evita tener que lidiar con el salto de todo si se vuelve relevante (y estoy seguro de que lo hará).

SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss,SSS");
Date time = dateFormat.parse(log4jts);
long millis = time.getTime();
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top