Foros del Web » Programando para Internet » Javascript »

Cronómetro preciso a partir de fecha

Estas en el tema de Cronómetro preciso a partir de fecha en el foro de Javascript en Foros del Web. Hola, he googleado a fondo pero no he encontrado la aplicación que se ajuste a mis necesidades, así que tengo que mendigar la ayuda de ...
  #1 (permalink)  
Antiguo 10/08/2011, 10:59
Avatar de ThunderWolf  
Fecha de Ingreso: julio-2011
Mensajes: 30
Antigüedad: 13 años
Puntos: 1
Cronómetro preciso a partir de fecha

Hola, he googleado a fondo pero no he encontrado la aplicación que se ajuste a mis necesidades, así que tengo que mendigar la ayuda de una mano experta.

Necesito un cronómetro que muestre los años, meses, días, horas, minutos y segundos a partir de una fecha determinada en un input o div, para poder meterles después un CSS.

Lo más parecido que he encontrado es este código, aunque solo muestra los días transcurridos en un document.write:

Script:
Código:
var montharray=new Array("Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec")

function countup(yr,m,d){

var today=new Date()
var todayy=today.getYear()

if (todayy < 1000)
todayy+=1900

var todaym=today.getMonth()
var todayd=today.getDate()
var todaystring=montharray[todaym]+" "+todayd+", "+todayy
var paststring=montharray[m-1]+" "+d+", "+yr
var difference=(Math.round((Date.parse(todaystring)-Date.parse(paststring))/(24*60*60*1000))*1)

document.write("Esta página se publicó hace "+difference+" días")
}

countup(2001,08,20)
Si se puede rizar el rizo, estaría genial que si alguno de los datos no fuera una unidad entera, la diera con decimales; como por ejemplo 0'16 años, 2 meses, 61 dias, etc..

Última edición por ThunderWolf; 11/08/2011 a las 02:59
  #2 (permalink)  
Antiguo 11/08/2011, 06:24
Avatar de ThunderWolf  
Fecha de Ingreso: julio-2011
Mensajes: 30
Antigüedad: 13 años
Puntos: 1
Respuesta: Cronómetro preciso a partir de fecha

Se ve que no busqué suficientemente bien, encontré un script completísimo y configurable. Vale tanto para cuenta regresiva como progresiva, según se introduzca un valor positivo o negativo en "CountStepper":

Parte 1: configuración: (en cualquier sitio de la página)
Código:
<script language="JavaScript">

/*Fecha y hora objetivo*/
TargetDate = "01/01/1900 12:00 PM";

/*Color de fondo*/
BackColor = "transparent";

/*Color de letra*/
ForeColor = "black";

/*Dinamico o estático, true y false respectivamente*/
CountActive = true;

/*Hacia delante o hacia atras, +1 y -1 respectivamente*/
CountStepper = +1;

/*Poner un 0 delante de las cifras o no, true y false respectivamente*/
LeadingZero = true;

/*La frase que se quiera poner, no modificar los %%X%%*/
DisplayFormat = "La página lleva activa %%A%% Años, %%M%% Meses, %%D%% Días, %%H%% Horas, %%Mn%% Minutos y %%S%% Segundos.";

/*El mensaje que aparecera al final de la cuenta regresiva. Sin efectos en la progresiva, a no ser que se ponga una fecha futura*/
FinishMessage = "El final de los tiempos";

</script>
Parte 2: motor: (en donde aparecerá el contador)
Código:
<script>

function calcage(secs, num1, num2) {
  s = ((Math.floor(secs/num1))%num2).toString();
  if (LeadingZero && s.length < 2)
    s = "0" + s;
  return "<b>" + s + "</b>";
}

function CountBack(secs) {
  if (secs < 0) {
    document.getElementById("cntdwn").innerHTML = FinishMessage;
    return;
  }
  DisplayStr = DisplayFormat.replace(/%%D%%/g, calcage(secs,86400,30));
  DisplayStr = DisplayStr.replace(/%%A%%/g, calcage(secs,31556926,99));
  DisplayStr = DisplayStr.replace(/%%M%%/g, calcage(secs,2629744,12));
  DisplayStr = DisplayStr.replace(/%%H%%/g, calcage(secs,3600,24));
  DisplayStr = DisplayStr.replace(/%%Mn%%/g, calcage(secs,60,60));
  DisplayStr = DisplayStr.replace(/%%S%%/g, calcage(secs,1,60));

  document.getElementById("cntdwn").innerHTML = DisplayStr;
  if (CountActive)
    setTimeout("CountBack(" + (secs+CountStepper) + ")", SetTimeOutPeriod);
}

function putspan(backcolor, forecolor) {
 document.write("<span id='cntdwn' style='background-color:" + backcolor + 
                "; color:" + forecolor + "'></span>");
}

/*Estos son los valores por defecto. Si pones datos inválidos en la configuración, utilizará estos. Son los del script original, sin mis modificaciones.*/

if (typeof(BackColor)=="undefined")
  BackColor = "white";
if (typeof(ForeColor)=="undefined")
  ForeColor= "black";
if (typeof(TargetDate)=="undefined")
  TargetDate = "12/31/2020 5:00 AM";
if (typeof(DisplayFormat)=="undefined")
  DisplayFormat = "%%D%% Days, %%H%% Hours, %%M%% Minutes, %%S%% Seconds.";
if (typeof(CountActive)=="undefined")
  CountActive = true;
if (typeof(FinishMessage)=="undefined")
  FinishMessage = "";
if (typeof(CountStepper)!="number")
  CountStepper = -1;
if (typeof(LeadingZero)=="undefined")
  LeadingZero = true;


CountStepper = Math.ceil(CountStepper);
if (CountStepper == 0)
  CountActive = false;
var SetTimeOutPeriod = (Math.abs(CountStepper)-1)*1000 + 990;
putspan(BackColor, ForeColor);
var dthen = new Date(TargetDate);
var dnow = new Date();
if(CountStepper>0)
  ddiff = new Date(dnow-dthen);
else
  ddiff = new Date(dthen-dnow);
gsecs = Math.floor(ddiff.valueOf()/1000);
CountBack(gsecs);

</script>
Ya tengo gran parte de lo que quería, pero no al 100%. Ahora puedo minimizar bastante mi petición, que se reduciría en...

1.- ¿Como puedo añadir los años?

2.- ¿Y como puedo añadir milisegundos actualizados a tiempo real?

Intentare añadir los años por mi cuenta añadiendo otro "DisplayStr" con el calculo de minutos y segundos correspondientes, no debería ser demasiado difícil.
Ya probé a añadir milisegundos pero claro... actualizandose cada segundo, lo que es una estupidez

Última edición por ThunderWolf; 11/08/2011 a las 09:07 Razón: Logré incluir los años fácilmente. Lo único que me queda son los milisegundos.
  #3 (permalink)  
Antiguo 11/08/2011, 13:19
Avatar de zerokilled
Javascripter
 
Fecha de Ingreso: abril-2009
Ubicación: Isla del Encanto, La Borinqueña [+>==]
Mensajes: 8.050
Antigüedad: 15 años, 2 meses
Puntos: 1485
Respuesta: Cronómetro preciso a partir de fecha

buenas,
tal y como concluyes, el script funciona solo hasta los segundos. para hacerlo funcionar hasta los milisegundos, tendrías que agregar o modificar algunas líneas. algunas de las posibles líneas son:
  • cuando se obtiene la diferencia del tiempo transcurrido o del faltante, no se debe truncar el resultado a segundos. el computo de la variable gsecs.
  • el setTimeout, en lugar de actualizar por segundos, debería actualizar por cierta cantidad de milisegundos. por tanto, debe cambiar el valor de la variable setTimeOutPeriod.
  • puesto que se actualiza por milisegundos, la variable CountStepper debe sumar la transición por milisegundos. lo adecuado sería que el valor de dicha variable sea la misma constante con la que se actualiza el conteo.
  • agregar un nuevo parámetro al string que contiene el formato. por ejemplo, %%ms%% para indicar milisegundos. conjuntamente debes agregar una línea adicional a la función CountBack para detectar el nuevo parámetro. en dicha línea, debes indicar como remplazo la operación necesaria para obtener los milisegundos de la variable local secs. puedes usar la función calcage.
  • nótese que los argumentos pasados a calcage dentro de la función CountBack son a base de segundos. puesto que ahora se calcula en base a milisegundos, los cálculos realizados para obtener cada parte del tiempo deben realizarse a base de milisegundos.

creo que eso es todo lo necesario.
__________________
la maldad es una virtud humana,
y la espiritualidad es la lucha del hombre contra su maldad.
  #4 (permalink)  
Antiguo 11/08/2011, 14:42
Avatar de ThunderWolf  
Fecha de Ingreso: julio-2011
Mensajes: 30
Antigüedad: 13 años
Puntos: 1
Respuesta: Cronómetro preciso a partir de fecha

De veras que agradezco la ayuda, pero sin plantillas con las que orientarme es como si me hablaran en sánscrito. Domino a la perfección el copy&paste, pero mis nociones de JS no van más mucho más allá del "Hola Mundo".

Lo que tengo claro es que en efecto todo el script está basado en segundos, por lo que no puedo determinar con exactitud los días de cada mes; y que manipulando el 990 de SetTimeOutPeriod altero la velocidad a la que se actualiza el contador. En lo que a mi respecta, el problema de los milisegundos sería historia, solo con hallar el valor apropiado para la variable y bajar una unidad de tiempo cada medida.

El script fue diseñado para contar hasta días; lo de meter meses y años ha sido un parcheo pasa salir del paso (efectivo, pero impreciso). Tendrían que añadirse un buen número de condicionantes y variables para implantarle características de calendario y sustraerle tanto cronometraje (eso de que un año tiene 31556926 segundos... es muy relativo).

Me conformo con este script, por ahora. A modo de tiempo orientatívo, aceptamos barco.

Última edición por ThunderWolf; 11/08/2011 a las 14:49
  #5 (permalink)  
Antiguo 12/08/2011, 06:53
Avatar de ThunderWolf  
Fecha de Ingreso: julio-2011
Mensajes: 30
Antigüedad: 13 años
Puntos: 1
Sonrisa Respuesta: Cronómetro PRECISO a partir de fecha

¡Aleluya! ¡Alabado sea Google!

Por fin mis oraciones han sido escuchadas; no las estaba rezando en el idioma apropiado, el ingles. Harto de hacer combinaciones de búsqueda en español, probé a buscar lo mismo pero con tags anglosajones. Descartando los tropecientos códigos basados en segundos, encontré la solución definitiva en el siguiente maravilloso script:

Código Javascript:
Ver original
  1. <script type="text/javascript">
  2. /**********************************************************************************************
  3. * CountUp script by Praveen Lobo (http://PraveenLobo.com/techblog/javascript-countup-timer/)
  4. * This notice MUST stay intact(in both JS file and SCRIPT tag) for legal use.
  5. * http://praveenlobo.com/blog/disclaimer/
  6. **********************************************************************************************/
  7. function CountUp(initDate, id){
  8.     this.beginDate = new Date(initDate);
  9.     this.countainer = document.getElementById(id);
  10.     this.numOfDays = [ 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 ];
  11.     this.borrowed = 0, this.years = 0, this.months = 0, this.days = 0;
  12.     this.hours = 0, this.minutes = 0, this.seconds = 0;
  13.     this.updateNumOfDays();
  14.     this.updateCounter();
  15. }
  16.  
  17. CountUp.prototype.updateNumOfDays=function(){
  18.     var dateNow = new Date();
  19.     var currYear = dateNow.getFullYear();
  20.     if ( (currYear % 4 == 0 && currYear % 100 != 0 ) || currYear % 400 == 0 ) {
  21.         this.numOfDays[1] = 29;
  22.     }
  23.     var self = this;
  24.     setTimeout(function(){self.updateNumOfDays();}, (new Date((currYear+1), 1, 2) - dateNow));
  25. }
  26.  
  27. CountUp.prototype.datePartDiff=function(then, now, MAX){
  28.     var diff = now - then - this.borrowed;
  29.     this.borrowed = 0;
  30.     if ( diff > -1 ) return diff;
  31.     this.borrowed = 1;
  32.     return (MAX + diff);
  33. }
  34.  
  35. CountUp.prototype.calculate=function(){
  36.     var currDate = new Date();
  37.     var prevDate = this.beginDate;
  38.     this.seconds = this.datePartDiff(prevDate.getSeconds(), currDate.getSeconds(), 60);
  39.     this.minutes = this.datePartDiff(prevDate.getMinutes(), currDate.getMinutes(), 60);
  40.     this.hours = this.datePartDiff(prevDate.getHours(), currDate.getHours(), 24);
  41.     this.days = this.datePartDiff(prevDate.getDate(), currDate.getDate(), this.numOfDays[currDate.getMonth()]);
  42.     this.months = this.datePartDiff(prevDate.getMonth(), currDate.getMonth(), 12);
  43.     this.years = this.datePartDiff(prevDate.getFullYear(), currDate.getFullYear(),0);
  44. }
  45.  
  46. CountUp.prototype.addLeadingZero=function(value){
  47.     return value < 10 ? ("0" + value) : value;
  48. }
  49.  
  50. CountUp.prototype.formatTime=function(){
  51.     this.seconds = this.addLeadingZero(this.seconds);
  52.     this.minutes = this.addLeadingZero(this.minutes);
  53.     this.hours = this.addLeadingZero(this.hours);
  54. }
  55.  
  56. CountUp.prototype.updateCounter=function(){
  57.     this.calculate();
  58.     this.formatTime();
  59.     this.countainer.innerHTML ="<strong>" + this.years + "</strong> <small>" + (this.years == 1? "year" : "years") + "</small>" +
  60.         " <strong>" + this.months + "</strong> <small>" + (this.months == 1? "month" : "months") + "</small>" +
  61.         " <strong>" + this.days + "</strong> <small>" + (this.days == 1? "day" : "days") + "</small>" +
  62.         " <strong>" + this.hours + "</strong> <small>" + (this.hours == 1? "hour" : "hours") + "</small>" +
  63.         " <strong>" + this.minutes + "</strong> <small>" + (this.minutes == 1? "minute" : "minutes") + "</small>" +
  64.         " <strong>" + this.seconds + "</strong> <small>" + (this.seconds == 1? "second" : "seconds") + "</small>";
  65.     var self = this;
  66.     setTimeout(function(){self.updateCounter();}, 1000);
  67. }
  68.  
  69. window.onload=function(){ new CountUp('April 16, 2010 19:00:00', 'counter'); }
  70.  
  71. </script>

Como se puede apreciar, no solo distingue entre los meses de 30, 31, y 28 días; ademas toma en consideración los años bisiestos. También utiliza el plural o el singular de la medida según corresponda (en ingles, pero es fácilmente modificable). Y no solo eso; ademas muestra sus resultados en un div para meterle el CSS que más te convenga. :

Código HTML:
Ver original
  1. <div id="counter">Lo que metas aquí aparece solo si hay problemas con el script.</div>

En el sitio de donde lo he extraído (incluido en el script) figuran también contadores regresivos, progresivos como el de este post, o una mezcla de ambos. Ademas indica como poner varios de ellos en la misma página.

El código es tan sencillo que hasta yo que soy negado en Javascript he conseguido añadirle los milisegundos por mi cuenta. Añadiría también las décimas, pero creo que no existe un get. para tal efecto.

Estoy más feliz que un regaliz

Última edición por ThunderWolf; 12/08/2011 a las 09:53 Razón: Perfeccionismo

Etiquetas: cronometro, fecha
Atención: Estás leyendo un tema que no tiene actividad desde hace más de 6 MESES, te recomendamos abrir un Nuevo tema en lugar de responder al actual.
Respuesta




La zona horaria es GMT -6. Ahora son las 13:08.