What is the best way to parse dates in binder - c#

Is it good approach in the model binder use the code like this:
TryParseDate(result.AttemptedValue, format, out parsedDate)
And then "format" is a variable with different (customer specific) date format. Like 12/31/2013 or 31.12.2013 or other ones.
I have big problem with the format binding because if user puts the date with only 1 digit like: 1/1/2014 it will not parse because in the "format" value allowed formats: dd/MM/yyyy
I know that it is possible to resolve by replacing this format to d/M/yyyy and then it works for both case, but is it good approach or it is dangerous?
Thank you in advance!

I would recommend leaving the default model binder to do its work, it does a pretty good job of it and will deal with localization issues (ie. different date formats for different locales) for you.
Consider that there will always be restrictions on how a user can enter a date (you don't allow them to enter yyyy-MM-dd for example, even though it is a valid date format). Your custom binder code won't change that because it supplies a format.
I'd suggest that your goal should be to permit users to enter dates in the format that would be most usual for them (eg. dd/MM/yyyy in UK or Spain, MM/dd/yyyy in US etc). That will deal with the majority of cases. If you need to cater for users in different locales, the default model binder will do it all for you, so long as you set the thread culture for the user session:
string cultureCode = "en-GB"; //retrieve eg. from user profile
Thread.CurrentThread.CurrentCulture = new CultureInfo(cultureCode)
If you want to help users who are inputting dates in other formats, simply put a hint on your page that explains the expected format.
If you really must accept multiple formats per locale, you will need to write a custom model binder, and might want to try passing an array of acceptable formats to it for each locale that you deal with.

Related

Allowing users to input several different types of DateTime formats

I have an application where I allow users to input different DateTime formats. So they could add into a list something like 'MM/dd/yyyy' or 'MM/DD/YYYY' etc, etc. Is there a way for me to check their input against a dataset of different of acceptable formats? Id like to display an error to them if they input a format which is not accepted by their culture.
I've seen posts here where you can use the DateTime TryParse or TryParseExact, but those seem to check the syntax of a string of an actual date like say '01/20/2016' as opposed to checking the actual format type as I describe above.
I've seen many posts where I can do something like :
var formats = new[] { "dd/MM/yyyy", "yyyy-MM-dd" };
And then use that format array as a check against an actual date, but can I check against a user input of the actual format type? Also I would rather not have to create a list myself of acceptable formats, but would rather use some type of already existing dictionary of acceptable formats to check against. I have looked around but have come up short handed in my pursuit. If there is some documentation out there or some method that could help me, please point me in the correct direction so that I can investigate it. Thanks.

Check environments timezone settings

I want to be able to check against the environments timezone settings and if its not a US timezone then I will handle the datetime with a more global format. For example. I have a user in America their settings is MM-DD-YYYY now if I have another user in Canada they want to see DD-MM-YYYY but instead of just giving them different versions I would rather have some logic that grabs the timezone and compares it against something and then that determines how the datetime will be handled.
if(System.TimeZone.StandardTime = US)
{
objOrderEntryItemUsageReport.VarShipDate = Convert.ToDateTime(datpkrShipDate.Value).ToString("MM/DD/YYYY");
}
else
{
objOrderEntryItemUsageReport.VarShipDate = Convert.ToDateTime(datpkrShipDate.Value).ToString("DD/MM/YYYY");
I just don't know the best way to check the environments timezone settings and even how to compare it to see if its a US timezone?
Would I need to create a dictionary with the American timezones in it and then do a while loop through that dictionary to see if the current timezone matches and if not then handle it like an international user?
The user's time zone and the user's culture are entirely separate matters.
It's not clear where this code is running, but basically you want to use the appropriate CultureInfo, and then you can use DateTime.TryParse specifying the culture. You can use TryParseExact specifying a standard format of d for "short date format". (Likewise for calls to ToString... just pass in the culture and a format of d.)
Alternatively - and preferably - use a DateTimePicker so you don't need to parse the value at all. (Given your names, it's possible that you're already using a DateTimePicker, so it's unclear why you're calling Convert.ToDateTime - the Value property is already of type DateTime.
Then, don't convert it to a string later either - your VarShipDate property shouldn't be a string property, it should be a DateTime property. That's what you're trying to represent, after all. Avoid string conversions as far as you possibly can. They are error-prone, culturally sensitive, and basically full of potential fail.
Additionally, I would strongly advise against using System.TimeZone - use System.TimeZoneInfo, which is effectively the replacement for TimeZone.

CultureInfo.InvariantCulture in plain english

I know that culture rules for dates/numbers is enough for an entire book, I think I have a simple question though..
Does using InvariantCulture basically mean that you explicitly define what culture the value (date/number/whatever) will be inputted/displayed as? And it overrides any other culture setting (such as the user agent's setting)?
If an app is built for an audience of one and only one culture, would it make sense to use InvariantCulture and define how you want values inputted/displayed each time?
Does using InvariantCulture basically mean that you explicitly define what culture the value (date/number/whatever) will be inputted/displayed as?
No. It's just a culture which is a bit like US English, except for a few things like currency sign. It's usually used to format/consume text which is to be understood or was produced by another computer rather than a human.
If an app is built for an audience of one and only one culture, would it make sense to use InvariantCulture and define how you want values inputted/displayed each time?
No, you would use the relevant CultureInfo for that culture. You could also explicitly define the format for dates etc, but that's an orthogonal concern. It may well be best to use one of the predefined standard formats for that culture, but if none of those meet your needs you can always be explicit.
InvariantCulture is Independent of any culture or any factor.
For example if you're using new CultureInfo("en-US") it will get you US English Culture(Which may not be actual US English Culture because OS gives you option to change these setting in Control Panel) it will return the modified version of Culture of "en-US" if any custom formatting applied to it.
In other words InvariantCulture will always gives you a Culture which can never be changed across Systems.
Let's assume you want to serialize some value(say double) and pass to another application or some other thread which is running in different culture leads to serious problems.
Consider the following code
Thread.CurrentThread.CurrentCulture = new CultureInfo("fr");
double source = 455.62d;
string serialized = source.ToString();//455,62 since `, is the decimal seperator` in "fr"
Thread t = new Thread((x) =>
{
double deserialized = double.Parse(((string)x));
Console.WriteLine(string.Format("Deserialized value is {0}", deserialized));//outputs 45562
});
t.CurrentCulture = new CultureInfo("en-US");
t.Start(serialized);
numbers matters more right? consider this string denotes AccountBalance?
Hope this helps
With specific regard to DateTime, the best advice I can give is to use CultureInfo.InvariantCulture for ParseExact and ToString when you have an exact format in mind. (You can also use it with Parse if you happen to know that your input format matches the invariant culture's formats, but I typically avoid this.)
Don't use the invariant culture when interacting with a user.
Keep in mind that the culture contains several items, including the ordering of day/month/year parts, the date and time part separator characters, the character encoding, and the language-specific names of the days of the week, months of the year, and abbreviations including am/pm.
Some examples of when you should use the invariant culture:
Files on disk, especially text files of a predefined format
External APIs, especially JSON or XML
Unit tests, unless you are specifically testing culture issues
Some examples of when you should use a specific culture such as en-US:
User Interface
Reports

ASP.NET MVC DateTime manual input conversion best practice

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.

Localized Date Validator

Is there a way to use user's culture to localize the Range Validator for date? I am looking for a good way to validate date and avoiding to provide a fix format (e.g.: do a dd/mm/yyyy using Regular Expression Validator)
Use the Date.TryParseExact() method, consulting the documentation.
Use members of the returned My.Application.Culture.CurrentCulture.DateTimeFormat object, which is of class System.Globalization.DateTimeFormatInfo, to retrieve the date formats for the current culture (there are several formats for every culture, such as long format and short format...).
This will be something closest to what I want actually.
Getting user's language preference based on language settings:
userLanguage = Request.UserLanguages[0];
Get ShortDatePattern base on language:
new CultureInfo(userLanguage).DateTimeFormat.ShortDatePattern;
From here I will use the pattern to validate user's input and to display the required format on the page.

Categories