Jump to content
rjsma

Mostrar a diferença entre a data gravada na bd e a data actual

Recommended Posts

rjsma

Boas malta,

Tenho andado aqui a tentar resolver um problema em que quero mostrar a diferença entre a data armazenada na base de dados e a data actual e se o resultado for mais a 15 minutos( 900 segundos) mostra a imagem de offline. Mas parace que não está a devolver nada da query porque ou aparece sempre offline ou online.

No ficheiro estado tenho a query que calcula a diferença:



//Armazena na variável data_bd a data da última acção do utilizador.
$consulta_data = mysql_query("SELECT status_online from utilizadores where utilizador='".mysql_real_escape_string($_SESSION["utilizador"])."'");
$res = mysql_fetch_assoc($consulta_data);
$data_bd = $res['status_online'];

	//Calcula o intervalo entre a data armazenada no campo status_online e a data actual. 
$calculo_datas = mysql_query("Select TIME_TO_SEC(TIMEDIFF('data_actual','$data_bd'))");
list($intervalo) = mysql_fetch_row($calculo_datas);

Depois para verificar se esta online ou nao, faço da seguinte maneira:


include ("includes/estado.php");
if ($intervalo > 900){ // 900 segundos = 15 minutos
echo "<img width='16px' height='16px' src='imagens/branco.gif' title='Desligado'/>";
}else{
echo "<img width='16px' height='16px' src='imagens/verde.png' title='Ligado'/>";
}

Cumprimentos

Share this post


Link to post
Share on other sites
bar

Depois se conseguires alguém que te consiga resolver isso, diz qualque coisinha  :P


Nem tocam na xixa.

Share this post


Link to post
Share on other sites
brunoais

Isso é uma verificação que devias de fazer só no servidor MySQL ou só no servidor PHP. Eles podem estar com horas diferentes e isso causar problemas nessa parte. Se queres a minha opinião, eu faria isso só no servidor MySQL.


"[Os jovens da actual geração]não lêem porque não envolve um telecomando que dê para mirar e atirar, não falam porque a trapalhice é rainha e o calão é rei" autor: thoga31

Life is a genetically transmitted disease, induced by sex, with death rate of 100%.

Share this post


Link to post
Share on other sites
rjsma

Isso é uma verificação que devias de fazer só no servidor MySQL ou só no servidor PHP. Eles podem estar com horas diferentes e isso causar problemas nessa parte. Se queres a minha opinião, eu faria isso só no servidor MySQL.

:dontgetit: Como assim?Podes explicar melhor, sff?

Share this post


Link to post
Share on other sites
brunoais

Eu já tive esta situação num servidor grátis.

O servidor do site estava em GMT-5 e o servidor MySQL estáva em GMT-7. Estava a testar um código php + SQL que queria usar para um programa meu e ele não estava a funcionar. Eu não percebia porque porque no meu servidor funcionava. Após umas horas (possivelmente mais de 10...) veio-me à cabeça a possibilidade do culpado ser que as horas dos 2 serem diferentes. Acertei em cheio.

Espero que isto ajude a perceber a situação.

Para resolveres esse código consegues usar um solução muito simples:

Junta essas 2 queries em uma para executar esse trabalho. Executas a query à tabela utilizador. BTW para obteres a data atual usa o now()


"[Os jovens da actual geração]não lêem porque não envolve um telecomando que dê para mirar e atirar, não falam porque a trapalhice é rainha e o calão é rei" autor: thoga31

Life is a genetically transmitted disease, induced by sex, with death rate of 100%.

Share this post


Link to post
Share on other sites
rjsma

Eu já tive esta situação num servidor grátis.

O servidor do site estava em GMT-5 e o servidor MySQL estáva em GMT-7. Estava a testar um código php + SQL que queria usar para um programa meu e ele não estava a funcionar. Eu não percebia porque porque no meu servidor funcionava. Após umas horas (possivelmente mais de 10...) veio-me à cabeça a possibilidade do culpado ser que as horas dos 2 serem diferentes. Acertei em cheio.

Espero que isto ajude a perceber a situação.

Para resolveres esse código consegues usar um solução muito simples:

Junta essas 2 queries em uma para executar esse trabalho. Executas a query à tabela utilizador. BTW para obteres a data atual usa o now()

