MomentJS .date() issue - javascript

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 :)

Related

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.

using moment js to pass in time zone and get hours offset?

I want to pass a three-digit time zone string like "GMT" or "EST" and get the offset like "-05:00" as a string from it.
Moment seems to handle it but I couldn't find a way...
This capability you are asking about has been deprecated. Tim Wood in this thread says:
The problem is that Date.prototype.toString returns such different results. That is the only place to get the timezone name (PST, CST, EST, etc). If this method is not returning any timezone information (as is the case with FF10 and IE9, there is no way to get it.
In that same thread there are mentions by some people about how they are able to get the abbreviated time zone and consequently pass it to moment but only in certain browsers.

Asp-net web api output datetime with the letter T

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.

json date returned from wcf service not consistent

I have a service that returns a date. The weird thing is that most of the time it comes back like this: /Date(1364227320000)/
but sometimes it returns the date like this /Date(1364050020139-0400)/
when I open up the visual studio debugger, the dates look the same for each one (minus differences in time)
What could account for this difference?
This is handled in System.Runtime.Serialization.Json.JsonWriterDelegator.WriteDateTimeInDefaultFormat(). If the DateTimeKind is Unspecified or Local, it adds the UtcOffset to the end (the -400 part, meaning Utc - 4 hours).
It depends on the kind of the DateTime object (i.e., the value of its Kind property). If you're returning a DateTime with DateTimeKind.Utc, there will be no offset. If the date time is of kind Local or Unspecified, the offset will be written out.
You can find more information about the format in the "DateTime Wire Format" section of the "Stand-Alone JSON Serialization" page on MSDN.

moment.utc('date string').format('DD-MMM-YYYY') returns the previous date

The Date in my database is getting stored as: '31-MAR-20'. I am using the following code to display the date back on UI.
moment.utc(data['dateString']).format('DD-MMM-YYYY');
But the above code is displaying the previous date i.e. 30-Mar-2020. How do I correct this issue ? Can I do it without using moment.js.
Thanks
You could attempt to use the default moment() for local mode.
From those docs:
moment(...) is local mode. Ambiguous input (without offset) is assumed to be local time. Unambiguous input (with offset) is adjusted to local time.
Example:
moment(data['dateString']).format('DD-MMM-YYYY');
NOTE: depending on your sites use case (especially if you plan to have global visitors), it may be a good idea to store the date in UTC for translation purposes like this. To ensure everyone sees the date relative to their location.

Categories

Resources