Ícone do site Linha de Comando

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:

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:

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.

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.

Sair da versão mobile