Asp-net web api output datetime with the letter T - javascript

the data in the DB look like this
2011-09-07 14:43:22.520
But my Web API outputs the data and replace the space with the letter T
2011-09-07T14:43:22.520
I can replace the letter T with a space again in jquery, but can I fix this problem from the Web API (make the web api output the original data?)
I also do not want the miliseconds at the end. How can I get rid of them?

The format of how you see the date in the database is usually irrelevant, because it should be passed into .Net as a DateTime - not as a string. (If you are storing it as a varchar in the database, you have a bigger problem.)
ASP.Net WebAPI is returning the value in format defined by ISO8601 and RFC3339. This is a good thing, as it is a recognized machine-readable format. You probably don't want to change it.
If you really want to change it, you would need to implement a custom JSON.Net JsonConverter, deriving from DateTimeConverterBase. This is discussed here and here.
But instead, you should consider how you are using the actual result in your client application. You mentioned jQuery, so I will assume your consumer is JavaScript. In many browsers, the ISO8601 value that you have is already recognized by the JavaScript Date constructor, so you might be able to just do this:
var dt = new Date("2011-09-07T14:43:22.520");
But this won't work in all browsers. And Date doesn't have a whole lot of flexibility when it comes to formatting. So instead, you might want to consider a library such as moment.js. With that in place, you can do this:
var m = moment("2011-09-07T14:43:22.520");
var s = m.format("YYYY-MM-DD HH:mm:ss"); // output: "2011-09-07 14:43:22"
Please note that the format string here conforms to moment.js, not to .NET. There are differences in case sensitivity. Please refer to the moment.js documentation for details.
One other thing - since the value you provided doesn't have either a Z at the end, nor does it have an offset such as -07:00, then I assume it came from a DateTime whos .Kind value is DateTimeKind.Unspecified. You should be aware that when this gets sent into JavaScript (or anywhere else for that matter), there is no information about what time zone is represented. JavaScript will assume the local time zone of the browser.
If that's not what you had intended, then you need to store UTC values in your database, and make sure they have DateTimeKind.Utc so they get serialized with a Z at the end. JavaScript will normalize this to the browser's time zone, but you will still be talking about the same moment in time.
Alternatively, you could use a DateTimeOffset type - which would serialize with the specific offset. JavaScript will still normalize this to the user's time zone.

Related

Using Python to parse date/time strings in *exactly* the same way as Javascript?

I have some client-side JavaScript code which reads a string and tries to parse it into a Date() object via new Date(theString), displaying the resulting Date as a UTC string to the user. If it's a string that can't be turned into a Date, of course, it becomes an Invalid Date, in which case instead it displays "Not a date/time."
I also have some server-side Python code which essentially does the same thing: takes the user-submitted maybe-a-date, and stores it as either a UTC string or as "not a date".
The trick is, I need the two pieces of code to always behave exactly the same on every single string. I could certainly just make a tiny Python endpoint that uses the existing Python code to send the appropriate response back to the client instead of using Date() client-side, but for various reasons that's an undesirable solution.
So is there a way to translate strings into dates in Python that's guaranteed to work exactly the same way as new Date(myString) does in JavaScript?
So is there a way to translate strings into dates in Python that's guaranteed to work exactly the same way as new Date(myString) does in JavaScript?
No.
It's impossible, because:
Parsing of strings other than the two formats specified in ECMA-262 is implementation dependent and it is easily demonstrated that different implemetations parse the same string differently (e.g. Why does Date.parse('COVINGTONOFFICE-2') return a real date?)
How various implementations parse unsupported formats is not documented, so you can only determine the rules through observing behaviour of every possible string, including those that look nothing like a date, in every implementation, then knowing which implementation you were trying to imitate

MomentJs output Date of toDate() is incorrect

