• Publicidad

Restar fechas en Perl

¿Ya sabes lo que es una referencia? Has progresado, el nível básico es cosa del pasado y ahora estás listo para el siguiente nivel.

Restar fechas en Perl

Notapor sarama » 2008-01-14 08:26 @393

¡¡Hola a todos!! Necesitaría vuestra ayuda.
Tengo un script hecho en Perl, al cual le paso una fecha por parámetro y la recojo con esta función:

Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
# MÉTODO PARA RECOGER LA FECHA INTRODUCIDA POR PARÁMETRO
sub introduce_fecha {
        if ($#ARGV != 0)
        {
 
                print("No has introducido una fecha de implantacion\n");
 
        }
        else
        {
                $fecha =$ARGV[x];
        }
        return $fecha;
       
        }
Coloreado en 0.006 segundos, usando GeSHi 1.0.8.4


Necesitaría restarle a la fecha que tengo almacenada en la variable $fecha un día. Para que me muestre el anterior.

Por ejemplo
$fecha = 01-01-2008 que al restarle un día me muestre 31-12-2007
¿Podéis ayudarme?

Gracias de antemano :D
sarama
Perlero nuevo
Perlero nuevo
 
Mensajes: 5
Registrado: 2008-01-14 08:19 @388

Publicidad

Notapor explorer » 2008-01-14 10:27 @477

Bienvenido a los foros de Perl en Español, Sarama.

Lo primero es saber el formato en que está la fecha. Pones que es "01-01-2008". Suponemos que es "día-mes-año". Esto es principal, porque luego influye en qué solución vamos a elegir.

Puedes hacer la resta de multitud de formas. En estos foros hay unas cuántas. Usa el sistema de búsqueda.

La forma más fácil es pasar la fecha a segundos, con la ayuda del módulo Time::Local. Luego le restas los segundos que hay en un día y luego con localtime() y strftime lo pasas a la fecha definitiva.

Aquí tienes algo parecido.
JF^D Perl programming & Raku programming. Grupo en Telegram: https://t.me/Perl_ES
Avatar de Usuario
explorer
Administrador
Administrador
 
Mensajes: 14476
Registrado: 2005-07-24 18:12 @800
Ubicación: Valladolid, España

Notapor sarama » 2008-01-14 11:53 @536

Hola explorer!!!
Perdona mi ignorancia pero es que soy nueva en este mundillo, y los scripts que estoy intentando modificar ya estaban creados...

Ya me había movido por los distintos foros viendo las respuestas pero no me convencian (o es que no e sabido utilizarlas).

Te voy a explicar un poco lo que hace mi script y para qué necesito calcular la fecha del día anterior al que recojo x parámetro:

Yo recibo un fichero con unos datos. El fichero debo modificarlo y añadirle al final el campo
Fecha de implantación que es la del día anterior al que recibo el fichero.


Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
#!/usr/bin/perl

## ESTE METODO LEE El ARCHIVO CON LOS DATOS QUE NOS ENVIAN EN LA RUTA ESPECIFICADA
## Y LO ALMACENA EN UNA VARIABLE

sub lee_fichero_temporal{

     $fichero="/ruta/Implantaciones_Realizadas_AIM_$fecha.txt";
        open(TEMP,$fichero) or die "No puedo abrir el archivo - $!";
        @array_temporal=<TEMP>;
        close(TEMP);
#BORRAMOS EL ARCHIVO DESPUES DE HABERLO LEIDO
        unlink $fichero;
        return(@array_temporal);
}


#METODO PARA RECOGER LA FECHA INTRODUCIDA POR PARAMETRO
sub introduce_fecha
        {
 
        if ($#ARGV != 0)
        {
 
                print("No has introducido una fecha de implantacion\n");
 
        }
        else
        {
                $fecha =$ARGV[x];
        }
        return $fecha;
       
        }

        # PROGRAMA PRINCIPAL

# EJECUTO EL METODO INTRODUCE_FECHA
$fecha = introduce_fecha;

# LEO FICHERO (EJECUTA EL METODO LEE_FICHERO_TEMPORAL)
        @array_temporal = lee_fichero_temporal;



#ABRO NUEVO FICHERO CON FECHA DIARIA EN EL NOMBRE
        open(NUEVO_FICHERO,">/ruta/IMPLANTACIONES_REALIZADAS_AIM_$fecha.txt") or
 die "No puedo abrir el archivo - $!";

#SI NO HAY NADA DENTRO DEL ARRAY, EL FICHERO ESTA VACIO ASI QUE NO HAGO NADA

if ($#array_temporal eq -1) {
}

        else
{
#IMPRIMO LA CABECERA CON EL FORMATO QUE NOS SOLICITAN

        print NUEVO_FICHERO "HERRAMIENTA;CODIGO_PETICION;FECHA_IMPLANTACION;\n";

### SI EL FICHERO TIENE DATOS ENTONCES RECORRO EL ARCHIVO POR LINEA

        foreach $linea(@array_temporal) {
       
#ELIMINO LA TERMINACION DE LA CADENA
        chomp($linea);
       
#QUITO ESPACIOS DE LA LINEA
        $linea =~ s/\s+//g;



#########AKI LLEGA EL PROBLEMA YA QUE ME FALTA RECOGER EN LA VARIABLE $fechaimpla el dia anterior al que tengo en $fecha x eso kiero restarle un dia, no sii es la mejor forma...... si sabes otra te agradeceria que me ayudases. De todas formas seguire probando #####

#ALMACENO LOS DATOS EN UNA VARIABLE
        $linea_nueva ="AIM;$linea;$fechaimpla;\n";

#IMPRIMO La Linea nueva (NO TIENE ESPACIOS Y ESTA SEPARADA POR ;)
        print NUEVO_FICHERO "$linea_nueva";
}
}
### CERRAMOS EL FICHERO NUEVO
close(NUEVO_FICHERO);
Coloreado en 0.002 segundos, usando GeSHi 1.0.8.4



De todas formas intenté probar un código:

Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
use Date::Manip;
Date_Init( "Language=Spanish", "DateFormat=non-US" );
$fecha = DateCalc("29/11/2005", "+ 3 dias laborales");
print UnixDate($fecha,"%d/%m/%Y");
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4

Este módulo está bien, pero no funcionará a menos que lo parcheéis según pongo aquí. Una vez hecho eso, es una delicia que te sume fechas, laborales o no.


Que es tuyo y en realidad no puedo parchearme nada ya que es una máquina del curro y no puedo.

Muchas gracias de antemano :)
sarama
Perlero nuevo
Perlero nuevo
 
Mensajes: 5
Registrado: 2008-01-14 08:19 @388

Notapor sarama » 2008-01-15 03:36 @191

También tengo esta función para recoger la fecha de hoy, y utiliza lo que me comentas.
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst,$fecha);
($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time());
$year=$year+1900;
$mon=$mon+1;
# Si el día o el mes empieza por 0 y la longitud es 1, ponemos un 0 delante
if (($mday !~ "^0") && (length($mday) eq 1 )) {$mday = "0".$mday }
if (($mon !~ "^0") && (length($mon) eq 1)) {$mon = "0".$mon }
# Fecha en formato DD-MM-AAAA
$fecha=sprintf("$mday-$mon-$year");
return $fecha;
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4


