Como trabalhar com datas do Moodle em consultas SQL

O Moodle armazena grande parte das datas no banco de dados como Unix timestamp, ou seja, um número inteiro que representa a quantidade de segundos transcorridos desde 1º de janeiro de 1970. Para exibir essas informações em relatórios SQL, é necessário converter o valor para um formato de data e hora legível.

Neste tutorial, você aprenderá como formatar datas do Moodle, tratar valores zerados, filtrar registros por período e calcular intervalos de tempo usando consultas SQL no MySQL ou MariaDB.

Como as datas são armazenadas no Moodle

Nas tabelas do Moodle, é comum encontrar campos como:

  • timecreated: data de criação do registro;
  • timemodified: data da última alteração;
  • lastaccess: data do último acesso;
  • firstaccess: data do primeiro acesso;
  • timestart: data inicial;
  • timeend: data final;
  • timecompleted: data de conclusão;
  • timefinish: data de finalização;
  • timesubmitted: data de envio de uma atividade.

Esses campos normalmente armazenam valores semelhantes ao seguinte:

1752865200

Esse número precisa ser convertido para uma data antes de ser apresentado em um relatório.

Formatar datas do Moodle com FROM_UNIXTIME

No MySQL e no MariaDB, a função FROM_UNIXTIME() converte um Unix timestamp para um valor de data e hora.

A consulta abaixo retorna a data e a hora do último acesso do usuário com o ID 2:

SELECT
    id,
    firstname,
    lastname,
    FROM_UNIXTIME(lastaccess, '%d/%m/%Y %H:%i:%s') AS ultimo_acesso
FROM mdl_user
WHERE id = 2;

O resultado será semelhante a:

2 | Administrador | Moodle | 18/07/2026 14:35:20

Os caracteres utilizados na formatação representam:

  • %d: dia com dois dígitos;
  • %m: mês com dois dígitos;
  • %Y: ano com quatro dígitos;
  • %H: hora no formato de 24 horas;
  • %i: minutos;
  • %s: segundos.

Para relatórios brasileiros, um dos formatos mais utilizados é:

%d/%m/%Y %H:%i:%s

Erro comum ao utilizar FROM_UNIXTIME no WHERE

A função FROM_UNIXTIME() não deve ser utilizada isoladamente dentro da cláusula WHERE, pois ela apenas converte o valor e não cria uma condição de comparação.

A consulta abaixo está incorreta:

SELECT *
FROM mdl_user
WHERE FROM_UNIXTIME(lastaccess, '%d/%m/%Y %H:%i:%s')
AND id = 2;

Além de não comparar a data com nenhum valor, aplicar funções diretamente sobre a coluna dentro do WHERE pode impedir o uso eficiente de índices em consultas maiores.

Para apenas exibir a data formatada, utilize a função no SELECT:

SELECT
    id,
    username,
    firstname,
    lastname,
    FROM_UNIXTIME(lastaccess, '%d/%m/%Y %H:%i:%s') AS ultimo_acesso
FROM mdl_user
WHERE id = 2;

Tratar datas com valor zero no Moodle

Em várias tabelas do Moodle, o valor 0 indica que determinado evento ainda não aconteceu. Um usuário que nunca acessou a plataforma, por exemplo, pode ter o campo lastaccess igual a zero.

Para evitar que o relatório apresente uma data correspondente ao início da época Unix, utilize uma expressão CASE:

SELECT
    id,
    firstname,
    lastname,
    CASE
        WHEN lastaccess = 0 THEN 'Nunca acessou'
        ELSE FROM_UNIXTIME(lastaccess, '%d/%m/%Y %H:%i:%s')
    END AS ultimo_acesso
FROM mdl_user
ORDER BY lastname, firstname;

Também é possível retornar NULL quando a data estiver zerada:

SELECT
    id,
    firstname,
    lastname,
    FROM_UNIXTIME(
        NULLIF(lastaccess, 0),
        '%d/%m/%Y %H:%i:%s'
    ) AS ultimo_acesso
FROM mdl_user;