Desculpa lá a minha burrice, estas a sugerir que transforme estas 2 queries em 1?No select qu estou a usar o timediff não está a retorna um valor inteiro mas sim resource #6, ja experimentei o select no phpmyadmin e funciona correctamente, pensava que bastava usar o mysql_fetch_row no php para conseguir buscar  o resultado do select.

        
        //Armazena na variável data_bd a data da última acção do utilizador.
        $consulta_data = mysql_query("SELECT status_online from utilizadores where utilizador='".mysql_real_escape_string($_SESSION["utilizador"])."'");
        $res = mysql_fetch_assoc($consulta_data);
        $data_bd = $res['status_online'];
         
        //Calcula o intervalo entre a data armazenada no campo status_online e a data actual. 
        $calculo_datas = mysql_query("Select TIME_TO_SEC(TIMEDIFF('data_actual','$data_bd'))");
        list($intervalo) = mysql_fetch_row($calculo_datas);

E também estas a disser que devo fazer esta verificação em mysql? :dontgetit:

include ("includes/estado.php");
if ($intervalo > 900){ // 900 segundos = 15 minutos
echo "<img width='16px' height='16px' src='imagens/branco.gif' title='Desligado'/>";
}else{
echo "<img width='16px' height='16px' src='imagens/verde.png' title='Ligado'/>";
}

Cumprimentos

Share this post


Link to post
Share on other sites
brunoais

Desculpa lá a minha burrice, estas a sugerir que transforme estas 2 queries em 1?

Sim. E isso faz-se com muita facilidade tendo em conta que não existe um from na 2ª query.

No select qu estou a usar o timediff não está a retorna um valor inteiro mas sim resource #6, ja experimentei o select no phpmyadmin e funciona correctamente, pensava que bastava usar o mysql_fetch_row no php para conseguir buscar  o resultado do select.

Isso que afirmas é verdade. É necessário usar uma das mysql_fetch_* (no teu caso, usaste o assoc no 1º e o row no 2º). Mas o mysql tb tem maneiras de fazer cálculos e retornar verdadeiro (1) ou falso (0).

        
        //Armazena na variável data_bd a data da última acção do utilizador.
        $consulta_data = mysql_query("SELECT status_online from utilizadores where utilizador='".mysql_real_escape_string($_SESSION["utilizador"])."'");
        $res = mysql_fetch_assoc($consulta_data);
        $data_bd = $res['status_online'];
         
        //Calcula o intervalo entre a data armazenada no campo status_online e a data actual. 
        $calculo_datas = mysql_query("Select TIME_TO_SEC(TIMEDIFF('data_actual','$data_bd'))");
        list($intervalo) = mysql_fetch_row($calculo_datas);

Com um pouco de pensamento, consegues juntar isto num só e por o mysql_fetch_assoc() a retornar exatamente o que queres.

É importante usares o AS para que tudo fique a funcionar de uma maneira lógica e fácil de perceber :P . Se nunca o usaste, isso pode ser a causa de não teres percebido a minha afirmação de juntar os 2.

E também estas a disser que devo fazer esta verificação em mysql? :dontgetit:

include ("includes/estado.php");
if ($intervalo > 900){ // 900 segundos = 15 minutos
echo "<img width='16px' height='16px' src='imagens/branco.gif' title='Desligado'/>";
}else{
echo "<img width='16px' height='16px' src='imagens/verde.png' title='Ligado'/>";
}

Cumprimentos

Sim. O MySQL verifica essa condição e irá retornar 1 ou 0. Usando esse número poderás aplicar a esse if para executar um desses códigos.


"[Os jovens da actual geração]não lêem porque não envolve um telecomando que dê para mirar e atirar, não falam porque a trapalhice é rainha e o calão é rei" autor: thoga31

Life is a genetically transmitted disease, induced by sex, with death rate of 100%.

Share this post


Link to post
Share on other sites
rjsma

