CodeGym /Cursos /C# SELF /Formatação e parsing de datas e horários

Formatação e parsing de datas e horários

C# SELF
Nível 15 , Lição 3
Disponível

1. Formatação de datas

Se você acha que mostrar 2025-06-19T17:30:00 tá estiloso, tenta mostrar esse formato pra sua avó ou pra galera da contabilidade. Provavelmente eles vão preferir algo mais simples: 19.06.2025 17:30. Já os colegas gringos esperam 06/19/2025 5:30 PM. DevOps e máquinas curtem mesmo é 2025-06-19T17:30:00Z. Ou seja, um DateTime na memória do programa pode aparecer de dezenas de jeitos diferentes na tela.

O caminho inverso também é clássico: o usuário digita uma data num campo ("19.06.2025"), e a gente tem que transformar isso num objeto C# sem confundir o que é dia e o que é mês. Automação, integrações, relatórios — em todo lugar é importante interpretar datas em texto do jeito certo.

Formatação básica

O C# deixa você converter um objeto de data/hora (DateTime, DateOnly, TimeOnly, DateTimeOffset) pra string usando o método .ToString():


DateTime now = DateTime.Now;
Console.WriteLine(now.ToString()); // Saída: 19.06.2025 17:30:25
Formatação básica de data e hora

Se você chamar .ToString() sem parâmetros — vai usar o formato padrão da cultura do sistema (por exemplo, Windows alemão mostra de um jeito, americano de outro).

Strings de formato padrão

Dá pra especificar o formato da saída usando as chamadas strings de formato padrão pra data e hora:

Formato Descrição Exemplo de saída
"d"
Data curta 19.06.2025
"D"
Data completa 19 de junho de 2025
"f"
Data completa + hora curta 19 de junho de 2025 17:30
"F"
Data completa + hora completa 19 de junho de 2025 17:30:25
"g"
Data e hora curtas 19.06.2025 17:30
"G"
Data curta + hora completa 19.06.2025 17:30:25
"t"
Hora curta 17:30
"T"
Hora completa 17:30:25
"M"/"m"
Mês e dia 19 de junho
"Y"/"y"
Ano e mês Junho de 2025
"O"/"o"
ISO 8601 (round-trip) 2025-06-19T17:30:25.0000000

Console.WriteLine(now.ToString("d")); // 19.06.2025
Console.WriteLine(now.ToString("F")); // 19 de junho de 2025 17:30:25
Console.WriteLine(now.ToString("O")); // 2025-06-19T17:30:25.0000000

Templates customizados (personalizados)

Se você precisa de formatos mais específicos, pode usar seus próprios templates:

Símbolo Significado
yyyy Ano, 4 dígitos
yy Ano, 2 dígitos
MM Mês, 2 dígitos
MMMM Nome do mês
dd Dia, 2 dígitos
d Dia, 1-2 dígitos
HH Hora (24h)
mm Minutos
ss Segundos
tt AM/PM

Console.WriteLine(now.ToString("yyyy-MM-dd HH:mm")); // 2025-06-19 17:30
Console.WriteLine(now.ToString("dd.MM.yyyy"));       // 19.06.2025
Console.WriteLine(now.ToString("dddd, MMMM d"));     // quarta-feira, junho 19

Diferenças culturais na formatação

Se você quiser o resultado no estilo de outro país ou idioma, usa a sobrecarga ToString(string, IFormatProvider):


var enUS = new System.Globalization.CultureInfo("en-US");
Console.WriteLine(now.ToString("D", enUS)); // June 19, 2025
  • Se você definir o template como "MM/dd/yyyy", não importa a cultura, sempre vai sair "06/19/2025".
  • Mas se usar só "d" ou "D" — o formato depende da cultura!

Pontos importantes ao trabalhar com formatação

Quando for formatar datas, é importante entender a diferença entre formatos padrão e personalizados. Os padrões ("d", "F", "G") se adaptam automaticamente à cultura do sistema, o que é ótimo pra interface de usuário, mas pode dar ruim quando você troca dados entre sistemas. Os formatos customizados dão controle total sobre a saída, mas exigem mais atenção.

Fica ligado no formato "O" (ou "o") — esse é o tal do "round-trip", que garante que a data convertida pra string e de volta vai ser exatamente igual. Esse formato é super importante pra serialização de dados ou quando você manda info pela rede.

2. Parsing de datas e horários: como transformar string em objeto

Parsing mais simples: DateTime.Parse

DateTime.Parse — método que tenta reconhecer a string da data levando em conta a cultura do sistema.


string input = "19.06.2025";
DateTime parsed = DateTime.Parse(input);
Console.WriteLine(parsed); // 19.06.2025 00:00:00

Se a string estiver errada — o programa vai dar exception (ninguém tá livre disso!).

Especificando a cultura


string input = "06/19/2025";
var enUS = new System.Globalization.CultureInfo("en-US");
DateTime dt = DateTime.Parse(input, enUS);
Console.WriteLine(dt); // 19.06.2025 00:00:00

Parsing seguro: TryParse


string input = "data errada";
bool ok = DateTime.TryParse(input, out DateTime safeDate);
if (!ok)
    Console.WriteLine("Erro: não consegui reconhecer a data!");

