PDA

Ver la Versión Completa : [ IDEA ] Subtarea que devuelve la fecha en formato AAAA-MM-DD


Caravantes
26/03/16, 18:58:12
Editado posterior (2016-03-29): en varios mensajes de este mismo hilo, los compañeros danko9696 , maid450 y WillyWeb nos ofrecen opciones de script que resuelven el mismo problema en una sola acción de Tasker. No dejes de ver sus posts.

Muchas veces guardo ficheros en cuyo nombre pongo la fecha del archivo.
- Copia de seguridad 01-03-2016
- Copia de seguridad 02-03-2016
- Copia de seguridad 28-02-2016
Pero eso tiene el inconveniente de que la ordenación alfabética por nombres de archivo no coincide con la ordenación cronológica.

Este problema se resuelve poniendo primero el año, luego el mes y luego el día, con lo cual la ordenación alfabética coincide con la cronológica.
- Copia de seguridad 2016-02-28
- Copia de seguridad 2016-03-01
- Copia de seguridad 2016-03-02

He creado una tarea sencilla que solo sirve para eso: para devolver cualquier fecha como un texto en formato AAAA-MM-DD. Esta subtarea puede ser utilizada por cualquier otra tarea principal que guarde archivos periódicamente. Como opción, también se puede añadir la hora. Fecha y hora se transmiten como parámetros entregados a la subtarea. Si se omite la fecha, se usa la fecha actual.
En el texto devuelto, como separadores solo se utiliza el guión y el guión-bajo porque nunca dan problemas como parte del nombre de archivo. En el texto devuelto siempre se usan cuatro dígitos para el año, dos para el mes y otros dos para el día.
Esta tarea solo utiliza variables locales. Se puede ejecutar directamente para ver (en un PopUp) el resultado. Creo que no necesita más explicaciones.


