TO_CHAR recebe uma data, um timestamp ou um numero e devolve uma string montada a partir de um modelo de texto. E a ferramenta principal do PostgreSQL para saida voltada a pessoas: uma data fixa para um relatorio, uma hora sem segundos, um preco com separadores de milhar.
Modelos para datas e horas
O primeiro argumento e o valor, o segundo e um modelo com codigos de campo. A pontuacao e os caracteres literais do modelo sao mantidos como estao, entao os hifens, os dois pontos e os espacos voce mesmo posiciona.
SELECT TO_CHAR(created_at, 'YYYY-MM-DD HH24:MI') AS ts
FROM users
ORDER BY created_at
LIMIT 5;
Os codigos mais usados:
YYYY e o ano de 4 digitos, YY o de 2.
MM e o mes em numero (01-12), DD o dia, HH24 a hora de 24 horas, MI os minutos, SS os segundos.
HH12 com AM/PM da a hora de 12 horas.
Day, Mon, Month sao os nomes de dia e mes em texto (regras de maiusculas abaixo).
Atencao para a pegadinha classica: MM e o mes e MI sao os minutos. E muito facil escrever HH24:MM e obter o numero do mes onde voce queria os minutos.
Nomes de mes e localizacao
Os codigos Day, Month, Mon, Dy copiam as maiusculas do modelo: Day gera Monday, DAY gera MONDAY, day gera monday. Os campos de texto sao preenchidos com espacos ate uma largura fixa; remova esse preenchimento com o modificador FM.
SELECT
TO_CHAR(created_at, 'FMDay, FMDD FMMonth YYYY') AS human_date,
TO_CHAR(created_at, 'Dy') AS short_dow
FROM orders
LIMIT 3;
O idioma dos nomes vem do parametro lc_time. Para forcar nomes localizados em uma unica consulta, ative o modo de traducao com o prefixo TM:
SELECT TO_CHAR(
created_at,
'TMDay, DD TMMonth YYYY'
) AS local_date
FROM orders;
O prefixo TM (translate mode) liga os nomes conforme a configuracao regional. Sem ele voce sempre recebe os ingleses Monday/June.
Com numeros, o TO_CHAR controla a largura, o agrupamento e o sinal por meio de uma mascara feita com 9, 0, D, G e companhia.
SELECT
TO_CHAR(amount, 'FM999G999G990D00') AS money,
TO_CHAR(id, '0000') AS padded_id
FROM orders
LIMIT 3;
Como ler a mascara:
9 e um digito com os zeros a esquerda suprimidos; 0 e um digito que sempre e impresso (use para preencher pela esquerda).
D e o separador decimal, G o de grupos; os caracteres reais seguem a localizacao (lc_numeric).
FM corta de novo o espaco inicial que o TO_CHAR reserva para o sinal.
L insere o simbolo de moeda, S imprime o sinal +/-.
Pegadinha: sem FM, os numeros positivos saem com um espaco inicial onde iria o menos, e as colunas do relatorio se desalinham. Para dinheiro voce quase sempre quer FM mais um 0 explicito antes de D, ou 0.50 aparece como .50.
No que o PostgreSQL difere do MySQL
O MySQL nao tem TO_CHAR para datas; ele usa DATE_FORMAT com um conjunto de codigos baseado em % totalmente diferente.
SELECT TO_CHAR(created_at, 'YYYY-MM-DD HH24:MI') FROM users;
SELECT DATE_FORMAT(created_at, '%Y-%m-%d %H:%i') FROM users;
As diferencas principais:
- Minutos: PostgreSQL usa
MI, MySQL usa %i (enquanto %m no MySQL e o mes).
- Relogio de 24 horas: PostgreSQL
HH24, MySQL %H.
- Nome do mes: PostgreSQL
Month/Mon, MySQL %M/%b.
- Numeros: no MySQL voce usa uma
FORMAT(amount, 2) separada para agrupar, e nao TO_CHAR.
ClickHouse segue um terceiro caminho: formatDateTime(created_at, '%Y-%m-%d %H:%M'), codigos no estilo do MySQL, mas aqui %M sao os minutos, nao o mes. A licao: um modelo de TO_CHAR nao e portavel, e trocar de banco obriga a reescreve-lo do zero.
TO_CHARrecebe uma data, um timestamp ou um numero e devolve uma string montada a partir de um modelo de texto. E a ferramenta principal do PostgreSQL para saida voltada a pessoas: uma data fixa para um relatorio, uma hora sem segundos, um preco com separadores de milhar.Modelos para datas e horas
O primeiro argumento e o valor, o segundo e um modelo com codigos de campo. A pontuacao e os caracteres literais do modelo sao mantidos como estao, entao os hifens, os dois pontos e os espacos voce mesmo posiciona.
SELECT TO_CHAR(created_at, 'YYYY-MM-DD HH24:MI') AS ts FROM users ORDER BY created_at LIMIT 5; -- 2026-06-17 14:32Os codigos mais usados:
YYYYe o ano de 4 digitos,YYo de 2.MMe o mes em numero (01-12),DDo dia,HH24a hora de 24 horas,MIos minutos,SSos segundos.HH12comAM/PMda a hora de 12 horas.Day,Mon,Monthsao os nomes de dia e mes em texto (regras de maiusculas abaixo).Atencao para a pegadinha classica:
MMe o mes eMIsao os minutos. E muito facil escreverHH24:MMe obter o numero do mes onde voce queria os minutos.Nomes de mes e localizacao
Os codigos
Day,Month,Mon,Dycopiam as maiusculas do modelo:DaygeraMonday,DAYgeraMONDAY,daygeramonday. Os campos de texto sao preenchidos com espacos ate uma largura fixa; remova esse preenchimento com o modificadorFM.SELECT TO_CHAR(created_at, 'FMDay, FMDD FMMonth YYYY') AS human_date, TO_CHAR(created_at, 'Dy') AS short_dow FROM orders LIMIT 3; -- Wednesday, 17 June 2026 | WedO idioma dos nomes vem do parametro
lc_time. Para forcar nomes localizados em uma unica consulta, ative o modo de traducao com o prefixoTM:SELECT TO_CHAR( created_at, 'TMDay, DD TMMonth YYYY' ) AS local_date FROM orders; -- com lc_time = pt_BR.UTF-8: quarta-feira, 17 junho 2026O prefixo
TM(translate mode) liga os nomes conforme a configuracao regional. Sem ele voce sempre recebe os inglesesMonday/June.Formatando numeros
Com numeros, o
TO_CHARcontrola a largura, o agrupamento e o sinal por meio de uma mascara feita com9,0,D,Ge companhia.SELECT TO_CHAR(amount, 'FM999G999G990D00') AS money, TO_CHAR(id, '0000') AS padded_id FROM orders LIMIT 3; -- 1,250.00 | 0042Como ler a mascara:
9e um digito com os zeros a esquerda suprimidos;0e um digito que sempre e impresso (use para preencher pela esquerda).De o separador decimal,Go de grupos; os caracteres reais seguem a localizacao (lc_numeric).FMcorta de novo o espaco inicial que oTO_CHARreserva para o sinal.Linsere o simbolo de moeda,Simprime o sinal+/-.Pegadinha: sem
FM, os numeros positivos saem com um espaco inicial onde iria o menos, e as colunas do relatorio se desalinham. Para dinheiro voce quase sempre querFMmais um0explicito antes deD, ou0.50aparece como.50.No que o PostgreSQL difere do MySQL
O MySQL nao tem
TO_CHARpara datas; ele usaDATE_FORMATcom um conjunto de codigos baseado em%totalmente diferente.-- PostgreSQL SELECT TO_CHAR(created_at, 'YYYY-MM-DD HH24:MI') FROM users; -- MySQL SELECT DATE_FORMAT(created_at, '%Y-%m-%d %H:%i') FROM users;As diferencas principais:
MI, MySQL usa%i(enquanto%mno MySQL e o mes).HH24, MySQL%H.Month/Mon, MySQL%M/%b.FORMAT(amount, 2)separada para agrupar, e naoTO_CHAR.ClickHouse segue um terceiro caminho:
formatDateTime(created_at, '%Y-%m-%d %H:%M'), codigos no estilo do MySQL, mas aqui%Msao os minutos, nao o mes. A licao: um modelo deTO_CHARnao e portavel, e trocar de banco obriga a reescreve-lo do zero.