Formato fixo: ParseExact e TryParseExact


var culture = System.Globalization.CultureInfo.InvariantCulture;
string dateStr = "2025-06-19";

DateTime d = DateTime.ParseExact(dateStr, "yyyy-MM-dd", culture);
Console.WriteLine(d); // 19.06.2025 00:00:00

bool parsedOk = DateTime.TryParseExact(
    "19.06.2025",
    "dd.MM.yyyy",
    System.Globalization.CultureInfo.InvariantCulture,
    System.Globalization.DateTimeStyles.None,
    out DateTime myDate);

Tabela de formatos populares

String Formato Objeto final
"2025-06-19" "yyyy-MM-dd" 19 de junho de 2025
"19.06.2025" "dd.MM.yyyy" 19 de junho de 2025
"06/19/2025" "MM/dd/yyyy" 19 de junho de 2025
"2025-06-19T14:15:16" "s" 19 de junho de 2025 14:15:16

Trabalhando com DateTimeStyles

No parsing, dá pra controlar o comportamento usando o parâmetro DateTimeStyles. Esse enum deixa você configurar como o parser interpreta os dados de entrada. Por exemplo, DateTimeStyles.AssumeUniversal faz o parser assumir que o horário é UTC se não tiver offset explícito. DateTimeStyles.AllowWhiteSpaces deixa ignorar espaços extras na string. Essas configs são muito úteis quando você pega dados de fontes externas, onde o formato pode ser meio imprevisível.

3. Formatação e parsing de DateOnly, TimeOnly

Os tipos novos DateOnly e TimeOnly estão sendo usados direto pra guardar datas/horários sem detalhes desnecessários.

Formatação


DateOnly birthday = new DateOnly(2000, 6, 19);
Console.WriteLine(birthday.ToString("dd MMMM yyyy")); // 19 de junho de 2000

Parsing


var d = DateOnly.ParseExact("19.06.2000", "dd.MM.yyyy");
Console.WriteLine(d.Day); // 19

Os métodos pra TimeOnly funcionam igual (só que os templates são só pra hora/minuto/segundo):

TimeOnly t = TimeOnly.ParseExact("23:59", "HH:mm");
Console.WriteLine(t.Hour); // 23

Vantagens do DateOnly e TimeOnly

Usar DateOnly e TimeOnly no lugar de DateTime tem várias vantagens. Primeiro, fica mais claro o que você quer dizer — se só precisa da data sem hora (tipo data de nascimento), DateOnly deixa isso explícito. Segundo, ajuda a evitar problemas com fuso horário, que podem rolar com DateTime. Terceiro, esses tipos ocupam menos espaço na memória e no banco de dados.

Formatação e parsing considerando fuso horário

Se você guarda horário com info de offset — usa DateTimeOffset. Isso é essencial pra sistemas internacionais e distribuídos. Todos os métodos de formatação e parsing são iguais, só que agora dá pra controlar o offset também:


DateTimeOffset meeting = new DateTimeOffset(2025, 6, 19, 17, 30, 0, TimeSpan.FromHours(3));
Console.WriteLine(meeting.ToString("o")); // 2025-06-19T17:30:00.0000000+03:00

string input = "2025-06-19T17:30:00+03:00";
var parsedOffset = DateTimeOffset.Parse(input);
Console.WriteLine(parsedOffset.Offset); // 03:00:00

4. Dicas práticas e erros comuns

Uma das armadilhas é confundir "dia" e "mês" ao fazer parsing de formatos internacionais. Por exemplo, a string "01/02/2025" nos EUA é 2 de janeiro, mas na maioria dos países europeus é 1 de fevereiro (surpresa!).

Também é comum esquecer o impacto da cultura: se o app roda num servidor na Alemanha, mas os usuários são de vários países, o formato da data do banco pode ser interpretado diferente em cada servidor.

Um erro frequente é usar .ToString() sem especificar cultura/formato pra logs e arquivos de troca: o resultado pode mudar depois de migrar pra outro SO ou se o app rodar com outro usuário do Windows.

Dicas pra trabalhar com datas

  • Pra guardar e trocar dados internamente, sempre use cultura invariante (CultureInfo.InvariantCulture) ou formatos explicitamente definidos.
  • Na interface do usuário, use a cultura do usuário ou deixa ele escolher o formato preferido.
  • Ao trabalhar com API e bancos de dados, prefira o formato ISO 8601, que é padrão internacional.
  • Sempre valide os dados de entrada: checa se a data existe, o intervalo e se os valores fazem sentido.

Trabalhando com diferentes fontes de dados

Ao integrar com sistemas externos, você vai lidar com datas em vários formatos. Alguns sistemas mandam datas como Unix timestamp (segundos desde 1 de janeiro de 1970), outros — como strings em formatos nacionais. É importante combinar antes o formato de troca de dados e sempre checar se o parsing tá certo.

Também vale lembrar que alguns formatos podem ser ambíguos. Por exemplo, "12/13/2025" é claramente 13 de dezembro de 2025, mas "12/11/2025" pode ser 12 de novembro ou 11 de dezembro, dependendo da cultura. Nesses casos, é melhor usar formatos menos ambíguos ou especificar explicitamente a cultura do parsing.

Comentários
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION