2012-05-11 23 views
12

Estoy tratando de probar los famosos eventos repetitivos en los calendarios que usan PHP/MySQL. Finalmente encontré algo que parece funcionar. Encontré mi answer here pero estoy teniendo un poco de dificultad para terminarlo.Repetición de eventos de calendario y algunas matemáticas finales

Mi primera tabla 'eventos'.

ID NAME 
1  Sample Event 
2  Another Event 

Mi segunda tabla 'events_meta que almacena los datos repetidos.

ID event_id  meta_key   meta_value 
1  1    repeat_start  1336312800 /* May 7th 2012 */ 
2  1    repeat_interval_1 432000 /* 5 days */ 

Con repeat_start ser una fecha sin tiempo como una marca de tiempo UNIX y repeat_interval una cantidad en segundos entre los intervalos (432 000 es de 5 días).

Tengo el siguiente MySQL que he modificado ligeramente desde el enlace de arriba. La marca de tiempo utilizada a continuación (1299132000, que es el 12 de mayo de 2012) es el día actual sin tiempo.

SELECT EV.* 
FROM `events` EV 
RIGHT JOIN `events_meta` EM1 ON EM1.`event_id` = EV.`id` 
RIGHT JOIN `events_meta` EM2 ON EM2.`meta_key` = CONCAT('repeat_interval_', EM1.`id`) 
WHERE EM1.meta_key = 'repeat_start' 
    AND (
     (CASE (1336744800 - EM1.`meta_value`) 
      WHEN 0 
       THEN 1 
      ELSE (1336744800 - EM1.`meta_value`)/EM2.`meta_value` 
      END 
     ) 
    ) = 1 

En lo anterior MySQL, el siguiente código deduce el campo repeat_start (EM1.'meta_value') a partir de la fecha actual y después lo divide por el campo de intervalo de repetición (EM2.'meta_value').

ELSE (1336744800 - EM1.`meta_value`)/EM2.`meta_value` 

O

TODAYS DATE - START DATE/5 DAYS 

Así que aquí es la matemática:

1336744800 - 1336312800 = 432000 
432000/432000 = 1 

Ahora que funciona perfecto. Pero si cambio de la fecha y hora actual de 5 días por delante para 1336312800 que es Mat 17a 2012, se ve un poco como esto:

1336312800 - 1336312800 = 864000 
86400/432000 = 2 

que no funciona porque es igual a 2 y en el MySQL tiene que ser igual a 1 Así que supongo que mi pregunta es, ¿cómo consigo que MySQL reconozca un número entero en lugar de tener que hacer esto?

... 
WHERE EM1.meta_key = 'repeat_start' 
    AND (
     (CASE (1336744800 - EM1.`meta_value`) 
      WHEN 0 
       THEN 1 
      ELSE (1336744800 - EM1.`meta_value`)/EM2.`meta_value` 
      END 
     ) 
    ) = IN (1,2,3,4,5,6,7,8,....) 

espero estar dando sentido y espero que sea sólo una cosa matemática simple o una función que MySQL tiene que ayudará :) Gracias por su ayuda!

EDIT: LA RESPUESTA

Gracias a @eggypal a continuación, he encontrado mi respuesta y, por supuesto, que era sencillo!

SELECT EV.* 
FROM elvanto_calendars_events AS EV 
RIGHT JOIN elvanto_calendars_events_meta AS EM1 ON EM1.`event_id` = EV.`id` 
RIGHT JOIN elvanto_calendars_events_meta AS EM2 ON EM2.`meta_key` = CONCAT('repeat_interval_', EM1.`id`) 
WHERE EM1.meta_key = 'repeat_start' 
AND ((1336744800 - EM1.`meta_value`) % EM2.`meta_value`) = 0 
+1

La fecha matemática basada en las marcas de tiempo y la cantidad fija de segundos en un día se interrumpirá con el horario de verano. – DCoder

+1

Buena llamada @DCoder. Guardo todas mis veces como GMT y luego uso la función CONVERT_TZ para determinar la fecha 'repeat_start'. Los ejemplos de código anteriores no incluyen este código adicional. Creo que eso debería funcionar bien ¿verdad? –

+0

¿me permitirá su consulta ver el resultado de la fecha de inicio y finalización? '1336744800' parece un día específico :( –

Respuesta

10

no es del todo claro lo que desea su consulta a hacer, pero el jist de su pregunta me hace inclino por lo que sugiere que se mira en la aritmética modular: en SQL, a % b devuelve el resto cuando a se divide por b - si no hay ningún resto (es decir, a % b = 0), entonces a debe ser múltiplo exacto de b.

En su caso, yo creo que está tratando de encontrar eventos donde el tiempo entre el evento de inicio y algunos dada literal es un múltiplo exacto del intervalo del evento: es decir, (literal - event_start) % event_interval = 0. Si no es cero, el valor es el tiempo para la siguiente aparición después de literal (y, por lo tanto, para determinar si la próxima ocurrencia ocurre dentro de un período de tiempo, por ejemplo un día, se probará para ver si el resto es menor que tal constante eg (literal - event_start) % event_interval < 86400).

Si esto no es lo que está buscando, por favor aclare exactamente lo que su consulta está tratando de lograr.

+0

¡Ese es el truco! Logré que funcionara en PHP: 'echo ((strtotime ('2012-05-22 00:00:00') - 1336312800)% 432000);' Intenté usar el '%' en MySQL pero no funcionó. ¿Es su equivalente? –

+0

Lo siento , ignora mi último comentario, funcionó! Editaré mi publicación original con el código final para ayudar a los demás :) –

+0

Empecé a seguirlo y no lo logré. Ayuadame. http://stackoverflow.com/questions/20286332/display-next-event-date – Billa

Cuestiones relacionadas