Valores decimais reconhecidos como DateTime em vez de retornar false de DateTime.Parse

9

Eu preciso executar uma verificação com base em um valor de seqüência de caracteres se é uma data ou decimal, mas a análise de data sempre retorna true para decimal.

string val = "3.5";
DateTime oDate = DateTime.Parse(val);

Retorna uma data válida 3/5/2019.

Como validar uma string para saber se é uma data válida quando o formato da data não é conhecido?

Munawar
fonte
6
Verificar decimal primeiro? Ou use DateTime.ParseExactse você souber quais formatos ele pode / deve ter #
A Friend
3
Você pode usar TryParseExacte especificar formatos de data válidos.
juharr
5
Na verdade - DateTime.Parsetenta vários padrões. Se você deseja reconhecer apenas alguns específicos, tente analisá-los especificamente.
Jon Skeet

Respostas:

3

"Como validar string para saber se é uma data válida?"

O problema é que "3.5" é considerada uma data válida (e também um decimal).

Se você deseja que o tipo decimal sempre "vença" (ou seja, você não deseja isDatee isDecimalque ambos sejam true), inclua uma verificação decimal em sua validação.

Uma maneira de fazer isso é usar os TryParsemétodos (que retornam a boolse uma string pode ser analisada para o tipo e que define um outparâmetro para o valor convertido) para determinar se a string pode ser convertida em um tipo, por exemplo:

string val = "3.5";

// temp variables to hold parsed values
DateTime tmpDate;
decimal tmpDec;
int tmpInt;

var isDecimal = decimal.TryParse(val, out tmpDec);
var isInteger = int.TryParse(val, out tmpInt);

// When checking if it's a DateTime, make sure it's not also a decimal
var isDate = !isDecimal && DateTime.TryParse(val, out tmpDate);
Rufus L
fonte
Eu já tinha tentado, mas 3.5 é uma data válida e um decimal válido, portanto, não ajuda em nada.
Munawar
11
No código acima, isDateé falseporque inclui uma verificação isDecimal. Não era isso que você estava pedindo?
Rufus L
2
@ Munawar - "3.5 é uma data válida e um decimal válido" exatamente. Se nós, como humanos, somos apresentados a essa sequência e a nenhum outro contexto, não sabemos se a intenção era uma data, um decimal ou outra coisa possível . Você não pode esperar que um computador obtenha magicamente uma resposta para ele.
Damien_The_Unbeliever
Sim, esta resposta é específica do problema e resolve o meu problema, embora o ParseExact seja o mais adequado se os formatos forem conhecidos.
Munawar
Você ainda tem o problema quando o formato da data é "12122019"
Athanasios Kataras
6

Verifique a documentação oficial no ParseExact

Se você conhece a representação exata, pode fazer algo assim:

  format = "ddd dd MMM yyyy h:mm tt zzz";
  try {
     result = DateTime.ParseExact(dateString, format, provider);
     Console.WriteLine("{0} converts to {1}.", dateString, result.ToString());
  }
  catch (FormatException) {
     Console.WriteLine("{0} is not in the correct format.", dateString);
  }

Se você não o conhece, está preso às convenções culturais

Analise uma sequência de data e hora usando as convenções de uma cultura específica. Sobrecarga de Parse (String, IFormatProvider) (consulte Convenções de análise e cultura)

Athanasios Kataras
fonte
O formato não é conhecido, pode ser baseado nas preferências do usuário.
Munawar
11
@Munawar, como você distinguirá entre 03/03/2019 e 01/03/2019 nessa situação?
Blaise
@Athanasios, o aplicativo é usado para diferentes regiões e datas armazenadas criptografadas. como o usuário pode alterar os formatos de data, não se preocupe com a aplicação de um formato específico, embora o ParseExact seja mais adequado se o formato for conhecido.
Munawar