A1: Anchor <Esta subtarea recibe en %par1 una fecha dd-mm-aa y la devuelve en formato AAAA-MM-DD. Si en %par2 hay una hora u otra cosa, la agrega devolviendo: AAAA-MM-DD_%par2. Si ejecutas la tarea directamente, parte del momento actual y muestra el resultado.>
A2: Establecer variable [ Nombre:%par1 A:%DATE Calcular:Apagado Añadir:Apagado ] Si (if) [ %par1 No ajust. ]
A3: Establecer variable [ Nombre:%par2 A:%TIME Calcular:Apagado Añadir:Apagado ] Si (if) [ %caller1 ~ ui ]
A4: Establecer variable [ Nombre:%fecha A:%par1 Calcular:Apagado Añadir:Apagado ]
A5: Establecer variable [ Nombre:%hora A:%par2 Calcular:Apagado Añadir:Apagado ]
A6: Separar variable [ Nombre:%fecha Separador:- Eliminar base:Apagado ]
A7: Detener [ Con error:Apagado Tarea: ] Si (if) [ %fecha(#) != 3 ]
A8: For [ Variable:%num Ítems:1:3 ]
A9: Probar Variable [ Tipo:Longitud Datos:%fecha(%num) Almacenar Resultado en:%tamaño ]
A10: Establecer variable [ Nombre:%fecha(%num) A:0%fecha(%num) Calcular:Apagado Añadir:Apagado ] Si (if) [ %num < 3 & %tamaño < 2 ]
A11: Establecer variable [ Nombre:%fecha(%num) A:20%fecha(%num) Calcular:Apagado Añadir:Apagado ] Si (if) [ %num = 3 & %tamaño < 4 ]
A12: End For
A13: Establecer variable [ Nombre:%aammdd A:%fecha(3)-%fecha(2)-%fecha(1) Calcular:Apagado Añadir:Apagado ]
A14: Si (if) [ %hora Ajuste ]
A15: Buscar y Reemplazar Contenido de Variable [ Variable:%hora Buscar:\. Ignorar Caso:Apagado Multilínea:Apagado Una sola coincidencia:Apagado Almacenar Coincidencias En: Reemplazar Coincidencias:Encendido Reemplazar Con:- ]
A16: Establecer variable [ Nombre:%aammdd A:_%hora Calcular:Apagado Añadir:Encendido ]
A17: Fin si (End if)
A18: Si (if) [ %caller1 ~ ui ]
A19: Pop-Up [ Título: Texto:%par1 / %par2 / %aammdd ...]
A20: Else
A21: Devolver [ Valor:%aammdd Detener:Encendido ]
A22: Fin si (End if)


:cucu:

danko9696
27/03/16, 05:39:51
Yo no usaría una subtarea solo para esta función. Mejor un scriptlet que te lo solucione en una sola linea. Más rapido y es facilmente modificable sobre la marcha para eliminar guiones, añadir hora o cualquier otro cambio. Asumiendo que ya existe la variable:

v_fecha = v_fecha.substr(6,4) + "-" + v_fecha.substr(3,2) + "-" + v_fecha.substr(0,2);

o (casi mejor, yo lo pondría sin guiones)

v_fecha = v_fecha.substr(6,4) + v_fecha.substr(3,2) + v_fecha.substr(0,2);

cace0353
27/03/16, 11:08:01
Yo no usaría una subtarea solo para esta función. Mejor un scriptlet que te lo solucione en una sola linea. Más rapido y es facilmente modificable sobre la marcha para eliminar guiones, añadir hora o cualquier otro cambio. Asumiendo que ya existe la variable:

v_fecha = v_fecha.substr(6,4) + "-" + v_fecha.substr(3,2) + "-" + v_fecha.substr(0,2);

o (casi mejor, yo lo pondría sin guiones)

v_fecha = v_fecha.substr(6,4) + v_fecha.substr(3,2) + v_fecha.substr(0,2);

Excelente, danko9696

Este es un magnífico ejemplo de lo que se puede hacer con JS en Tasker, simplificando las acciones, aumentando la claridad del código y la velocidad de ejecución!

Ya he puesto el link al post en el HILO ESPECIFICO de integración de JS en Tasker, pero me permito una sugerencia, danko9696 : aunque en este caso se entiende muy bien si has hecho algo de programación, no estaria de mas "documentar" las sentencias del código que uno aporta. Piensa que muchos somos neófitos y si lo "explicas" un poco será más pedagógico el aporte.

Saludos a todos!

danko9696
27/03/16, 17:05:48
Excelente, @danko9696 (http://www.htcmania.com/member.php?u=868681)

Este es un magnífico ejemplo de lo que se puede hacer con JS en Tasker, simplificando las acciones, aumentando la claridad del código y la velocidad de ejecución!

Ya he puesto el link al post en el HILO ESPECIFICO de integración de JS en Tasker, pero me permito una sugerencia, danko9696 : aunque en este caso se entiende muy bien si has hecho algo de programación, no estaria de mas "documentar" las sentencias del código que uno aporta. Piensa que muchos somos neófitos y si lo "explicas" un poco será más pedagógico el aporte.

Saludos a todos!
Hombre, es solo una linea (y bien corta), no una serie de bucles con unas cuantas variables que puedan ser complicados de seguir. Creo que si has manejado alguna vez variables en Tasker resulta obvio lo que hace a primera vista aunque no se tenga ni idea de programación, sobre todo conociendo la finalidad de cambiar el orden de los caracteres.

Comentar de paso que se puede hacer parecido con acciones de tasker usando tres variable section, aunque sigue necesitando más de una linea y más de una variable, ya que necesita una acción por troceado en lugar de poder trocear y concatenar todo en la misma linea.

Caravantes
28/03/16, 02:07:21
v_fecha = v_fecha.substr(6,4) + "-" + v_fecha.substr(3,2) + "-" + v_fecha.substr(0,2);

Gracias por la propuesta, excelente. Siempre es grato recibir alternativas de este tipo.

En realidad, el objetivo era un poco más ambicioso. La tarea hace cosas como "añadir un cero a la izquierda" cuando el mes o el día tienen un solo dígito ("8-3-16"). Supongo que ese ajuste también se podrá programar en script, pero de momento desborda mis conocimientos.

Creo que la cuestión fundamental es que quien utiliza una tarea o un script debe ser capaz de entenderlo y tener cierta soltura para mantenerlo (modificarlo y/o adaptarlo a nuevas circunstancias). Evidentemente, quienes sabéis programar en script podéis elegir cuándo cambiar de acera, dependiendo de que en cada circunstancia os resulte más ventajoso ir por el sol o por la sombra.

Está muy bien que con ejemplos como éste nos demostréis la utilidad de aprender script y su sencillez: alguno ya se va animando; quizá otros tardaremos un poco más.

Firmado: un envidioso. :sisi1:

danko9696
28/03/16, 14:21:40
Gracias por la propuesta, excelente. Siempre es grato recibir alternativas de este tipo.

En realidad, el objetivo era un poco más ambicioso. La tarea hace cosas como "añadir un cero a la izquierda" cuando el mes o el día tienen un solo dígito ("8-3-16"). Supongo que ese ajuste también se podrá programar en script, pero de momento desborda mis conocimientos.

Creo que la cuestión fundamental es que quien utiliza una tarea o un script debe ser capaz de entenderlo y tener cierta soltura para mantenerlo (modificarlo y/o adaptarlo a nuevas circunstancias). Evidentemente, quienes sabéis programar en script podéis elegir cuándo cambiar de acera, dependiendo de que en cada circunstancia os resulte más ventajoso ir por el sol o por la sombra.

Está muy bien que con ejemplos como éste nos demostréis la utilidad de aprender script y su sencillez: alguno ya se va animando; quizá otros tardaremos un poco más.

Firmado: un envidioso. :sisi1:
No se, yo lo veo de otro modo. No creo que sea lógico que en una lista de aportes todos y cada uno deban de ser considerados tutoriales. En mi opinión esa no es (o no debería ser) su función, sino precísamente la de descargar de forma rápida algo para lo que no necesites comprender cómo funciona y que luego si quieres puedas examinar en detalle buscando información en otras fuentes para comprender su función.

No me parece razonable que el manejo de cadenas en javascript sea explicado, además de en la sección tutorial de uso de variables de javascript en todas y cada una de cualquier posible tarea que se añada. Si alguien quiere hacer un tutorial a la vez me parece perfecto pero no debería ser algo exigible, creo yo.

Si me bajo un script ya hecho, sobre todo si es para algo muy concreto, no espero que me expliquen cómo hace lo que hace sino qué parametros necesita y qué hace o qué valores devuelve, que si te fijas es justo lo que haces con Tasker, no necesitas saber cómo funcionan las acciones a nivel interno.

Y es que es más, muchas partes de código que he escrito yo mismo no entiendo cómo lo he hecho si lo miro tiempo después y tendría que deshacer el código, organizarlo en el notepad y echar un vistazo poco a poco. Lo que sí necesito entender son las partes que no pueden ser facilmente aisladas, como FOR e IFs importantes.


Por ejemplo, he realizado cambios para controlar que haya o no ceros delante y añado hora quitando los dos puntos:

v_fecha = ("20"+v_fecha.substr(v_fecha.search("-")+1,77).substr(v_fecha.substr(v_fecha.search("-")+1,77).search("-")+1,77)).slice(-4)+"-"+("0"+v_fecha.substr(v_fecha.search("-")+1,77).substr(0,v_fecha.substr(v_fecha.search("-")+1,77).search("-"))).slice(-2)+"-"+("0"+v_fecha.substr(0,v_fecha.search("-"))).slice(-2)+" "+(v_hora!="%v_hora" ? "" + v_hora.substr(0,2) + v_hora.substr(3,2) : "");

Si veo esto en mitad de código junto con muchas más cosas, de primeras no voy a tener ni idea de lo que hace, y mucho menos cómo lo hace (exactamente). Ni falta que hace. Una vez que funciona lo meto y ahí se queda. Quizás un comentario delante en plan de "ddmmaaaa->aaaammdd", pero poco más y puede que ni eso (puesto en una tarea aparte es innecesario), no voy a comentar absolutamente todo. Porque muchas veces metes en el código cosas que no has hecho de un tirón sino en varios pasos (como en este caso) y usas solo la versión final. Lo importante no es el cómo lo hace, sobre todo para cosas muy específicas, sino saber lo que hacen las instrucciones (o tener documentación/tutoriales a mano), de modo que si quieres analizarlo puedas hacerlo poco a poco, copiandolo a otro sitio y desmontándolo para verlo mejor.

Yo tampoco soy ningún experto en javascript. Se lo justo para desenvolverme con Tasker. Eso sí, sin miedo a buscar documentación o ejemplos. Realmente es ponerse a ello, y compensa porque aunque cueste un poco arrancar luego es mucho más cómodo. Salvo usar plugins, que no me queda otra, ya no me planteo usar acciones nativas de Tasker.

En la practica lo que yo haría sería modificar los archivos ya existentes a mano (o si son muchos -muchos cientos o miles- con una macro en windows) y simplemente que las funciones donde guarde archivos con fecha en el nombre lo hagan siempre en el formato correcto.

Caravantes
28/03/16, 21:03:04
Danko, muchas gracias.
Al comienzo del hilo he insertado una advertencia bien visible informando sobre tus alternativas, para que todos los lectores tengan conocimiento de ellas desde el principio.

Respondiendo a tu último comentario, no tengo ficheros a los que necesite renombrar. Hasta ahora los he nombrado correctamente (AAAA-MM-DD) a mano, pues ha sido algo ocasional. Ahora me he planteado este asunto porque creo que voy a implementar una nueva tarea Tasker que guardará ficheros automáticamente y quiero que también lo haga de esta forma.

maid450
29/03/16, 09:11:30
Como siempre digo, por lo general hay muchas formas diferentes de hacer las cosas, apunto aquí un par de formas más de como se podría enfocar esto para tener más variedad y así cada uno que se quede con la que más le guste/convenga.
Evidentemnte, siendo yo, voy a usar JS para las 2 xD

1) El objeto Date
Esta es la más "de programación", y por ello la que casi siempre uso yo cuando tengo que trabajar con fechas.
En JS existe un objeto Date para manejar fechas (aquí (http://www.w3schools.com/jsref/jsref_obj_date.asp) una referencia de las formas en que se puede crear el objeto y las funciones que expone, me voy a limitar a las más básicas).
Para crear el objeto con la fecha actual basta hacer

var fecha = new Date();
Otras opciones para inicializar el objeto con otra fecha sería pasando entre parentesis:


un timestamp en ms (como el %TIMEMS de Tasker)
una fecha en formato texto (este no es muy recomendable porque los formatos que acepta no están claros, y normalmente son formatos anglosajones con el mes antes del día)
pasando el año, mes, día, horas, minutos, segundos y milisegundos separando por comas. Se puede parar donde quieras (por ejemplo pasar solo año, mes y día) y el resto lo inicializa a 0 (o 1 para el dia y/o el mes)

Una vez el objeto está creado, este ofrece varias funciones para trabajar con la fecha (ver el enlace de antes para todas), para este caso nos valen las "getters" (getDate/getMonth/getFullYear) pero como un simple ejemplo de lo interesante que puede ser este objeto, veamos como podríamos sacar qué día será dentro de 6 horas y 32 minutos (la complicación de hacerlos de otras formas es que hasta las 17:27, 6:32 más tarde seguirá siendo el mismo día, pero a partir de las 17:28, 6:32 despues ya será el día siguiente, así pues aunque se podría hacer de otras formas sería bastante complejo)

var fecha = new Date();
fecha.setHours(fecha.getHours() + 6); //establecemos las horas a las horas actuales + 6
fecha.setMinutes(fecha.getMinutes() + 32); //establecemos los minutos a los minutos actuales + 32
Tras esto, fecha.getDate() devolvería el día del mes (entre 1-31) que será dentro de 6:32, sin más calculos raros.


Presentado este objeto, vamos a como aplicarlo a lo que queremos hacer, tendríamos que usar los getters como decía, y lo unico a tener en cuenta es:


los 3 metodos devuelven un numero entero, es decir que si el valor es < a 10 hay que ponerle un 0 delante.
getMonth() curiosamente devuelve el numero del mes empezando desde 0 (enero es 0 en vez de 1 que sería lo lógico) con lo que hay que sumarle 1 para sacar el valor que queremos (esto aún es más raro teniendo en cuenta que getDate() devuelve el día entre 1 y 31 como es de esperar, pero bueno, alguna razón abrá...)

Así pues, la fecha actual en formato AAAA-MM-DD podemos sacarla así:

//versión facilmente legible:
var fecha = new Date();
var dias = fecha.getDate();
if(dias < 10) dias = '0' + dias;
var meses = fecha.getMonth() + 1;
if(meses < 10) meses = '0' + meses;
var anyo = fecha.getFullYear();
var fecha = anyo + '-' + meses + '-' + dias;

//versión compacta
var fecha = new Date();
fecha = fecha.getFullYear() + '-' + (fecha.getMonth() + 1 < 10? '0' + (fecha.getMonth() + 1) : (fecha.getMonth() + 1)) + '-' + (fecha.getDate() < 10? '0' + fecha.getDate() : fecha.getDate());
en ambos casos, en %fecha tendremos la fecha en el formato que queremos.


2) Expresiones regulares
Si no necesitamos modificar la fecha añadiendo/quitando horas, minutos, etc... igual usar objetos y cosas tan "de programación" nos parece complicarnos la vida, con lo que igual nos gusta más simplemente manejar las cadenas de texto como ha propuesto Danko, el problema es que cuando el día o el mes tienen/no tienen 0's delante se complica bastante, ahí pueden entrar las expresiones regulares.
Esto lo voy a explicar menos porque es algo más dificil de explicar y entender, pero en script queda bastante limpio.

var fecha = global('DATE');
var partes = /(\d+)-(\d+)-(\d+)/.exec(fecha);
fecha = partes[3] + '-' + (partes[1] < 10? '0' + partes[1] : partes[1]) + '-' + (partes[2] < 10? '0' + partes[2] : partes[2]);
Y ya tendríamos la fecha en el formato que queremos.




Como pequeño apunte, en ambos casos he usado el operador ternario de js que es una forma abreviada de asignar un valor u otro a una variable en funcion de una condicion.
Lo explico rápidamente:


var a = condicion? valor1 : valor2;
//equivale a
var a = '';
if(condicion) a = valor 1;
else a = valor2;
Muy práctico para compactar cosas, yo en ambos casos lo he usado para añadir o no un 0 delante de los días/meses < 10

danko9696
29/03/16, 09:56:29
2) Expresiones regulares
Si no necesitamos modificar la fecha añadiendo/quitando horas, minutos, etc... igual usar objetos y cosas tan "de programación" nos parece complicarnos la vida, con lo que igual nos gusta más simplemente manejar las cadenas de texto como ha propuesto Danko, el problema es que cuando el día o el mes tienen/no tienen 0's delante se complica bastante, ahí pueden entrar las expresiones regulares.
Esto lo voy a explicar menos porque es algo más dificil de explicar y entender, pero en script queda bastante limpio.

var fecha = global('DATE');
var partes = /(\d+)-(\d+)-(\d+)/.exec(fecha);
fecha = partes[3] + '-' + (partes[1] < 10? '0' + partes[1] : partes[1]) + '-' + (partes[2] < 10? '0' + partes[2] : partes[2]);
Y ya tendríamos la fecha en el formato que queremos.
En el ejemplo de regex, si el mes (o día) es menor que 10 sigue tratando la fecha como cadena, por lo que quedaría 2016-29-003 (habría que añadir un *1 a partes[1] y partes[2]), además de que coje por defecto el formato de mmddyyyy

Creo que para los ceros mejor un troceado antes que con operador ternario.
fecha = partes[3] + '-' + ("0"+partes[2]).slice(-2) + '-' + ("0"+partes[1]).slice(-2);

cace0353
29/03/16, 11:13:08
Estoy alucinando... :oh:

Vaya nivel que está cogiendo el hilo y el juego que puede dar. Magníficas aportaciones de los dos compañeros!

Seguid así que gracias a vuestros aportes vamos aprendiendo todos y mejorando nuestros "programitas"

Firmado: otro envidioso

WillyWeb
29/03/16, 14:02:54
En el ejemplo de regex, si el mes (o día) es menor que 10 sigue tratando la fecha como cadena, por lo que quedaría 2016-29-003 (habría que añadir un *1 a partes[1] y partes[2]), además de que coje por defecto el formato de mmddyyyy

La solución de maid450, al margen del orden de las partes, funciona perfectamente con una fecha como "1-2-3333", aunque yo lo hubiera acortado un poco más...

fecha = "1-2-3333";
partes = fecha.split("-");
var fecha = partes[2]+'-'+(partes[1]<10?'0':'')+partes[1]+'-'+(partes[0]<10?'0':'')+partes[0];

Pero reconozco que me ha gustado mucho tu solución (no te molestes maid X-D)...

fecha = "1-2-3333";
partes = fecha.split("-");
var fecha = partes[2] + '-' + ("0"+partes[1]).slice(-2) + '-' + ("0"+partes[0]).slice(-2);

Simple y elegante :ok:

danko9696
29/03/16, 14:11:01
La solución de maid450, al margen del orden de las partes, funciona perfectamente con una fecha como "1-2-3333", aunque yo lo hubiera acortado un poco más...

fecha = "1-2-3333";
partes = fecha.split("-");
var fecha = partes[2]+'-'+(partes[1]<10?'0':'')+partes[1]+'-'+(partes[0]<10?'0':'')+partes[0];Pero reconozco que me ha gustado mucho tu solución (no te molestes maid X-D)...

fecha = "1-2-3333";
partes = fecha.split("-");
var fecha = partes[2] + '-' + ("0"+partes[1]).slice(-2) + '-' + ("0"+partes[0]).slice(-2);Simple y elegante :ok:
Tu ejemplo sigue fallando con el tema de los ceros. Prueba ahora con "01-02-3333" XDD

WillyWeb
29/03/16, 14:29:09
Tu ejemplo sigue fallando con el tema de los ceros. Prueba ahora con "01-02-3333" XDD

Pues tienes razón :oh:

Juraría que cuando lo he probado antes funcionaba (seguro que la culpa es de la web en la que he corrido el script :risitas:).

Definitivamente me gusta más tu solución :aplausos:

EDITO...

Pues sí que funcionaba, pero con una fechas como estas: "1-2-3333" , "11-22-3333". Es decir, si día o mes nunca tienen ceros a la izquierda. Si la fecha es así "01-02-3333" no funciona bien. :(

maid450
29/03/16, 14:36:11
Tu ejemplo sigue fallando con el tema de los ceros. Prueba ahora con "01-02-3333" XDD
El caso es que el string de fecha de Tasker no viene con ceros, de ahí la "necesidad" de añadirlos si el numero es inferior a 10 ;-)

De todas formas, la verdad es que tu solución del slice no se me había ocurrido (siempre he usado esa funcion con arrays de numeros o cadenas, pero no con strings...) pero me gusta :thumbup:
WillyWeb cierto que en este caso un simple split cumple a la perfección, me he precipitado sacando el bazooka de las regex para acabar con unas simples moscas xD

Lo dicho, variedad de aproximaciones y así cada uno que use la que más le guste y al final todos aprendemos alguna cosa :-)

danko9696
29/03/16, 15:18:11
El caso es que el string de fecha de Tasker no viene con ceros, de ahí la "necesidad" de añadirlos si el numero es inferior a 10 ;-)

De todas formas, la verdad es que tu solución del slice no se me había ocurrido (siempre he usado esa funcion con arrays de numeros o cadenas, pero no con strings...) pero me gusta :thumbup:
@WillyWeb (http://www.htcmania.com/member.php?u=68214) cierto que en este caso un simple split cumple a la perfección, me he precipitado sacando el bazooka de las regex para acabar con unas simples moscas xD

Lo dicho, variedad de aproximaciones y así cada uno que use la que más le guste y al final todos aprendemos alguna cosa :-)
La fecha de Tasker puede que no, pero puede ser una fecha procedente de un archivo, o de un httpget, etc...

Yo al reves, no había caido en intentar usar regex, además de que mi intención inicial era hacerlo con una única instrucción de las básicas del tutorial unicamente, pero es la versión que más me gusta, porque con muy poca modificación puede servir para cuando no sabemos cual va ser el separador.

Pues tienes razón :oh:

Juraría que cuando lo he probado antes funcionaba (seguro que la culpa es de la web en la que he corrido el script :risitas:).

Definitivamente me gusta más tu solución :aplausos:

EDITO...

Pues sí que funcionaba, pero con una fechas como estas: "1-2-3333" , "11-22-3333". Es decir, si día o mes nunca tienen ceros a la izquierda. Si la fecha es así "01-02-3333" no funciona bien. :(
Realmente no es mi solución sino de maid450. La parte "chunga" es el regex. Lo del slice es una bobada.