¿Sería parecido?

MUCHAS GRACIAS
sarama
Perlero nuevo
Perlero nuevo
 
Mensajes: 5
Registrado: 2008-01-14 08:19 @388

Notapor explorer » 2008-01-15 08:13 @384

Esta es una de las posibles soluciones.
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
#!/usr/bin/perl
use POSIX qw[strftime];
use Time::Local;
use strict;
use warnings;

my $fecha;                              # La fecha de entrada estará en formato dia-mes-año
my $fecha_seg;                          # La misma fecha, en segundos
my $fecha_ayer;                         # La fecha del día anterior en día-mes-año

# Ver si el usuario nos ha pasado la fecha
if ( ! @ARGV ) {
    die "Uso: $0 <dd-mm-aaaa>\n\n    dd-mm-aaaa : Fecha de implantación\n\n";
}

# Comprobemos que la fecha es correcta
$fecha = shift @ARGV;
if ( my ($dia,$mes,$anno) = $fecha =~ m/(\d+)-(\d+)-(\d+)/ ) {
    # Conversión a segundos. Esta función fallará si la fecha es incorrecta
    $fecha_seg = timelocal(00,00,00,$dia,$mes-1,$anno);
}
else {
    die "ERROR: La fecha no es correcta.\n";
}

# Cálculo del día de ayer
$fecha_ayer = strftime "%d-%m-%Y", localtime $fecha_seg - 24 * 60 * 60;
print "Fecha implantación: $fecha_ayer\n";