A função NULLIF(lastaccess, 0) transforma o valor zero em NULL. Dessa forma, FROM_UNIXTIME() também retorna NULL.

Consultar usuários pelo período do último acesso

Para localizar usuários que acessaram o Moodle depois de uma data específica, converta a data informada para Unix timestamp com a função UNIX_TIMESTAMP().

Usuários que acessaram depois de uma data

SELECT
    id,
    firstname,
    lastname,
    email,
    FROM_UNIXTIME(lastaccess, '%d/%m/%Y %H:%i:%s') AS ultimo_acesso
FROM mdl_user
WHERE deleted = 0
  AND suspended = 0
  AND lastaccess >= UNIX_TIMESTAMP('2026-07-01 00:00:00')
ORDER BY lastaccess DESC;

Usuários que acessaram dentro de um período

SELECT
    id,
    firstname,
    lastname,
    email,
    FROM_UNIXTIME(lastaccess, '%d/%m/%Y %H:%i:%s') AS ultimo_acesso
FROM mdl_user
WHERE deleted = 0
  AND lastaccess >= UNIX_TIMESTAMP('2026-07-01 00:00:00')
  AND lastaccess < UNIX_TIMESTAMP('2026-08-01 00:00:00')
ORDER BY lastaccess DESC;

O uso de uma data inicial inclusiva e uma data final exclusiva evita problemas com horários, minutos e segundos do último dia do período.

Também é recomendável comparar diretamente o campo numérico com o timestamp. Essa abordagem permite que o banco utilize um índice existente no campo, quando disponível.

Localizar usuários que nunca acessaram o Moodle

Para encontrar contas que nunca registraram acesso, filtre o campo lastaccess pelo valor zero:

SELECT
    id,
    username,
    firstname,
    lastname,
    email,
    FROM_UNIXTIME(timecreated, '%d/%m/%Y %H:%i:%s') AS data_cadastro
FROM mdl_user
WHERE deleted = 0
  AND lastaccess = 0
ORDER BY timecreated DESC;

Essa consulta pode ser útil para identificar usuários cadastrados que ainda não entraram no ambiente virtual.

Consultar usuários inativos há determinado número de dias

Para localizar usuários que não acessam o Moodle há mais de 30 dias, compare o campo lastaccess com o timestamp correspondente à data atual menos 30 dias:

SELECT
    id,
    firstname,
    lastname,
    email,
    FROM_UNIXTIME(lastaccess, '%d/%m/%Y %H:%i:%s') AS ultimo_acesso
FROM mdl_user
WHERE deleted = 0
  AND suspended = 0
  AND lastaccess > 0
  AND lastaccess < UNIX_TIMESTAMP(DATE_SUB(NOW(), INTERVAL 30 DAY))
ORDER BY lastaccess ASC;

Para alterar o período, substitua 30 DAY pelo intervalo desejado.

Calcular há quantos dias ocorreu o último acesso

A função TIMESTAMPDIFF() pode ser utilizada para calcular a diferença entre o último acesso e a data atual:

SELECT
    id,
    firstname,
    lastname,
    FROM_UNIXTIME(lastaccess, '%d/%m/%Y %H:%i:%s') AS ultimo_acesso,
    TIMESTAMPDIFF(
        DAY,
        FROM_UNIXTIME(lastaccess),
        NOW()
    ) AS dias_sem_acesso
FROM mdl_user
WHERE deleted = 0
  AND lastaccess > 0
ORDER BY dias_sem_acesso DESC;

O campo calculado dias_sem_acesso mostra a quantidade de dias transcorridos desde o último acesso do usuário.

Formatar a data de criação do usuário

O campo timecreated da tabela mdl_user registra quando a conta foi criada:

SELECT
    id,
    username,
    firstname,
    lastname,
    FROM_UNIXTIME(timecreated, '%d/%m/%Y %H:%i:%s') AS data_cadastro
FROM mdl_user
WHERE deleted = 0
ORDER BY timecreated DESC;

Consultar datas de acesso por curso

O campo lastaccess da tabela mdl_user representa o último acesso geral do usuário ao Moodle. Para consultar o último acesso dentro de cada curso, utilize a tabela mdl_user_lastaccess.