O que ainda me está  fazer um pouco de confusão é esse assunto das diferenças horarias. Porque no campo status online(variavel $data_bd) está armazenada a data da ultima acção do utilizador que foi inserido atraves do php ( date("Y-M-Y H:i:s") por isso está com o horario da europa, agora se ir comparar com a funcao NOW() no mysql deverá estar com o horario americano.Por isso penso que continua a existir o mesmo problema mesmo que faça essa queries que sugeriste.

Por acaso o meu pensamento descrito em cima esteja vou tentar fazer essa querie, como disseste e muito bem nunca tinha usado nem sabia que existia essa funcao (AS) não percebi muito bem o que faz o AS achei muito confuso a explicação e tambem estar em ingles não ajuda.

Podias dizer se é mais ou menos isto:

SELECT status_online from utilizadores where utilizador='".mysql_real_escape_string($_SESSION["utilizador"]"' AS TIME_TO_SEC(TIMEDIFF('NOW()','status_online'))

Share this post


Link to post
Share on other sites
brunoais

para resolver esse problema de diferenças horárias tens:

http://dev.mysql.com/doc/refman/5.5/en/date-and-time-functions.html#function_convert-tz

e tens:

http://dev.mysql.com/doc/refman/5.5/en/date-and-time-functions.html#function_utc-timestamp

Trabalhas na DB a usar o UTC_TIMESTAMP() em vez do now() (ambos são igualmente rápidos) e envolves os 2 nisto:

CONVERT_TZ(status_online,'+00:00','+10:00');

substituindo o: +10:00 para uma hora que faça sentido.

E tb, usando isto podes ter cada utilizador a usar a sua própria hora. Cada um pode receber uma hora diferente dependendo da sua hora local, basta:

CONVERT_TZ(status_online,'+00:00','$horaLocal:00');

em que $horaLocal contém uma string no formato: (+|-)[0-9][0-9]

Podias dizer se é mais ou menos isto:

SELECT status_online from utilizadores where utilizador='".mysql_real_escape_string($_SESSION["utilizador"]"' AS TIME_TO_SEC(TIMEDIFF('NOW()','status_online'))

Não... algo mais:

SELECT status_online, TIME_TO_SEC(TIMEDIFF('NOW()','status_online')) AS timeDiff, (TIME_TO_SEC(TIMEDIFF('NOW()','status_online')) > 7000 ) AS isOffline  from utilizadores where utilizador='".mysql_real_escape_string($_SESSION["utilizador"]"'

N sei se pus coisas a mais aqui mas acho q esta query dá para perceber a ideia que eu quero passar. Há uma parte q n sei se dá erro de sintaxe, só experimentando.


"[Os jovens da actual geração]não lêem porque não envolve um telecomando que dê para mirar e atirar, não falam porque a trapalhice é rainha e o calão é rei" autor: thoga31

Life is a genetically transmitted disease, induced by sex, with death rate of 100%.

Share this post


Link to post
Share on other sites
rjsma

Já estou a começar a apanhar as coisas.

SELECT status_online, TIME_TO_SEC(TIMEDIFF('NOW()','status_online')) AS timeDiff,(TIME_TO_SEC(TIMEDIFF('NOW()','status_online')) > 7000 ) AS isOffline  from utilizadores where utilizador='".mysql_real_escape_string($_SESSION["utilizador"]"'

Portanto nesta query vai sair a data e hora da ultima acção do utilizador e se esta offline ou online (0 e 1 respectivamente).

Fiz um teste no phpmyadmin e saiu o seguinte output:

http://imageshack.us/f/685/dgfdg.jpg/

Penso que no isoffline deveria aparecer 1 e não compreendi o campo timeDiff(será a diferença entre as datas)?

Enganei-me estou a gravar a ultima accao do utilizador no mysql

UPDATE utilizadores set status_online=NOW() where utilizador='".mysql_real_escape_string($_SESSION["utilizador"])."'"

Sendo assim ainda é preciso fazer essas conversoes horarias?

Share this post


Link to post
Share on other sites
brunoais

Sendo assim ainda é preciso fazer essas conversoes horarias?

Sem problemas. Basta alterar o que interessa :P

Começando aqui:

UPDATE utilizadores set status_online=NOW() where utilizador='".mysql_real_escape_string($_SESSION["utilizador"])."'"

Aonde está now() é UTC_TIMESTAMP()

Assim até acelera um pouco as coisas porque não precisa de executar conversões nem guardar dados de conversão na DB (ele guarda timestamps sempre em GMT e converte automaticamente quando se usa o select).

e na parte de:

SELECT status_online, TIME_TO_SEC(TIMEDIFF('NOW()','status_online')) AS timeDiff,(TIME_TO_SEC(TIMEDIFF('NOW()','status_online')) > 7000 ) AS isOffline  from utilizadores where utilizador='".mysql_real_escape_string($_SESSION["utilizador"]"'

Só reparei aqui que tens o now() entre plicas. Isso está a fazem com q ele não execute a função. Isso provoca que ele retorne 0 (erro).

Então, aonde está (incluindo as aspas):

'NOW()'

deve estar:

UTC_TIMESTAMP()

e na parte de:

SELECT status_online

envolvendo o:

status_online

usas o CONVERT_TZ(,'GMT','(o tempo para transformar)');

para obteres o tempo da maneira que quiseres.

Se só usavas o status_online para usar depois o timediff, podes esquecer usar isto e trabalhar só com os outros 2.

e tudo deve ficar bem de pois de alguma resincronização (o utilizador correspondente ficar online).


"[Os jovens da actual geração]não lêem porque não envolve um telecomando que dê para mirar e atirar, não falam porque a trapalhice é rainha e o calão é rei" autor: thoga31

Life is a genetically transmitted disease, induced by sex, with death rate of 100%.

Share this post


Link to post
Share on other sites
bLACKLOTUS90

Fiz algo parecido à pouco tempo, pode ser que te ajude:

Sempre que é feito qualquer request ao server:

if(isset($_SESSION['GDE']['ID'])) $dbObj -> query("UPDATE ut_attr_website SET ult_click='".date('Y-m-d H:i:s')."', ligado='1' WHERE id='".$_SESSION['GDE']['ID']."'") or die($erObj->report($dbObj->error));

Se a session estiver inicializada, faço um update e meto o ult_click com a data actual.

$qry = $dbObj -> query("SELECT utilizador FROM utilizadores u LEFT OUTER JOIN ut_attr_website wu ON u.id = wu.id WHERE ult_click > '".date("Y-m-d H:i:s", mktime (date("H"),date("i")-5,date("s"),date("m"),date("d"),date("Y")))."' AND ligado = '1'");
while($row = mysql_fetch_array($qry,MYSQL_BOTH)) {
   $users[] = $row['utilizador'];
}

Depois verifico quais são os users que o ult_click foi feito à 5min ou depois.

Este exemplo não é bem o que pretendes (aqui quero ver quais são os users que estão ligados), mas dá para tirares uma ideia.


# Catholic programmingif(!defined('GOD')) die();

Share this post


Link to post
Share on other sites
rjsma

Portanto no select do status online fica assim:


UPDATE utilizadores set status_online=UTC_TIMESTAMP() where utilizador='".mysql_real_escape_string($_SESSION["utilizador"])."'

Depois aqui penso que seja isto:


SELECT CONVERT_TZ(status_online,'+01:00') TIME_TO_SEC(TIMEDIFF(UTC_TIMESTAMP(),'status_online')) AS timeDiff,(TIME_TO_SEC(TIMEDIFF('NOW()','status_online')) > 7000 ) AS isOffline  from utilizadores where utilizador='".mysql_real_escape_string($_SESSION["utilizador"]"'

No 1 select está a retornar a hora com 1 hora em atraso ( agora é 11:40 então está-me a gravar com 10:40).

Será necessário usar tambem o CONVERT_TZ nesse select? Como já estou a fazer no 2 select não sei se será util.

Share this post


Link to post
Share on other sites
bLACKLOTUS90

No 1 select está a retornar a hora com 1 hora em atraso ( agora é 11:40 então está-me a gravar com 10:40).

Isso porque o servidor têm o timezone em UTC. se fores ao php.ini e mudares o date.timezone para Europe/London, esse 'problema' acaba :P


# Catholic programmingif(!defined('GOD')) die();

Share this post


Link to post
Share on other sites
brunoais

Portanto no select do status online fica assim:


UPDATE utilizadores set status_online=UTC_TIMESTAMP() where utilizador='".mysql_real_escape_string($_SESSION["utilizador"])."'

Correto

Depois aqui penso que seja isto:


SELECT CONVERT_TZ(status_online,'+01:00') TIME_TO_SEC(TIMEDIFF(UTC_TIMESTAMP(),'status_online')) AS timeDiff,(TIME_TO_SEC(TIMEDIFF('NOW()','status_online')) > 7000 ) AS isOffline  from utilizadores where utilizador='".mysql_real_escape_string($_SESSION["utilizador"]"'

Errado. Tens aí, pelo menos, um erro de sintaxe:

CONVERT_TZ(status_online,'+01:00')

é

CONVERT_TZ(status_online, '+00:00', '+01:00')

No 1 select está a retornar a hora com 1 hora em atraso ( agora é 11:40 então está-me a gravar com 10:40).

Será necessário usar tambem o CONVERT_TZ nesse select? Como já estou a fazer no 2 select não sei se será util.

Não percebi...

NOTA:O gmt não tem hora de verão nem de inverno. Quando convertes tens q ter isso em conta :P .

Isso porque o servidor têm o timezone em UTC. se fores ao php.ini e mudares o date.timezone para Europe/London, esse 'problema' acaba :)