# Leer el fichero temporal
my $fichero = "/ruta/Implantaciones_Realizadas_AIM_$fecha.txt";
open FICHERO, "<$fichero" or die "ERROR: No puedo leer el archivo $fichero: $!\n";
my @fichero = <FICHERO>;
close FICHERO;

# Creamos el nuevo contenido del fichero
open FICHERO,">$fichero" or die "ERROR: No puedo escribir el archivo $fichero: $!\n";
if ( @fichero ) {
    print FICHERO "HERRAMIENTA;CODIGO_PETICION;FECHA_IMPLANTACION;\n";

    foreach my $linea ( @fichero ) {
        chomp $linea;
        $linea =~ s/\s+//g;
        print FICHERO "AIM;$linea;$fecha_ayer;\n";
    }
}
close FICHERO;
 
Coloreado en 0.002 segundos, usando GeSHi 1.0.8.4


La solución es la siguiente: usamos el módulo Time::Local, incluido en la distribución Perl, que nos pasa una fecha dada en sus componentes (día, mes, año...) a su fecha en tiempo Unix (segundos desde el Epoch). Luego, solo tenemos que restar a ese número de segundos, los segundos correspondientes a un día. Con localtime() convertimos esa fecha dada en segundos a una fecha en componentes que, con la ayuda de strftime(), obtendremos la fecha ya formateada.

En la solución he puesto el mismo fichero de entrada que de salida, porque eso es lo que me parece después de ver tu código.
JF^D Perl programming & Raku programming. Grupo en Telegram: https://t.me/Perl_ES
Avatar de Usuario
explorer
Administrador
Administrador
 
Mensajes: 14476
Registrado: 2005-07-24 18:12 @800
Ubicación: Valladolid, España

Notapor sarama » 2008-01-15 11:05 @503

¡Hola explorer!
Gracias, lo de la fecha funciona, he hecho unos arreglillos porque me daba errores.

Pero ahora me da otro error... jejejejeje.

En este caso el fichero se llama igual pero en teoría se supone que creo uno nuevo. En otros casos el fichero de entrada el título está en minúscula y el de salida en mayúscula, porque daba error al machacarlo que es lo que me sucede ahora... te explico:

Este es el código final:

Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
#!/usr/bin/perl
use POSIX qw[strftime];
use Time::Local;
#use strict;
#use warnings;


        sub lee_fichero_temporal{

                $fichero="/de/gdpv/batch/es/dat/di/IMPLANTACIONES_REALIZADAS_SIVA_$fecha.txt";
                open(TEMP,$fichero) or die "No puedo abrir el archivo - $!";
                @array_temporal=<TEMP>;
                close(TEMP);
                 unlink $fichero;
                 return(@array_temporal);
                }      

        sub introduce_fecha{
 
        if ($#ARGV != 0)
        {
 
                print("No has introducido una fecha de implantacion\n");
 
        }
        else
        {
                $fecha =$ARGV[x];
        }
        return $fecha;
        }

 $fecha = introduce_fecha;
 @array_temporal = lee_fichero_temporal;

my $fecha;                              # La fecha de entrada estará en formato dia-mes-año
my $fecha_seg;                          # La misma fecha, en segundos
my $fecha_ayer;                         # La fecha del día anterior en día-mes-año
# Comprobemos que la fecha es correcta
$fecha = shift @ARGV;
if ( my ($dia,$mes,$anno) = $fecha =~ m/(\d+)-(\d+)-(\d+)/ ) {
    # Conversión a segundos. Esta función fallará si la fecha es incorrecta
    $fecha_seg = timelocal(00,00,00,$dia,$mes-1,$anno);
}
else {
    die "ERROR: La fecha no es correcta.\n";
}

# Cálculo del día de ayer
$fecha_ayer = strftime "%d-%m-%Y", localtime $fecha_seg - 24 * 60 * 60;
print "Fecha implantación: $fecha_ayer\n";

# Leer el fichero temporal
my $fichero = "/de/gdpv/batch/es/dat/di/IMPLANTACIONES_REALIZADAS_SIVA_$fecha.txt";
open FICHERO, "<$fichero" or die "ERROR: No puedo leer el archivo $fichero: $!\n";
my @fichero = <FICHERO>;
close FICHERO;

# Creamos el nuevo contenido del fichero
open FICHERO,">$fichero" or die "ERROR: No puedo escribir el archivo $fichero: $!\n";
if ( @fichero ) {
    print FICHERO "HERRAMIENTA;CODIGO_PETICION;FECHA_IMPLANTACION;\n";

    foreach my $linea ( @fichero ) {
        chomp $linea;
        $linea =~ s/\s+//g;
        print FICHERO "AIM;$linea;$fecha_ayer;\n";
    }
}
close FICHERO;
Coloreado en 0.002 segundos, usando GeSHi 1.0.8.4


y al ejecutar el script:

Código: Seleccionar todo
>sivareali.pl 06-12-2007
Fecha implantación: 05-12-2007
ERROR: No puedo leer el archivo /RUTAi/IMPLANTACIONES_REALIZADAS_SIVA_06-12-2007.txt: No such file or directory


¿Puede ser por que no se puede sobreescribir? De todas formas voy a hacer pruebas con otros ficheros.

Oye, y ¡muchas gracias!
sarama
Perlero nuevo
Perlero nuevo
 
Mensajes: 5
Registrado: 2008-01-14 08:19 @388

Notapor explorer » 2008-01-15 12:07 @546

Por favor, sarama... has mezclado mi programa con el tuyo... no me extraña que te den problemas.

El error que muestras dice que no puede leerlo porque no lo encuentra. Es decir, '/RUTAi/IMPLANTACIONES_REALIZADAS_SIVA_06-12-2007.txt' no existe como fichero. Tendrás que repasar el camino (path) de los ficheros. No tiene nada que ver con sobreescribirlo, porque todavía no ha llegado a esa parte del programa.

No mezcles nombres de fichero con mayúsculas o minúsculas. Tendrás problemas en el futuro. Es algo que depende mucho del sistema operativo en que te encuentres. Decídete por una única regla de escritura.

Si lo que quieres es borrar el antiguo deberás usar unlink(), como en tu programa. Lo que no nos has contado es qué reglas tienes que seguir a la hora de crear el nombre del nuevo fichero. Solo ponías en tu programa que tuviera la fecha escrita por el usuario.

Si has tenido problemas a la hora de sobreescribir un fichero, es que no tendrás permiso de escritura en ese fichero.
JF^D Perl programming & Raku programming. Grupo en Telegram: https://t.me/Perl_ES
Avatar de Usuario
explorer
Administrador
Administrador
 
Mensajes: 14476
Registrado: 2005-07-24 18:12 @800
Ubicación: Valladolid, España

Notapor sarama » 2008-01-16 10:40 @486

Perdona explorer... llevas razón. El motivo por el que mezclé el código era porque el fichero de entrada es Implantaciones_Aim_$fecha y el de salida (es otro)
IMPLANTACIONES_AIM_$fecha.

Por eso lo mezclé. He probado el tuyo y por supuesto que funciona. Solo le he hecho una pequeña modificación y ya hace lo que quiero.

MUCHÍSIMAS GRACIAS Y PERDONA POR LAS MOLESTIAS :):):)
sarama
Perlero nuevo
Perlero nuevo
 
Mensajes: 5
Registrado: 2008-01-14 08:19 @388


Volver a Intermedio

¿Quién está conectado?

Usuarios navegando por este Foro: No hay usuarios registrados visitando el Foro y 0 invitados