SELECT
    u.id AS usuario_id,
    CONCAT(u.firstname, ' ', u.lastname) AS usuario,
    c.id AS curso_id,
    c.fullname AS curso,
    CASE
        WHEN ula.timeaccess = 0 THEN 'Sem acesso registrado'
        ELSE FROM_UNIXTIME(ula.timeaccess, '%d/%m/%Y %H:%i:%s')
    END AS ultimo_acesso_curso
FROM mdl_user_lastaccess ula
INNER JOIN mdl_user u
    ON u.id = ula.userid
INNER JOIN mdl_course c
    ON c.id = ula.courseid
WHERE u.deleted = 0
ORDER BY ula.timeaccess DESC;

Consultar datas de matrícula nos cursos

As matrículas dos usuários são registradas na tabela mdl_user_enrolments. O campo timecreated indica quando o vínculo de matrícula foi criado.

SELECT
    u.id AS usuario_id,
    CONCAT(u.firstname, ' ', u.lastname) AS usuario,
    c.id AS curso_id,
    c.fullname AS curso,
    FROM_UNIXTIME(ue.timecreated, '%d/%m/%Y %H:%i:%s') AS data_matricula,
    CASE
        WHEN ue.timestart = 0 THEN NULL
        ELSE FROM_UNIXTIME(ue.timestart, '%d/%m/%Y %H:%i:%s')
    END AS inicio_matricula,
    CASE
        WHEN ue.timeend = 0 THEN 'Sem data de término'
        ELSE FROM_UNIXTIME(ue.timeend, '%d/%m/%Y %H:%i:%s')
    END AS fim_matricula
FROM mdl_user_enrolments ue
INNER JOIN mdl_enrol e
    ON e.id = ue.enrolid
INNER JOIN mdl_course c
    ON c.id = e.courseid
INNER JOIN mdl_user u
    ON u.id = ue.userid
WHERE u.deleted = 0
ORDER BY ue.timecreated DESC;

Consultar datas de conclusão de curso

A tabela mdl_course_completions armazena informações relacionadas à conclusão dos cursos. O campo timecompleted contém a data de conclusão, quando o usuário atende aos critérios configurados no curso.

SELECT
    u.id AS usuario_id,
    CONCAT(u.firstname, ' ', u.lastname) AS usuario,
    c.id AS curso_id,
    c.fullname AS curso,
    CASE
        WHEN cc.timecompleted IS NULL OR cc.timecompleted = 0
            THEN 'Curso não concluído'
        ELSE FROM_UNIXTIME(cc.timecompleted, '%d/%m/%Y %H:%i:%s')
    END AS data_conclusao
FROM mdl_course_completions cc
INNER JOIN mdl_user u
    ON u.id = cc.userid
INNER JOIN mdl_course c
    ON c.id = cc.course
WHERE u.deleted = 0
ORDER BY cc.timecompleted DESC;

Consultar a data de envio de tarefas

Nas versões atuais do Moodle, as tarefas são armazenadas principalmente nas tabelas mdl_assign e mdl_assign_submission.

A consulta abaixo retorna a data de criação e a data da última modificação de cada envio:

SELECT
    a.id AS atividade_id,
    a.name AS atividade,
    c.fullname AS curso,
    u.id AS usuario_id,
    CONCAT(u.firstname, ' ', u.lastname) AS usuario,
    s.status,
    FROM_UNIXTIME(s.timecreated, '%d/%m/%Y %H:%i:%s') AS data_criacao_envio,
    FROM_UNIXTIME(s.timemodified, '%d/%m/%Y %H:%i:%s') AS ultima_modificacao
FROM mdl_assign_submission s
INNER JOIN mdl_assign a
    ON a.id = s.assignment
INNER JOIN mdl_course c
    ON c.id = a.course
INNER JOIN mdl_user u
    ON u.id = s.userid
WHERE u.deleted = 0
ORDER BY s.timemodified DESC;

Consultar datas das tentativas de questionários