Bem... Eu sempre trabalhei para programas que não permitem fazer isso e todas as ajudas q dou é para isso mesmo. Fazer algo que funciona no máximo número de servidores possível. Isso pode ser solução mas não está no meu "dicionário de resoluções de problemas".


"[Os jovens da actual geração]não lêem porque não envolve um telecomando que dê para mirar e atirar, não falam porque a trapalhice é rainha e o calão é rei" autor: thoga31

Life is a genetically transmitted disease, induced by sex, with death rate of 100%.

Share this post


Link to post
Share on other sites
rjsma

SELECT CONVERT_TZ(status_online, '+00:00', '+01:00') TIME_TO_SEC(TIMEDIFF(UTC_TIMESTAMP(),'status_online')) AS timeDiff,(TIME_TO_SEC(TIMEDIFF('NOW()','status_online')) > 7000 ) AS isOffline  from utilizadores where utilizador='".mysql_real_escape_string($_SESSION["utilizador"]"'

Neste select, alterei conforme dizeste mas está a ter um problema de sintaxe, já confirmei os parenteses e as aspas e está tudo no sitio.

UPDATE utilizadores set status_online=UTC_TIMESTAMP() where utilizador='".mysql_real_escape_string($_SESSION["utilizador"])."'

Aqui está a gravar a data com 1 hora de atraso, por exemplo agora é 12:20 grava como 11:20.O que tinha perguntado se valha a pena usar o CONVERT_TZ para adicionar 1 hora nesta query.

