I have some data picked up from an excel file.
I want to validate that the user has entered a valid date time string. I have tried to use DateTime.Parse method but found that certain values seem to be accepted.
For example,
If I submit 3.3 as a date time this is accepted by the DateTime.Parse method as a valid date time and outputs 03/03/2012 00:00:00
I want to want to block this. Only allowing the user to enter correctly formatted date times.
So for example a user could supply 03/03/2012 or 03/03/2012 12:30:00 but not values like 01022012 or 3.3.2012
Any Ideas?
You want to use DateTime.ParseExact or DateTime.TryParseExact
This allows you do parse from a date format string of your choice.
http://msdn.microsoft.com/en-us/library/system.datetime.tryparseexact.aspx
Examples here:-
http://msdn.microsoft.com/en-us/library/ms131044.aspx
You can use RegEx to to this. Something like this should help #"\d{2}/\d{2}/\d{4}(\s+\d{2}\:\d{2}\:\d{2})?"
You can handle it on the client side with various jquery plugin/functions like this or a simple Google search can return many other useful results.
if you want to handle it on the server side, (I am not sure on what project you are working) but depending over it you can write your own method/use Regex or Data Annotation MVC.
If you are still having trouble try adding few details about your project such as Language, Architecture etc. that would help more in providing the right solution.
Hope it helps. Thankyou
Related
I was looking at a code in an application (Someone else wrote it),on some cases it worked fine and on some cases it gave exceptions,it was actually converting strings in datetime,here is the code
//5000 is the year,but what about "1" is it month or day ?,if its month
//then what about the day ?
DateTime time = DateTime.Parse("1.5000");//1.5000 doesn't looks a date to me ?
time.ToString();//returns "1/1/5000 12:00:00 AM"
//where as if I give this string to DateTime.Parse();
time = DateTime.Parse("2341.70");
//FormatException was unhandled
//String was not recognized as a valid DateTime.
A Confusing thought
How does this string "3.5000" (it matches the 1.5000 pattern) evaluates , does this means 3-3-5000 or 1-3-5000 ,the format is ambiguous its unclear and confusing !
My questions are,
What kind of formats can DateTime.Parse expects ?
Whats happening in the code above ?
Suggestions to improve the code ?
Many people have commented on the possible reasons for the parse that you have seen being successful but your question seems to have several separate parts...
1. What kind of formats can DateTime.Parse expects ?
DateTime.Parse has been written to be as inclusive as possible. Pretty much anything that it can find someway to make into a DateTime it will do its best to do so which means in addition to the usual familiar yyyy-MM-dd type formats more strange ones like M.yyyy or yyyy.M and so on.
2. Whats happening in the code above ?
That is very complicated because the DateTime.Parse method is itself very complicated. You can probably fidn the source code out there somewhere but the complexity made it very hard for me to follow. Without being able to give precise details I'm going to answer this the same as above. What is happening is that the framework is trying its best to give you a date back and not throw an exception. The date it gives is the best guess as to what you meant.
3. Suggestions to improve the code ?
It sounds like if you are getting parse exceptions that you are passing dates in formats that are unexpected. Without knowing what those inputs are its hard to say. Two things could improve your code though. Making sure a single consistent date format is used and then using DateTime.ParseExact to ensure that it conforms to the right format. You will remove all ambiguity this way but you will sacrifice flexibility.
The second option is to use DateTime.TryParse. This will attempt to parse your date and then return a boolean saying whether it succeeded or not. If successful the date parse will be returned in a ref parameter. This won't make your code any better at recognising unknown date formats but will let your code know when such an unparsable format crops up and you can deal with it (eg by providing user feedback reporting the wrong format and suggesting a correct one, or just by logging it or something else).
What the best method is depends mostly on where your input is coming from. If it is user input then I'd go with the second option. If it is automated input then you probably want to make sure your input is standardized and then use the first option. Of course circumstances always vary so this is not a hard and fast rule. :)
In regards to "2. Whats happening in the code above ?":
In some cultures, the date separator is a dot instead of a slash. So for example 13.12.2013 is a valid date (2013-12-13) in the format "dd.MM.yyyy". Now by whatever design choice, the day part in this example is not mandatory and if left out, is automatically filled with 1. So parsing 12.2013 would result in 2013-12-01. And therefore it's easy to see how 1.5000 would become 5000-01-01. 2341.70 can not be parsed, because 2341 is not a valid month. - So in this case 1.5000 is a "valid" date in the format M.yyyy.
I'm trying to build a validator that will work with .NET's DefaultModelBinder of using DateTime.Parse to convert a string from the form post to a DateTime. I don't want to have to wait until a date has been posted to the server for it to realize it was a bad date.
Currently jquery.validate uses the following code to validate date fields:
// http://docs.jquery.com/Plugins/Validation/Methods/date
date: function(value, element) {
return this.optional(element) || !/Invalid|NaN/.test(new Date(value));
}
However, due to Javascript's terrible Date parser, this:
275481/69/100089
Will evaluate as valid, to Sep. 12, 275760.
While on the other hand, this:
11-19-2013
Will evaluate as invalid.
Of course, I understand that C#'s DateTime.Parse() takes things like culture (localization) and leap year into account, and I could live with assuming a fixed (US) culture, and allowing "02-29-2013" on the client and kick it out at the server (ideally not, but it's acceptable).
But I can't believe someone hasn't put together a better date validator to work with C#'s DateTime.Parse() logic.
Maybe someone has, I just haven't found it -- which is why I'm posting here.
And I know I have several ways to go about this -- from incredibly simple (less accurate) to incredibly complex (more accurate), but I'm hoping someone has already gone down this road and found the sweet spot.
Datejs seems pretty robust to me. Its parse function supports over 150 cultures:
Date.parse("February 20th 1973")
And in case you need to parse a date string that is not valid in the current culture you can use the parseExact function:
// The Date of 15-Oct-2004
Date.parseExact("10/15/2004", ["M/d/yyyy", "MMMM d, yyyy"]);
In all honesty, your best bet is to perform an AJAX hit, and ask your ASP.net web-server to parse the string and return a Javascript date.
Javascript libraries easily get confused with different locales, e.g.:
GET /ParseDate.ashx?dateStaring=06/01/34 4:53:05 غ.و&locale=ar-SA
Which gets really complicated because:
"6/1/34" = November 19, 2012
The .NET framework, with Windows behind it, has support for a lot of different locales.
Instead of trying to find two Datetime implementations (one for JS and another for C#) that have similar validation and parsing, have you considered having the client 1)use its own library to validate the date and 2)parse and reformat the date to a C# friendly format?
This would allow you to use DateJS to get a very flexible front end for date inputs, make it easier to deal with the client side culture, and let your server side deal with a fixed format.
Have you tried passing your string into the constructor?
Here's a sample from https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Date
var birthday = new Date("December 17, 1995 03:24:00");
I have ASP.NET MVC site with ordinary Html Form with text field to put Date in.
<input type="textbox" name="date"/>
Controller method looks like:
void DoSomething(DateTime date)
{
....
}
As users have different locales and habits how to enter date how shall I handle DateTime formats? I guess there should be code that try to parse string to several date time formats. Can I handle all DateTime(s) params centralized without Helper class call every time controller expects DateTime ? How can I take into account user locale ?
Thank you in advance!
You can use jQuery UI datepicker for example, and set the format. This will also be a better user experience then a simple textbox..
$('#datetime').datepicker({ format: 'yy-mm-dd hh:ii' });
Datepicker provides support for localizing its content to cater for
different languages and date formats.
Best practice here is to force users to enter only one date format.
You can achieve this with RegularExpression validation and date picker such as JQuery Datepicker.
UPDATE :
Also, if you not want to force users to one format, please check DateTime.Parse method of C# but it is a little tricky and you need to be careful while using it. There might be some conflicts. (E.g. 2011-01-01 can be seen as two different dates if you don't know the format.)
If you try to handle every type of formats you will have to provide the type of the format.
Issue that is commonly faced is mm-dd-yy and dd-mm-yy format say 02-01-11. Question is is it 2 Jan or 1 Feb.
If you are able to send the correct format type there shouldn't be any problem other than the input string could be wrong itself.
The best solution (which you may not be looking for) is to validate date/time while user inputs in the form. Like making separate drop down box(or just text box) for date and month.
I use asp.net 4 and c#.
I need to use a WebControl of type Validation namely RegularExpressionValidator to detect data inputed in a TextBox that IS NOT in format yyyy-MM-dd (String).
Any idea how to write the RegEx to apply ot this control?
Thanks
Here's one possible regex:
^\d{4}-((0\d)|(1[012]))-(([012]\d)|3[01])$
Note: this will prevent months >12 and days >31, but won't check specific months for length (ie it won't block 30th Feb or 31st Apr). You could write a regex to do that, but it would be quite lengthy, and 29th Feb is always going to give you problems in regex.
I'd say if you need that kind of fine-grained validation, you're better off parsing the date with a date library; regex isn't the tool for you. This regex should be sufficient for basic pre-validation though.
I've also gone lenient on the year; just checking that it's four digits. But if you want some sort of sanity check (ie within certain bounds), it shouldn't be too hard to add. Foe example, if you want to match only dates in the this century, you would replace the \d{4} at the beginning of the regex with 20\d{2}. Again, trying to validate a date with excessive accuracy in regex is going to be difficult and you should use a date parser, but you can get basic century-level matching quite easily to prevent the user entering anything really silly.
Finally, I've put ^ and $ to tie off the ends of the string so it can't match if the user enters a valid date and extra characters as well. (You may want to add a string length validator for this as well).
Hope that helps.
Spudley's answer above allows 00 for day and month.
I fixed it :
^\d{4}-((0[1-9])|(1[012]))-((0[1-9]|[12]\d)|3[01])$
Note: neither of these expressions check for days in a month that are invalid, e.g. 04/31, 06/31 or 02/29 on non-leap years.
Regular expression \d\d\d\d-\d\d-\d\d should do the trick.
I would like to add a little change in Spudley's answer:
^\d{4}$|^\d{4}-((0?\d)|(1[012]))-(((0?|[12])\d)|3[01])$
so you can use date like 2013-5-5 (month and date is not necessary the zero but can be used)
Hope it helps.
Another implementation for ISO 8601 structured dates:
^\d{4}-\d{1,2}-\d{1,2}\s\d{1,2}:\d{1,2}:\d{1,2}.?\d{0,}$
It's not quite as strict, and will accept incorrect dates, but it should validate that it follows the ISO 8601 structure even if the date is a non-existent one. It should also be fairly simple to understand for anyone with a basic Regex understanding.
If you really want to ensure the date is correct, and work with it, run DateTime.TryParse() on it.
(19|20)[0-9]{2}-(0[1-9]|1[012])-(0[1-9]|[12][0-9]|3[01])
mach result:
1999-09-12
((([0-9][0-9][0-9][1-9])|([1-9][0-9][0-9][0-9])|([0-9][1-9][0-9][0-9])|([0-9][0-9][1-9][0-9]))-((0[13578])|(1[02]))-((0[1-9])|([12][0-9])|(3[01])))|((([0-9][0-9][0-9][1-9])|([1-9][0-9][0-9][0-9])|([0-9][1-9][0-9][0-9])|([0-9][0-9][1-9][0-9]))-((0[469])|11)-((0[1-9])|([12][0-9])|(30)))|(((000[48])|([0-9]0-9)|([0-9][1-9][02468][048])|([1-9][0-9][02468][048]))-02-((0[1-9])|([12][0-9])))|((([0-9][0-9][0-9][1-9])|([1-9][0-9][0-9][0-9])|([0-9][1-9][0-9][0-9])|([0-9][0-9][1-9][0-9]))-02-((0[1-9])|([1][0-9])|([2][0-8])))
This is the regex for yyyy-MM-dd format.
You can replace - with \/ for yyyy/MM/dd...
Tested working perfect..
This seems like something I should be able to find on Google but I'm not having much look.
I'd like to format a date as day/month. Only thing I've found it {0:M} which displays the information I want however the month written out like December rather than "12". I need to use 02/12 if possible due to space restrictions.
Thanks for any help!
You could try the following format:
{0:dd/MM}
Have you simply tried:
myDateTime.ToString(#"dd/MM");
Are you sure its ignoring your local computer regional settings ?
What happens if you do:
Console.WriteLine(date1.ToString("M", CultureInfo.CreateSpecificCulture("en-US")));