A tabela mdl_quiz_attempts registra as tentativas realizadas nos questionários. Entre os principais campos de data estão timestart, timefinish e timemodified.

SELECT
    q.id AS questionario_id,
    q.name AS questionario,
    c.fullname AS curso,
    u.id AS usuario_id,
    CONCAT(u.firstname, ' ', u.lastname) AS usuario,
    qa.attempt AS tentativa,
    qa.state AS situacao,
    FROM_UNIXTIME(qa.timestart, '%d/%m/%Y %H:%i:%s') AS inicio,
    CASE
        WHEN qa.timefinish = 0 THEN 'Tentativa não finalizada'
        ELSE FROM_UNIXTIME(qa.timefinish, '%d/%m/%Y %H:%i:%s')
    END AS termino
FROM mdl_quiz_attempts qa
INNER JOIN mdl_quiz q
    ON q.id = qa.quiz
INNER JOIN mdl_course c
    ON c.id = q.course
INNER JOIN mdl_user u
    ON u.id = qa.userid
WHERE u.deleted = 0
ORDER BY qa.timestart DESC;

Consultar datas dos registros de log

Nas versões atuais do Moodle, os logs de eventos normalmente são armazenados na tabela mdl_logstore_standard_log. O campo timecreated registra quando o evento aconteceu.

SELECT
    l.id,
    l.userid,
    CONCAT(u.firstname, ' ', u.lastname) AS usuario,
    l.eventname,
    l.action,
    l.target,
    l.objecttable,
    l.objectid,
    l.ip,
    FROM_UNIXTIME(l.timecreated, '%d/%m/%Y %H:%i:%s') AS data_evento
FROM mdl_logstore_standard_log l
LEFT JOIN mdl_user u
    ON u.id = l.userid
ORDER BY l.timecreated DESC
LIMIT 100;

Para limitar a consulta aos eventos dos últimos sete dias:

SELECT
    l.id,
    l.userid,
    CONCAT(u.firstname, ' ', u.lastname) AS usuario,
    l.eventname,
    l.action,
    l.target,
    FROM_UNIXTIME(l.timecreated, '%d/%m/%Y %H:%i:%s') AS data_evento
FROM mdl_logstore_standard_log l
LEFT JOIN mdl_user u
    ON u.id = l.userid
WHERE l.timecreated >= UNIX_TIMESTAMP(DATE_SUB(NOW(), INTERVAL 7 DAY))
ORDER BY l.timecreated DESC;

Atenção aos nomes das tabelas do Moodle

Alguns nomes de tabelas encontrados em tutoriais antigos não correspondem às tabelas utilizadas nas versões atuais do Moodle.

  • mdl_user_students não é a tabela padrão para identificar estudantes. Matrículas e funções devem ser consultadas por meio de tabelas como mdl_user_enrolments, mdl_enrol, mdl_role_assignments e mdl_context.
  • mdl_log pertence ao sistema de logs legado. Em instalações atuais, normalmente é utilizada mdl_logstore_standard_log.
  • mdl_assignement está escrito incorretamente. A tabela atual da atividade de tarefa é mdl_assign.
  • mdl_assignment_submissions pertence ao módulo antigo de tarefas. Nas versões atuais, a tabela normalmente utilizada é mdl_assign_submission.
  • mdl_message_reads não deve ser considerado um nome universal nas versões atuais, pois o subsistema de mensagens passou por alterações entre versões.

Antes de criar um relatório, confirme os nomes e campos disponíveis na versão instalada do Moodle.

O prefixo das tabelas pode ser diferente de mdl_

O prefixo mdl_ é o padrão mais conhecido, mas pode ter sido alterado durante a instalação do Moodle.

O prefixo utilizado pelo ambiente está definido no arquivo config.php:

$CFG->prefix = 'mdl_';

Caso a instalação utilize outro prefixo, adapte as consultas. Por exemplo, uma tabela chamada mdl_user pode estar registrada como moodle_user ou ead_user.

Atenção ao fuso horário

A função FROM_UNIXTIME() utiliza o fuso horário configurado na sessão do MySQL. Portanto, a data apresentada diretamente pelo banco pode ser diferente da data mostrada na interface do Moodle.

Para verificar o fuso horário da sessão e do servidor MySQL, execute:

SELECT
    @@SESSION.time_zone AS fuso_sessao,
    @@global.time_zone AS fuso_global,
    NOW() AS data_atual_mysql;

Quando o Moodle, o PHP e o banco utilizam configurações diferentes de fuso horário, podem ocorrer diferenças de algumas horas nos relatórios.

Não altere o fuso horário global do banco sem avaliar o impacto sobre as outras aplicações que utilizam o mesmo servidor.

Compatibilidade com PostgreSQL

A função FROM_UNIXTIME() é específica do MySQL e do MariaDB. Em uma instalação do Moodle com PostgreSQL, utilize a função TO_TIMESTAMP().

SELECT
    id,
    firstname,
    lastname,
    TO_CHAR(
        TO_TIMESTAMP(lastaccess),
        'DD/MM/YYYY HH24:MI:SS'
    ) AS ultimo_acesso
FROM mdl_user
WHERE id = 2;

Para filtrar por data no PostgreSQL, utilize EXTRACT(EPOCH FROM ...):

SELECT
    id,
    firstname,
    lastname,
    TO_CHAR(
        TO_TIMESTAMP(lastaccess),
        'DD/MM/YYYY HH24:MI:SS'
    ) AS ultimo_acesso
FROM mdl_user
WHERE lastaccess >= EXTRACT(
    EPOCH FROM TIMESTAMP '2026-07-01 00:00:00'
);

Validação das consultas

Para validar uma consulta que trabalha com datas do Moodle:

  1. Execute inicialmente a consulta para apenas um usuário ou curso conhecido.
  2. Compare a data retornada pelo SQL com a informação apresentada na interface do Moodle.
  3. Verifique se o campo possui valor zero ou NULL.
  4. Confirme o fuso horário do banco de dados.
  5. Confira se o prefixo das tabelas é realmente mdl_.
  6. Antes de executar relatórios grandes, teste a consulta com um LIMIT.

Um teste simples pode ser realizado com:

SELECT
    id,
    firstname,
    lastname,
    lastaccess AS timestamp_original,
    FROM_UNIXTIME(lastaccess, '%d/%m/%Y %H:%i:%s') AS data_formatada
FROM mdl_user
WHERE lastaccess > 0
ORDER BY lastaccess DESC
LIMIT 10;

O campo timestamp_original permite comparar o número armazenado com a data convertida.

Problemas comuns ao consultar datas do Moodle

A data retorna 01/01/1970

Esse resultado geralmente ocorre quando o campo contém o valor zero. Utilize CASE ou NULLIF() para tratar registros que ainda não possuem uma data válida.

A data está algumas horas adiantada ou atrasada

Verifique o fuso horário do Moodle, do PHP e da sessão do banco de dados. A função FROM_UNIXTIME() considera o fuso configurado no MySQL.

A consulta não retorna registros no período esperado

Confira se a data utilizada no filtro foi convertida corretamente com UNIX_TIMESTAMP(). Também verifique se o campo possui zero ou NULL.

A consulta está lenta

Evite aplicar FROM_UNIXTIME() diretamente na coluna usada no WHERE. Prefira converter a data de comparação para timestamp:

-- Evite esta condição em tabelas grandes
WHERE DATE(FROM_UNIXTIME(timecreated)) = '2026-07-18';
 
-- Prefira comparar o valor numérico
WHERE timecreated >= UNIX_TIMESTAMP('2026-07-18 00:00:00')
  AND timecreated < UNIX_TIMESTAMP('2026-07-19 00:00:00');

A segunda forma reduz a necessidade de conversão de cada registro e pode aproveitar melhor os índices existentes.

As datas do Moodle normalmente são armazenadas como Unix timestamps. Em bancos MySQL e MariaDB, utilize FROM_UNIXTIME() para exibir as datas e UNIX_TIMESTAMP() para transformar uma data em um valor adequado para filtros.

Deixe um comentário

O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *

Rolar para cima