formatting dates incorrectly, trying to understand the reason - c#

sorry if this question is a little ... strange, but I am a little lost to what is happening and how to control it. What I need to better understand is the following:
I have an ASP MVC application that works with Linq-To-SQL and an MSSQL server. The application is an inside (office only) website, and I am mentioning that so it wont sound that strange when I say that we wanted to ignore browser language, culture, date, whatever... settings and always display the date in the format "dd/MM/yyyy". Always.
So, now that I am testing a specific form in the website I encounter something very, very strange.
The first strange thing is that the date is not displayed on the screen correctly. Let me elaborate, I have a simple view that gets some data, read from the database, inside a model. So, as I fought for sometime with teaching the datetime object to display in a certain way on server level (meaning giving it an attribute like [Display(..)] or [DataType(...)] didn't force the date to look the way I want, so I simply wrote the following:
<input id="BirthDate" name="BirthDate" type="text" value="<%= Model.BirthDate.HasValue ? Model.BirthDate.Value.ToString("dd/MM/yyyy") : "" %>" class="text-box datepicker" />
However, even though I am specifically formatting the date to display "dd/MM/yyyy" in the input, it doesnt. When the browser settings are Dutch, the value inside this box is displayed with 'dd-MM-yyyy'.
I can somehow accept that, the browser is a smart guy(or gal) and identifies that the value in the box is a date and applies formatting according to the selected language settings. I don't know how to tell it not to screw with my dates, but I can get to believe that this is what happens. HOWEVER, what I am finding a lot difficult to accept is that THE Date formatting somehow goes back to the database. This sentance didnt really mean anything so I am explaining again. I have a table that has a few columns, one of them being a varchar(100). Super, and because of some very interesting designing, that field can contain text, dates and whatever.
So, because the field is a string, and later on I simply display it in a paragraph and dont need to do the whole dance of casting it to a DateTime object and then formatting it back when it gets in the view (which works so perfectly as I previously mentioned) I simply save it in the table in the correct format (dd/MM/yyyy).
Yea, but not really. My code would look like that:
var date = DateTime.Now;
db.EmployeeHistory log = new EmployeeHistory();
log.ActionType = 1;
log.EmployeeId = 1671;
log.At = date;
log.Context = "A TEST";
log.ObjectTitle = "Who cares";
log.EmployeeHistoryChangesSets.Add(new EmployeeHistoryChangesSet()
{ PropertyName = "TEST PROPERTY", NewValue = date.ToString("dd/MM/yyyy"), OldValue = date.ToString() });
dataContext.EmployeeHistories.InsertOnSubmit(log);
dataContext.SubmitChanges();
This is a of course a test, one that didnt make me happy at all. Because, if you are paying attention, there is a field in the database which is mapped to a string (varchar(...)) and then I am taking the Date, make it a string with the .ToString() method while formatting it into a "dd/MM/yyyy" format. So I am not using dates (well I am using a Date object to get the date, but I am converting it to a string) I am using only strings.
And somehow, for some reason that is truly escaping me, the string/date is saved in the database in the format: 'dd-MM-yyyy'. I really didnt expect it to behave in such a way. At first I was going to accept my fate, even though I was having a really hard time accepting that the database will take the liberty to format my input even though IT IS a string.
So, further testing showed me that the Date.ToString("dd/MM/yyyy") method actually returns the date in 'dd-MM-yyyy', depending on the browser language settings. Meaning that if I change my settings and it works correctly again ("dd/MM/yyyy").
So, my question is, what am I missing? Why is the .ToString() method not formatting the date correctly? Is my analisys correct or am I up and to the right on this one? If there is a good reason for that (even though I cant come up with one), should I just create my own extension method for DateTime class and implement the formatting mannualy or is there a better way?
I am really sorry for the long post (again). I would appreciate some clarity, as the whole project will behave this way. Thanks in advance

Related

C# .Net Linq and converting datetime to formatted sting

I have the query
var result = (from myView in db.loginSessions
where myView.machine.ToUpper().Equals(machine.ToUpper())
&& myView.start >= myStart
&& myView.end <= myEnd
orderby myView.start
select new loginSessionList {
Id = myView.id,
Machine = myView.machine.ToUpper(),
Start = myView.start.ToString("u"),
End = myView.end.ToString("u"),
User = myView.username
}).ToList();
I get ArgumentOutOfRange exceptions on the datetime conversions. I have tried different ToString conversion strings. I have tried the other To... date->string conversions offered by Intellisence. I have tried Convert.string(myView.start). Nothing has worked. I have googled and have found advice using all the things I have tried. Do I have to post-process the generated list?
What have I missed?
I have 3 rules for dealing with DateTimes that served me well:
Always store, retreive and transmit the UTC value. Translating into the proper local Timezone is the job of ToString(), wich asks Windows for the users timezone. You do not want to add timezones to your troubles.
Avoid store, retreive or transmission of DateTimes as strings. Keep it in proper types whenever possible
If you can not follow rule 2 (like when you deal with Serialsiation), at least pick a fixed Culture Format and String encoding on all endpoints. You do not want to get different Cultures or faulty implied Encodings to your existing troubles
So, the answer to my issue had nothing to do with Linq or .Net. #JoeEnos put me on the right track as mentioned in my comment to his comment. I had created a class to receive each row of query result. The date fields were initially DateTime types but I started having issues. I changed those fields to string and then ended up asking my question above.
Back when the receiving class still had the DateTime fields, all of the fields had lowercase names. I must have applied some sort of code formatting that CamelCased the field names. This meant that after serializing the results the CamelCased names could not be found and the javascript didn't care.
I fixed the field names in my js code, changed the field data types back to DateTime and all is good.
Thanks

General number formatting (#,00) in mvc asp.net and switching between formats

My main problem is that i need to be able to have asp.mvc accept the Danish number format (meaning a dot every thousand and a comma seperator). Since i am working on a larger system, I need a more in-depth solution.
The formating problem includes the fact that I need to beable to solve the errorhandling aswell, which does not accept the 0,00 as a number. best case, the solution still maintains the possibility to calculate with the numbers without having to format them each time.
As another point, I need to beable to switch between the English format, meaning (0.00) and the Danish (0,00).
TL;DR
Solve the problem of using a diffrent formatting in mvc asp.net from (en 0.00) to (da 0,00), including errorhandling, still allowing for calculations in jquery or javascript, and the posibility to switch back to the english format (0.00).
What would be the best way to go about this?
Edit: Solved most of it!
To get the View (Jquery validate) to accept comma as a seperator I've inserted "One regexp" from this: http://mfranc.com/javascript/jquery-valdiator-modyfing-decimal-separator/
Adding the custom model binding, provided by #chrispratt solved the problem of the controller receiving the number in the right format.
On top of this I've added code to modify any number entered into an input field into the right format.
Also all numbers and their display formats are checked before being shown. (since some doubles display without ,00)
I think that should be it, now all that remains is to devise some method of switching between languages and formats, which I should beable to manage.
Thanks for the help!
Any help is apprichiated!
Thanks in advance!

WorkFront / AtTask API $$TODAYe+6m flaw?

The workfront API isn't returning the same results as our web report:
On our web front-end on workfront one of the reports has a date range from $$TODAYbw to $$TODAYe+6m and it returned about ~500 rows.
I tried the same query on the API like so (formatted for easier reading)
/v7.0/RSALLO/search
?fields=DE:project:Probability,allocationDate,scheduledHours,project:name,project:status,roleID,project:status,role:name
&allocationDate_Mod=between
&allocationDate=$$TODAYbw
&allocationDate_Range=$$TODAYe+6m
&AND:0:project:status_Mod=notin
&AND:0:project:status=CPL
&AND:0:project:status=DED
&AND:0:project:status=REJ
&AND:0:project:status=UZF
&AND:0:project:status=IDA
&AND:0:roleID_Mod=in
&AND:0:roleID=55cb58b8001cc9bc1bd9767e080f6c10
&AND:0:roleID=55cb58b8001cc9bd9fc0f8b03a581493
&AND:0:roleID=55cb58b8001cc9bfaa01243cd6024b6d
&AND:0:roleID=55cb58b8001cc9c0afa399dece405efd
&$$LIMIT=1000
which returned barely any results. Notice the &allocationDate_Range=$$TODAYe+6m line. If I change it to read =$$TODAY+6m without the end of day modifier the API returns ~500 rows.
I went through every filter criteria and it's only the allocationDate range that is going wrong. I found this resource for the date modifiers and in it there is no e+6m example, yet it works on our web front-end report.
Is the API flawed or is the web report doing something extra in the background?
I don't have an exact solution for your problem, but I can confirm that the API does have some difficulty parsing wildcards like you're trying to use and they don't always come up the way we expect. Furthermore, the API doesn't parse things the same way as text mode reporting, so a query that looks great in the latter might return something different in the former.
If I may propose a different solution, since you're already coding this up outside of Workfront then I suggest you simply perform the date calculations on your own and pass explicit datetime objects to Workfront instead of allowing it to use its own logic. I know this doesn't answer the question of "what is a query that will return exactly what I want" but it should give you the correct end result.
For what it's worth, I spent about 15 minutes trying to get an example working on my end and I gave up after it kept returning values which should have been outside of my own date range.

C#: Dateformat in C# for Inserting to sql server

I have a textbox with date format dd/MM/yyyy that I want to convert to the format yyyy-MM-dd to insert it into a database.
I tried
Convert.DateTime/DateTime.ParseExact
but it always give me the system's default date format.
I don't know any other method to convert it in C#...
You shouldn't be converting it to a string at all to insert it into your database. (I'm surprised at all the other answers which are recommending this approach.)
Instead, you should be using parameterized SQL, and set the value of the parameter to the DateTime value you've got. You should be using parameterized SQL anyway to avoid SQL injection attacks, and to keep your code and data separate. The fact that it avoids unnecessary string conversions (each of which is a potential pain point) is yet another benefit.
This part of your question suggests you've got a fundamental misconception:
I used Convert.DateTime/DateTime.ParseExact it always give me system date format.
Those methods will give you a DateTime. A DateTime doesn't have a format. When you call ToString you just get the default format for the current culture, but that's not part of the value. It's like with numbers - 16 and 0x10 are the same number, and the int doesn't "know" whether it's in decimal or hex; it's a meaningless concept.
All of this goes beyond your immediate problem, towards trying to keep your code base clean in terms of types. You should keep data in its most appropriate form for as much of the time as you possibly can, and make sure you understand exactly what that data means at all points. Conversions to other types (such as strings) for communication should be done only at API/system boundaries, and avoided even there if possible (e.g. using parameterized SQL as in this case).
There are many methods but none so useful and logical than using Parametrized SQL. Here's the Wikipedia page! For more information on Parametrized SQL statements, Visit this Coding Horror page!
There is actually no need to change it. This is just the display format, but the 'DateTime' object inside stays the same. Depending on how you want to insert, you can just use:
string dateValue = DateTime.Now.ToString("yyyy-MM-dd");
And insert this in your query string.
EDIT
But as Jon Skeet commented, building your query string manually like this should never be done. A cleaner approach like parameterized SQL or utilizing NHibernate should be your first concern.
Hope this works!
DateTime variable= Convert.ToDateTime(your date);
You can format it like this:
string sDateTime = Convert.ToDateTime(txtTextBox.Text).ToString("yyyy-MM-dd");
Edit
There are many ways to skin a cat when it comes to preparing information for entry into a database. My solution here answers the OP directly, however I very much acknowledge that there are better ways to do this.
I'd suggest reading through Jon Skeet's post on this page as well, as he raises some extremely valid points regarding the approach of the OP.
Hope that helps.

Data Annotation Phone Number Conversion

I want to gracefully convert phone number input from my users into a specific phone number format.
I would like convert this with a dataAnnotation, Just as
[dataType(dataType.Date)] displays a dateTime as a string
Ie:
0205938472 into +61205938472
02 0593 8472 into +61205938472
0593 8472 into +61205938472 (I will assume the area code from where
they live or if its a mobile)
02-0593-8472 into +61205938472
Etc, I also want to convert the other direction:
+61205938472 into 02 0593 8472 (Or whatever format i choose)
I want to do this to promote readability for the user but retain a strict data type in the database.
Questions
Is using a dataAnnotation in this manner considered bad practice?
How would I actually write the dataAnnotation( /However you would do it)?
(please include some code)
Edit: to clarify, i do not want someone to write the extension for me, I would just like an example of key pieces of code and implementation.
Please Note
These are Australia, New Zealand and internationally formatted
numbers being stored as internationally formatted numbers.
And International Formatted numbers being converted to Australia, New Zealand or internationally formatted depending on the user's location (which i can determine)
Depending on the UI you're using, you might be able to do this using a:
ASP.NET: Custom binding code (see example)
ASP.NET MVC: ModelBinder
WPF: CustomBinder
Windows Forms: Custom Converters/Editors
As parsing and formatting usually happens in the UI layer, I doubt you will find a solution that works at the data/model layer and which will work universally or which can do more than just validation.
In the data annotations namespace, there is a DataType.PhoneNumber which you can attach to your properties. Though you, yourself, remain responsible to do the parsing and the formatting using the appropriate display technology.
Data annotations and datatype are used for validation, not for converting values. The datatype is mostly used so that the validation knows where to start guessing.
2. That is asking too much for someone to code an extension like that, especially without showing any effort.
You can use DataTypeAttribute like so:
[DataType(DataType.PhoneNumber)]
public string PhoneNumber{get; set;}

Categories

Resources