excuses si cela a été demandé auparavant. J'ai des données que j'ai besoin de stocker comme chaînes, certaines de ces données étant dates. Les données commencent comme des chaînes telles que "01/02/10" (Format britannique) em>. Maintenant, plus tard, ces données sont analysées et, en fonction de la analyse de l'analyse, les résultats sont différents (01-février -10 vs 02 jan-10 par exemple). Étant donné que les données commencent comme des chaînes, avant que je l'ai enregistrée, je voudrais dire, "Si cela ressemble à une date, le format comme DD-mmm-yy" em>. Le problème que beaucoup de choses ressemblent à une date à la fonction DateTime.Parse (). p> Donc, j'ai appliqué certaines règles et n'acceptez que des formats de date "raisonnables" pour mes chèques et écrivit une fonction isdate (). Je cherche des suggestions sur la façon de faire cela parce que, pendant que cela fonctionne, ma solution semble très maladroite. P> Toute la raison pour laquelle je l'ai fait plutôt que de descendre la routine habituelle DateTime.tryparse est clair si vous ont déjà commencé à jeter des cordes aléatoires (comme "3/4" et "6.12"). P> Voici ce que j'ai jusqu'à présent: p> 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;
}
}
9 Réponses :
Avez-vous consulté DateTime.tryparse () alternative remplacer où il vous donne beaucoup plus de contrôle sur ce qu'il considère comme une date? P>
Cela ne vous donne pas beaucoup de contrôle supplémentaire.
Avez-vous vérifié en essayant denttime.trypsarse code> surcharge qui accepte
iFormatProvider code> et
DateTimeMestyles code> arguments? Vous pourrez peut-être utiliser cela pour être plus difficile sur ce que vous acceptez comme une date réelle, tout en jetant inutilement une exception juste pour tester les chaînes. P>
Oui j'ai. Je ne trouve pas un moyen de l'empêcher de penser que "3/4" ou "6.12" n'est pas une date (et je ne jette pas d'exceptions).
envisagez d'utiliser DateTime.trySeexact P >
Je pensais l'avoir fait. La question étant que je ne contrôle pas le format des données, mais c'est une attente raisonnable que sa date de format au Royaume-Uni qui pourrait ou non avoir une partie du temps.
Pour convertir une chaîne à ce jour, vous spécifiez une culture qui utilise ce format spécifique:
Comme nous voulons convertir la date de chaîne "jj / mm / aaaa" à ce jour .. ou utilisez la méthode parseexact: p> 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
}
Sent comme le spam. Vous pouvez promouvoir vos propres trucs, mais s'il vous plaît inclure un contenu plus réel que celui d'un lien vers votre propre blog.
@Joel: Désolé, je ne savais pas que pour fournir un lien d'un blog de son propre blog n'est pas accepté sur Stackoverflow.
La liaison aux blogs va bien et la liaison à votre blog convient. Liaison à votre blog lorsque la plupart de votre réponse sont derrière le lien et votre nom de blog ressemble à un nom d'entreprise sent le spam. Que ce soit ou non, le spam n'a pas d'importance - l'odeur est là. Votre réponse modifiée est beaucoup plus agréable, merci.
Vous pouvez également avoir votre propre vérification d'expression régulière après avoir trouvé une date potentielle si vous avez besoin d'un maximum de contrôle.
quelque chose comme ça. Couvre XX-YY-ZZ et XX / AA / ZZ selon votre exigence P> P>
Le problème est que mon exemple simple vérifie environ 70 formats de date valides. Accordé une regex pourrait attraper plus d'un format, mais vous auriez toujours beaucoup de chaînes de regex. De plus, à la plupart des gens, ils ressemblent à un bruit de la ligne. : o)
Il semble qu'il n'y ait aucune réponse simple dans ce cas. Votre recherche d'un plus grand degré de contrôle mais facilité d'utilisation. C'est plus une décision de conception ici. Soit envisagez de limiter le nombre de formats acceptés ou de combiner un couple de chèques de regex simples pour des trucs comme «3/4» ou «6.12» et après l'utilisation DateTime.Tryparse une fois que la chaîne a passé les expressions de regex.
Oh et avec regex, des commentaires peuvent aller un long chemin
Essayez
DateTime result; DateTime.TryParseExact(value.ToString(), new string[] { "dd/MM/yyyy", "d/M/yyyy" }, null, DateTimeStyles.None, out result)
Salut merci. Je n'avais pas taché, je pouvais passer un éventail de formats acceptables.
using System.Globalization; CultureInfo ukCI = CultureInfo.CreateSpecificCulture("en-GB"); Console.WriteLine(DateTime.Parse("1/2/2010", ukCI).ToString("dd-MMM-yyyy")); You can use TryParse in place of Parse, if you want to validate that the argument is a date.
À la fin, je suis allé avec une version de ce qui suit:
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); }
Ceci est évidemment un piratage, mais ce que j'ai fini par faire était d'ajouter la référence VisualBasic et utilisez simplement la fonction isdate code> de la fonction C #:
Nice - et référencer VB est plus un problème culturel qu'un problème de distribution / de dépendance.
Pourquoi ne pas utiliser denttime.tryparse, puis faire une vérification de la santé mentale par exemple sur une partie de la date de date de retour renvoyée?