Conversão de datas para algarismos romanos no dia a dia
A conversão de data em algarismo romano é mais simples do que parece, mas tem detalhes que travam quem não conhece a regra por trás. Você pega um número como 2024 e transforma em MMXXIV. Para datas, vira uma questão de fazer isso para dia, mês e ano separadamente. Vou explicar como eu faço, com exemplos práticos e o problema que quase me fez perder uma manhã inteira.
O algoritmo por trás da data em algarismo romano
O sistema romano funciona com símbolos fixos. M = 1000, D = 500, C = 100, L = 50, X = 10, V = 5, I = 1. A regra principal é: escreva do maior para o menor valor, e quando um símbolo menor aparece antes de um maior, você subtrai. IV = 4, IX = 9, XL = 40, XC = 90, CD = 400, CM = 900. Sem essas exceções, qualquer explicação fica incompleta. No meu caso, eu precisava gerar um relatório onde cada registro tinha sua data convertida. Eu comecei escrevendo uma função simples em Python. Achei que seria questão de 20 minutos. Foi. Quase. O problema veio quando testei com datas no século XIX. Anos como 1899 viraram. Por quê? Porque 1899 em romano é MDCCCXCIX, e meu código tratava os 900 (CM) como se o ano tivesse um 900 literal somado ao 800. A confusão é que o sistema de subtração se aplica dentro de cada posição decimal, não no valor total de forma ingênua.
O workaround foi simples: em vez de tentar converter o ano inteiro de uma vez, eu dividi em milhares, centenas, dezenas e unidades, converti cada bloco com tabelas próprias, e juntei. Eis a tabela que eu uso como referência rápida: Unidades: I=1, II=2, III=3, IV=4, V=5, VI=6, VII=7, VIII=8, IX=9
Dezenas: X=10, XX=20, XXX=30, XL=40, L=50, LX=60, LXX=70, LXXX=80, XC=90 Centenas: C=100, CC=200, CCC=300, CD=400, D=500, DC=600, DCC=700, DCCC=800, CM=900
Milhares: M=1000, MM=2000, MMM=3000
Como converter uma data completa na prática
Se a data é 15 de março de 2024, você trata cada parte separadamente. Dia 15 vira XV. Mês 3 (março) vira III. Ano 2024 vira MMXXIV. Juntando com barras ou pontos, fica XV.III.MMXXIV ou 15-III-2024 dependendo do padrão que você adota. A parte mais chata é o mês. Algarismos romanos para meses vão de I a XII. Eu sempre monto um dicionário para isso:
1=I, 2=II, 3=III, 4=IV, 5=V, 6=VI, 7=VII, 8=VIII, 9=IX, 10=X, 11=XI, 12=XII Dia também merece atenção. Dias 1 a 31 cobrem todas as combinações das tabelas acima. Dia 29, por exemplo, é XXIX. Dia 31 é XXXI. Nada complicado, só preciso garantir que o código não tente converter dia 0 ou dia 32, senão o resultado fica sem sentido.
👉 Clique no botão abaixo para saber mais sobre o assunto!
Implementação prática com data em algarismo romano
Se você está num projeto que exige formatação de data em algarismo romano, aqui vai uma abordagem que eu uso e recomendo. Ela funciona tanto para dias pontuais quanto para batches grandes. A função central recebe uma data e devolve a string romana. O segredo é nunca pular a validação inicial. Se o ano for menor que 1 ou maior que 3999, o sistema romano clássico simplesmente não tem representação. Isso limita muito o uso para documentos históricos anteriores ao ano 1 ou para previsões futuras, o que pode ser um problema real se o seu escopo abranger cronogramas longos.
Eu gosto de manter a função pura, sem dependências externas, porque a lógica é pequena. No Python, com a estrutura de dicionários que mostrei, dá para escrever tudo em menos de 40 linhas. Em JavaScript, o raciocínio é idêntico. A performance é suficiente para processar milhares de registros em segundos.
Dica técnica que ninguém menciona
A maioria dos tutoriais ensina a converter números inteiros, mas esquece de mencionar que datas em algarismos romanos têm convenções diferentes conforme o contexto. Em documentos jurídicos brasileiros, por exemplo, é comum ver o dia em algarismo romano e o mês por extenso. Em placas e brasões, usa-se apenas o ano. Se você padronizar sem checar o padrão do setor, o resultado pode parecer errado para quem lê, mesmo estando tecnicamente correto. Também vale saber que a indústria de numeração romana não usa o zero. Não existe símbolo para zero no sistema. Se a sua aplicação precisa lidar com data de nascimento onde o dia ou mês é desconhecido, não tem como representar isso em romano puro. Nesses casos, a solução honesta é usar um placeholder como "?" ou manter o algarismo arábico naquela posição. Tentar forçar uma conversão vai gerar nonsense.
Quando evitar data em algarismo romano
Não adianta fingir que é uma solução universal. Existem cenários onde converter data em algarismo romano é péssima ideia. Processadores de texto legíveis por OCR sofrem bastante com I, V, X e L, especialmente em fontes pequenas. A ambiguidade visual entre I e l minúsculo é real. Além disso, a formatação romana ocupa mais espaço que a arábica. Uma data como 07/03/2024 tem 10 caracteres. Em romano, VII.III.MMXXIV tem 13. Em layouts apertados, isso importa. Para relatórios automatizados que precisam ser alimentados por scripts downstream, usar algarismos romanos nas datas vai quebrar parsing e ordenação. A ordem cronológica deixa de ser natural. 2024 vem antes de 1999 em ordem lexicográfica normal, mas MMXXIV vem depois de MCMXCIX. Quem for consumir esses dados depois vai precisar de uma função inversa de conversão, o que adiciona complexidade desnecessária.
Se o objetivo é apenas estética, considere usar a formatação romana apenas no cabeçalho ou em elementos gráficos. Mantenha os dados brutos em formato arábico na base. Essa separação resolve a maioria dos problemas que eu vi aparecerem em projetos reais.
Como testar se sua conversão está correta
Eu sempre incluo testes de borda no meu código. Data 01/01/0001 deve produzir I.I.M. Data 31/12/1999 deve produzir XXXI.XII.MCMXCIX. Data 29/02/2000 deve produzir XXIX.II.MM. Esses três casos cobrem os problemas mais comuns: anos com centena 900, anos bissextos, e dias com dezena 20 mais unidade 9. Se passar nesses três, provavelmente passa em todos. A função inversa também vale a pena implementar, mesmo que só para validação. Converter de volta de romano para numérico e comparar com a data original é o teste mais rápido que existe. Leva menos de 20 linhas e elimina 99% dos bugs silenciosos.
Se quiser o código pronto, a lógica está disponível em repositórios abertos. Procure por "roman date converter" no GitHub. A maioria das implementações segue exatamente o padrão que descrevi aqui: divisão por posição, tabelas fixas, e validação de intervalo. Nada de bibliotecas pesadas. Um arquivo pequeno resolve.