I've started using momentJs in an Angular/Typescript project. (Included incase it's relevant in any way although I very much doubt it)
In the run method of my module I call
moment.locale(window.navigator.language);
which correctly sets the locale to en-GB in my instance. Further down the line I use moment to parse a GB time.
when doing the following:
var mom = moment("24/11/2015 00:00:00");
for example. This populates a new moment object using the defaults set on the moment global (If i understand how it should work correctly). moms date is set to 2016-12-11T00:00:00.000Z. This clearly means it's parsed the given string in en-US instead of en-GB which was set via Locale in a default setting prior to this call. Is there anything I've missed in configuration/setup of moment which would make this not work?
I've also inspected the _locale property of my variable. mom._locale is set to en-gb and I can see the L,LL,LLL etc etc formats are all en-GB formatted values (as they should be).
running mom.toDate(); unsurprizingly returns the 2016 date stored internally by the moment object.
Some misc information I forgot to include:
I am using the latest release of momentjs from NuGet (Version 2.10.6 at time of writing) and I've included moment-with-locales.js in my HTML
Using any recent version of MomentJS, you should see why in the console:
Deprecation warning: moment construction falls back to js Date. This is discouraged and will be removed in upcoming major release. Please refer to https://github.com/moment/moment/issues/1407 for more info.
Unless you specify a format string, MomentJS relies on the Date object's parsing, and unfortunately, regardless of locale the Date object will, with a string using /, assume U.S. format. One of the many, many things that aren't quite right with Date.
You'll need to use a format string, or supply the string in the simplified ISO-8601 format used by Date. From Parse > String:
When creating a moment from a string, we first check if the string matches known ISO 8601 formats, then fall back to new Date(string) if a known format is not found.
var day = moment("1995-12-25");
Warning: Browser support for parsing strings is inconsistent. Because there is no specification on which formats should be supported, what works in some browsers will not work in other browsers.
For consistent results parsing anything other than ISO 8601 strings, you should use String + Format.
So I got around this by fetching the locale data from moment and just passing it into the format parameter. Considering the example input of "24/11/2015 00:00:00" I would structure my format as below:
var format = moment.localeData().longDateFormat('L') + " " + moment.localeData().longDateFormat("LTS");
this generates the format mask of "DD/MM/YYYY HH:mm:ss".
You can mix and match whatever formats you want and this will be locale specific to whatever you set moment.locale("") to be (presuming you have the locale information setup in moment already)
This is a crazy workaround and I'm surprised that moment doesn't presume locale information as default when parsing. TJCrowder has raised an issue on Github with the moment guys which I suggest anyone who cares should comment on. https://github.com/moment/moment/issues/2770
You're probably better off passing the format to moment directly and validating the string before hand. This will ultimately reduce the amount of debugging you'll need to do and get you up and running straight away.
var mom = moment("24/11/2015 00:00:00", "DD/MM/YYYY HH:mm:ss");
You could try the new(ish) Intl API but browser support is limited (IE11+), so I would recommend having a user select the month in a dropdown or something to force them to input a certain way.

MomentJS .date() issue

Could anyone please explain me why moment("2013-04-22 00:00:00+07:00").date() returns 21?
For example moment("2013-04-22 00:00:00+02:00").date() returns 22.
I would be interested in getting the date without taking into account any timezone info in the string from which the moment object is built, i.e. always 22 in this particular example.
I think I figured it out: moment("iso8601_string") parses/converts that string into a local time. In my case, I'm in the UTC+2 timezone, so parsing strings containing "+02:00" (or "+01:00") and then calling .date() returns 22 because the time stored in the moment object matches my local time.
However, when parsing a string with e.g. "+07:00", the time stored in the moment object will be my local time, in which case the date will actually be different, a day before.
I think also my original requirement was convoluted and based on an incorrect assumption. My use-case was that I got the datetime from some UI widget always as date+time, but I needed only the date. Writing a unit test which parsed a string containing "+07:00" caused the date to be "incorrect". However this was an incorrect assumption, because (at least in my use-case) the datetime from the UI widget will always be in the local time so the code won't ever parse a string containing "+07:00".
I'm not sure that a use-case as I originally stated does exist in the real world:
you get a string containing a date in another timezone
you need to take the date out of it, but in the timezone of that date (why?)
I guess normally whenever getting a date from somewhere remote the convention is to always get UTC, that way the point of reference is clear and you can convert it further locally. So probably the case when you get a date in a random timezone and need the date from it, in that timezone, isn't common. Still, as an academic question, I don't know how I would be able to get the date out of it in that case :)