Share this post


Link to post
Share on other sites
brunoais

SELECT CONVERT_TZ(status_online, '+00:00', '+01:00') TIME_TO_SEC(TIMEDIFF(UTC_TIMESTAMP(),'status_online')) AS timeDiff,(TIME_TO_SEC(TIMEDIFF('NOW()','status_online')) > 7000 ) AS isOffline  from utilizadores where utilizador='".mysql_real_escape_string($_SESSION["utilizador"]"'

Neste select, alterei conforme dizeste mas está a ter um problema de sintaxe, já confirmei os parenteses e as aspas e está tudo no sitio.

Sempre que existe um erro desses é extremamente útil saber qual é a mensagem de erro que o sistema indica. Poupa imenso trabalho para corrigir erros.

UPDATE utilizadores set status_online=UTC_TIMESTAMP() where utilizador='".mysql_real_escape_string($_SESSION["utilizador"])."'

Aqui está a gravar a data com 1 hora de atraso, por exemplo agora é 12:20 grava como 11:20.O que tinha perguntado se valha a pena usar o CONVERT_TZ para adicionar 1 hora nesta query.

Faz como quiseres. Simplesmente mantém em conta que se usares aí vais ter que atualizar as outras queries para se adaptarem ao novo tempo (algo que atrasa bastante as queries se usado em demasia).


"[Os jovens da actual geração]não lêem porque não envolve um telecomando que dê para mirar e atirar, não falam porque a trapalhice é rainha e o calão é rei" autor: thoga31

Life is a genetically transmitted disease, induced by sex, with death rate of 100%.

Share this post


Link to post
Share on other sites
rjsma

Sempre que existe um erro desses é extremamente útil saber qual é a mensagem de erro que o sistema indica. Poupa imenso trabalho para corrigir erros.Faz como quiseres. Simplesmente mantém em conta que se usares aí vais ter que atualizar as outras queries para se adaptarem ao novo tempo (algo que atrasa bastante as queries se usado em demasia).

O erro que aparece é o seguinte:

#1064 - You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'TIME_TO_SEC(TIMEDIFF(UTC_TIMESTAMP(),'status_online')) AS timeDiff,(TIME_TO_SEC(' at line 1

O que acha que pode ser?

Share this post


Link to post
Share on other sites
brunoais

falta uma vírgula antes da string q aparece aí.


"[Os jovens da actual geração]não lêem porque não envolve um telecomando que dê para mirar e atirar, não falam porque a trapalhice é rainha e o calão é rei" autor: thoga31

Life is a genetically transmitted disease, induced by sex, with death rate of 100%.

Share this post


Link to post
Share on other sites
rjsma

Sim, tinhas razão.

Olha o isoffline recebe sempre um valor o ou 1, certo? Neste output saiu um o que calculo corresponde a offline e as diferenças de tempo era de segundos quando testei no phpmyadmin.O timeDiff tem um valor nulo que presumo o resultado deveria ser a diferença entre as datas em segundos.Portanto deve ser algum erro na parte onde utilizo a função TIMEDIFF.

http://imageshack.us/f/535/semttulold.jpg/

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×
×
  • Create New...

Important Information

By using this site you accept our Terms of Use and Privacy Policy. We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.