Escrevendo um equivalente IsDate() em C#?
Peço Desculpa se isto já foi perguntado antes. Eu tenho alguns dados que eu preciso armazenar como strings, alguns desses dados são datas. Os dados começam como strings como "01/02/10" (formato uk) . Agora, mais tarde, estes dados são processados e, dependendo do que faz o processamento, os resultados são diferentes (01-fev-10 vs. 02-Jan-10, por exemplo). Dado que os dados começam como strings, antes de Os armazenar eu gostaria de dizer, " se isto se parece com uma data, formate-o como dd-mmm-AA " .
O problema é que muitas coisas parecem uma data para o DateTime.Função Parse ().então, eu apliquei algumas regras e só aceito formatos de datas "razoáveis" para minhas verificações, e escrevi uma função IsDate (). Estou procurando sugestões sobre como fazer isso porque, enquanto funciona, minha solução parece muito desajeitada.
A razão de eu ter feito isto, em vez de ir pela data habitual.A rotina de TryParse é clara se alguma vez começou a atirar cordas aleatórias nele (como "3/4" e "6.12"). Eis o que tenho até agora:class Program
{
static void Main(string[] args)
{
Debug.Assert(IsDate(6.12) == false);
Debug.Assert(IsDate("3/4") == false);
Debug.Assert(IsDate(010210) == false);
Debug.Assert(IsDate("010210") == false);
Debug.Assert(IsDate("12-jan-2000") == true);
Debug.Assert(IsDate("12-12-20") == true);
Debug.Assert(IsDate("1/1/34") == true);
Debug.Assert(IsDate("09/30/20") == false);
Debug.Assert(IsDate(DateTime.Now) == true);
}
static Boolean IsDate(Object value)
{
DateTimeFormatInfo DateTimeFormatGB = new CultureInfo("en-GB").DateTimeFormat; // new CultureInfo("en-US").DateTimeFormat;
return IsDate(value, DateTimeFormatGB);
}
static private List<String> AcceptableDateFormats = new List<String>(72);
static Boolean IsDate(Object value, DateTimeFormatInfo formatInfo)
{
if (AcceptableDateFormats.Count == 0)
{
foreach (var dateFormat in new[] { "d", "dd" })
{
foreach (var monthFormat in new[] { "M", "MM", "MMM" })
{
foreach (var yearFormat in new[] { "yy", "yyyy" })
{
foreach (var separator in new[] { "-", "/" }) // formatInfo.DateSeparator ?
{
String shortDateFormat;
shortDateFormat = dateFormat + separator + monthFormat + separator + yearFormat;
AcceptableDateFormats.Add(shortDateFormat);
AcceptableDateFormats.Add(shortDateFormat + " " + "HH:mm"); // formatInfo.TimeSeparator
AcceptableDateFormats.Add(shortDateFormat + " " + "HH:mm:ss");
}
}
}
}
}
String sValue = value.ToString().Trim();
DateTime unused;
foreach (String format in AcceptableDateFormats)
{
if (DateTime.TryParseExact(sValue, format, formatInfo, DateTimeStyles.None, out unused) == true) return true;
}
return false;
}
}
Eu não usei os separadores de data / hora da Informação da cultura porque eu queria aceitar tanto um " / "e um" -". Eu acho que eu poderia ter usado o tempo um though, como que é improvável mudar (para mim).
9 answers
Verificaste DateTime.TryParse () 's Alternative override where it gives you a lot more control over what it considers to be a date?
Considere a utilização de DateTime.TryParseExact
Para converter o texto até à data, tanto poderá indicar uma cultura que use esse formato específico : como se quiséssemos converter a data "dd / MM / AAAA" para a data..
datetime mydate = Convert.ToDateTime(
txtdate.Text, CultureInfo.GetCulture("en-GB")
);
Ou utilizar o método ParseExact:
datetime mydate = DateTime.ParseExact(
txtdate.Text, "dd/MM/yyyy", CultureInfo.Invariant
);
O método Parsexact só aceita esse formato específico, enquanto o Convert.O método ToDateTime ainda permite algumas variações no formato, e também Aceita alguns outros formatos de data.
Para apanhar dados ilegais, pode utilizar o método TryParseExact:
DateTime d;
if (DateTime.TryParseExact(txtdate.Text, "dd/MM/yyyy", CultureInfo.Invariant, DateTimeStyles.None, out d)) {
datetime mydate = d;
} else {
// communcate the failure to the user
}
Hope below links irá lhe fornecer alguma ajuda:
Http://dotnetacademy.blogspot.com/2010/09/convert-string-to-date.html
Http://msdn.microsoft.com/en-us/library/system.datetime.tryparse.aspx
Http://msdn.microsoft.com/en-us/library/9h21f14e.aspx
Http://dotnetacademy.blogspot.com/2009/10/get-current-system-date-format.html
Este é um exemplo para tryParse : http://dotnetperls.com/datetime-tryparse
Já saiu a tentar {[[0]} sobrecarga que aceita argumentos IFormatProvider
e DateTimeStyles
? Você pode ser capaz de usar isso para ser mais exigente sobre o que você aceita como uma data real, embora não desnecessariamente jogando exceção apenas para testar as cordas.
Tenta
DateTime result;
DateTime.TryParseExact(value.ToString(), new string[] { "dd/MM/yyyy", "d/M/yyyy" }, null, DateTimeStyles.None, out result)
No final, eu fui com uma versão do seguinte:
static private List<String> AcceptableDateFormats = new List<String>(180);
static Boolean IsDate(Object value, DateTimeFormatInfo formatInfo)
{
if (AcceptableDateFormats.Count == 0)
{
foreach (var dateFormat in new[] { "d", "dd" })
{
foreach (var monthFormat in new[] { "M", "MM", "MMM" })
{
foreach (var yearFormat in new[] { "yy", "yyyy" })
{
foreach (var separator in new[] { "-", "/", formatInfo.DateSeparator })
{
String shortDateFormat;
shortDateFormat = dateFormat + separator + monthFormat + separator + yearFormat;
AcceptableDateFormats.Add(shortDateFormat);
AcceptableDateFormats.Add(shortDateFormat + " " + "HH:mm");
AcceptableDateFormats.Add(shortDateFormat + " " + "HH:mm:ss");
AcceptableDateFormats.Add(shortDateFormat + " " + "HH" + formatInfo.TimeSeparator + "mm");
AcceptableDateFormats.Add(shortDateFormat + " " + "HH" + formatInfo.TimeSeparator + "mm" + formatInfo.TimeSeparator + "ss");
}
}
}
}
AcceptableDateFormats = AcceptableDateFormats.Distinct().ToList();
}
DateTime unused;
return DateTime.TryParseExact(value.ToString(), AcceptableDateFormats.ToArray(), formatInfo, DateTimeStyles.AllowWhiteSpaces, out unused);
}
IsDate
Em C#:
using Microsoft.VisualBasic;
//...other code...
if (Information.IsDate(YourDateObject)) {
//...more code...
}
Em alternativa, poderá ter a sua própria verificação de expressão regular depois de encontrar uma data potencial se necessitar de um maior grau de controlo. algo assim.
^(0[1-9]|1[012])[- /.](0[1-9]|[12][0-9]|3[01])[- /.](19|20)\d\d$
Abrange xx-yy-zz e xx / yy/zz de acordo com as suas necessidades
using System.Globalization;
CultureInfo ukCI = CultureInfo.CreateSpecificCulture("en-GB");
Console.WriteLine(DateTime.Parse("1/2/2010", ukCI).ToString("dd-MMM-yyyy"));
Pode usar TryParse
no lugar de Parse
, Se quiser validar que o argumento é uma data.