Angular app and internationalization and localization

we have an existing silverlight app which runs in browser + on hardware.
we want to rewrite this app using angular js and html5.
one of the key requirements with new system is support of internationalization and localization. and target countries are usa, brazil, italy for now.
Am new to this area and have lot of basic questions.
does existing database needs to be redesigned to support same ? i mean to identify columns (product_name/customer_name etc) that needs to have locale specific data and then store data for each locale and modify sprocs and webapi to accept language parameter and then get content based on that. ?
I believe we need to user nvarchar for such columns.
what will happen to currency and date time columns in db ? say there is quantity column then what should be data type of this column in db ? if current locale is Portuguese then will qty stored in Portuguese number.
what is the best practices for storing and retrieving currency column
based on locale.
what is the best practices for storing and retrieving date column
based on locale.
how to handle string checks, numeric checks in webapi methods ?
how to do comparison and checks in javascript for string,number,datetime
please share link to some good pointers which could help.
so in short right from javascript to .net webapi to database (sql) how should we take care of locale dependent logic and fields
thanks.
A lot of questions, let's see if I can answer those.
If your existing application is properly internationalized, I don't think there is any need to modify the database. Just make sure it is able to handle international characters (NCHAR, NVARCHAR, NTEXT in MS SQL, valid character encodings in others).
As for DB design, it is good to keep things locale-independent as long as you can. For instance it is better to store keys in the database and resolve them at runtime. However, if your data is dynamic (i.e. you have product names and their descriptions that changes often), the only way to go is to have translation table and look the data up using valid locale. It's quite complex in relational world (i.e. joins), but it could be done.
2,3. All the numeric columns should be kept locale-independent and formatted on the UI side. The more problematic would be prices and sales orders - you would need an additional column to store the currency code (i.e. 12.34 | USD). On the UI side you would need to pass the code to the Angular currency filter. The only gotcha here is, Angular does not support easy locale context switching, so you would need to use a hacky library like Angular Dynamic Locale to load the formats for you.
Similar. Keep it locale-independent. DB built-in types should automatically handle that for you and give you nice DateTime/DateTimeOffset (in a .Net world) back. The only gotcha would be the time zone - it may make sense to use DATETIMEOFFSET MS SQL type, as others does not store time zone.
There is an alternative way to store date and times in the database - you may decide to store it as a number of milliseconds since January 1, 1970 UTC - as BIGINT type. Especially if you are going to read this directly to JS, you will be able to easily re-create JS Date object (should you need this for calculations or something) in a valid time zone (it works the other way round as well). All you have to do to format date is to use this number (not date, that is AFAIR) and Angular's date filter with UTC as a parameter.
I don't think I understand what you're asking exactly. I guess the question is about validation of user input, rather than API. Well, beware of using Regular Expressions, because JavaScript doesn't handle Unicode well (at least in this area). You'd need to ask more precise question.
Assuming that you have Number and Date objects (i.e. typeof o == 'number') it is straightforward (as in obj1 === obj2).
As far as strings are concerned... Well, str1 === str2 will give you valid answer if you want to be exact. If you want to sort them, modern web browsers (Chrome 14+, Firefox 29+, IE11+) implement EcmaScript 402 Internationalization API so you can do something like str1.localeCompare(str2, locale), see this article.
The real problem occurs when you want to compare two strings case insensitive and accent insensitive for equality (as oppose for ordering like in case of sorting). Basically, there is no way (and this is true even in "big" programming languages like Java or C#).

Localize dates on a browser?

Let's say I have a date that I can represent in a culture-invariant format (ISO 8601).
I'll pick July 6, 2009, 3:54 pm UTC time in Paris, a.k.a. 5:54 pm local time in Paris observing daylight savings.
2009-07-06T15:54:12.000+02:00
OK... is there any hidden gem of markup that will tell the browser to convert that string into a localized version of it?
The closest solution is using Javascript's Date.prototype.toLocaleString(). It certainly does a good job, but it can be slow to iterate over a lot of dates, and it relies on Javascript.
Is there any HTML, CSS, XSLT, or otherwise semantic markup that a browser will recognize and automatically render the correct localized string?
Edit:
The method I am currently using is replacing the text of an HTML element with a localized string:
Starting with:
<span class="date">2009/07/06 15:54:12 GMT</span>
Using Javascript (with jQuery):
var dates = $("span.date", context);
// use for loop instead of .each() for speed
for(var i=0,len=dates.length; i < len; i++) {
// parse the date
var d = new Date(dates.eq(i).text());
// set the text to the localized string
dates.eq(i).text(d.toLocaleString());
}
From a practical point of view, it makes the text "flash" to the new value when the Javascript runs, and I don't like it.
From a principles point of view, I don't get why we need to do this - the browser should be able to localize standard things like currency, dates, numbers, as long as we mark it up as such.
A follow up question: Why do browsers/the Web not have such a simple feature - take a standard data item, and format it according to the client's settings?
I use toLocaleString() on my site, and I've never had a problem with the speed of it. How are you getting the server date into the Date object? Parsing?
I add a comment node right before I display the date as the server sees it. Inside the comment node is the date/time of that post as the number of milliseconds since epoch. In Rails, for example:
<!--<%= post.created_at.to_i * 1000 %>-->
If they have JS enabled, I use jQuery to grab those nodes, get the value of the comment, then:
var date = new Date();
date.setTime(msFromEpoch);
// output date.toLocaleString()
If they don't have JS enabled, they can feel free to do the conversion in their head.
If you're trying to parse the ISO time, that may be the cause of your slowness. Also, how many dates are we talking?
Unfortunately, there is not.
HTML & CSS are strictly used for presentation, as such, there is no "smarts" built in to change the way things are displayed.
Your best bet would be to use a server side language (like .NET, Python, etc.) to emit the dates into the HTML in the format you want them shown to your user.
It is not possible to do this with HTML, it has no smart tags that can make any kind of decisions like this. It is strictly presentational. I do wonder, though, if HTML5 perhaps has a tag for something like this...
Anyways, the way I see it, you have 3 options:
Stick to the Javascript way. There's questions with more details on it on this website, such as How do I display a date/time in the user’s locale format and time offset? and How can I determine a web user’s time zone?
Try to use geolocation. That is, your server side script fires off a request to one of the many geolocator services out there on the user's first page visit to try and guess where the user is. The downside of this is that it will be wrong about 10% of the time, so it's not that much better than the market share Javascript is going to get you.... (all in all, then, not a very good method...)
Ask the user! You will see that most websites that want to display a tailored experience for you will ask you this sort of thing because it's just not possible to know. As a neat fallback, you could wrap the question around <noscript> tags so you only ask those with Javascript disabled while offering the Javascript experience to those that have it.
Dojo has some pretty good localizations for dates and currencies. Using this method also allows you to pick different formats (e.g.: short date vs long date) and force locales.
The language and the user's locale should be sent on the HTTP header. You can use those to create the correct date format server-side to be displayed to the user. However, this is often undesirable because many users completely ignore their locale settings in their OS and/or browser. So, you may be feeding USA style timestamps to New Zealanders.
I liked the trick posted in the comment above, but it sounds like a QA headache, since you could be dealing with a large number of clients that implement timestamps in very different ways.
The most effective solution I have seen, is to simple provide a panel to allow your users to choose what time format they like. Some users even ****gasp**** like ISO formats. Then you do the time format conversion server side. If your application language does not have good locale to timezone formatting mapping, check your database. Many databases provide locale-based customized timezone formatting as well.
Because this anwser still popups in google I share that this is now possible to do by using a readonly datetime-local input (see below) and you can then style the input the way you want:
<input type="datetime-local" value="2018-06-12T19:30" readonly />
For more information see: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/datetime-local

Categories

Resources