Date object in safari - javascript

I am using safari 8.0, And I try to do
new Date('sat-oct-10-2015');
on chrome the result is Date object with the right date. But on safari the result is
Invalid Date
how can I work with dates in this format in safari?

Do not use the Date constructor (or Date.parse) to parse strings. Until ES5, parsing of date strings was entirely implementation dependent. After that, the long form of ISO 8606 has been specified, however parts of that changed with ECMAScript 2015 so that even using specified formats is not consistent across browsers (e.g. 2015-10-15 12:00:00 may result in 3 different results in browsers currently in use).
The solution is to manually parse date strings, either write your own function (which is not difficult if you only need to support one format) or use a small library.

Always try to use the standard date format specified by ECMAScript ISO format.
Date.parse() i.e Date constructor will always produce the expected result if you use the standard string format. Also the browser may support additional string formats, but that may not be supported by all other browser vendors.

When creating a Date object with a “human-readable” string, you must use a certain format, usually conforming to RFC2822 or ISO 8601.
It may be that a browser is able to process your new Date('sat-oct-10-2015');, but this is not demanded by the specifications.
Hint: Look at some other ways to create a date object, for example with a Unix timestamp. This is easier and more reliable than the dateString approach.

I'd suggest using moment.js for dates in JavaScript. Then you can simply parse the date with
moment('sat-oct-10-2015', 'ddd-MMM-DD-YYYY').format();
moments API has good support in all major browsers and eases date manipulating and displaying with JavaScript.

Related

How do I accept multiple formats of date with moment.js

I want to accept dates from the users but I cannot enforce the users to enter the date in a specific format. I have tried going through the momentjs documentation but couldn't really find how its done. I can specify an array of formats but then I'll be tied down to those specific formats only.
I know that MS Excel and many other apps does this. (Take date input in some format and convert it to the application suitable format)
If not with moment.js how else can I achieve this? What could be the algorithm or logic that can achieve this thing.
Thanks!
Moment.js can parse an ambiguous string as a date if you don't specify expected formats. It will first attempt to parse it as an ISO 8601 date format, then as an RFC 2822 format and ultimately fall back to JS Date parsing. Keep in mind the supported formats in a JS Date are inconsistent between browsers.
For this reason it's highly advised to always parse using a set of expected formats and enforce the user to input in one of these. Otherwise you may end up with incorrectly parsed dates.

getTime() not working on Safari the way it works on Chrome

What's the best way to get this to work on both Chrome and Safari? Works fine on Chrome. Returns NaN on Safari.
new Date("2018-11-22 14:24:34 -0800").getTime()
You shouldn't pass the date as a String to the constructor of Date because that causes Date.parse() to be called.
The Date.parse() method parses a string representation of a date, and returns the number of milliseconds since January 1, 1970, 00:00:00 UTC or NaN if the string is unrecognized or, in some cases, contains illegal date values (e.g. 2015-02-31).
It is not recommended to use Date.parse as until ES5, parsing of strings was entirely implementation dependent. There are still many differences in how different hosts parse date strings, therefore date strings should be manually parsed (a library can help if many different formats are to be accommodated).
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/parse
To mitigate those differences in implementation, I recommend you use a library like moment.js.
Try using this for the safari browser support:
new Date(("2018-11-22 14:24:34").replace(/-/g, "/")).getTime().valueOf()

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.

ISO 8601 Date JS Interpretation Difference - IE/FF versus Chrome

Why do IE/FF and Chrome javascript engines differ on how to interpret this Date format (YYYY-MM-DDTHH:mm:ss.fff) without the timezone designator?
new Date("2015-02-18T15:43:57.803").getUTCHours()
UTC Hours
Chrome: 15
IE11/FF: 21
I don't understand this - is it because Chrome assumes it's local whereas IE/FF assume it's UTC? This seems like a Chrome bug.
Interestingly - appending a "Z" to the end of the string tells both Chrome and IE/FF that the time is UTC and they can agree. Has anyone else noticed this javascript implementation discrepancy with Date?
new Date("2015-02-18T15:43:57.803Z").getUTCHours()
UTC Hours
Chrome: 15
IE11/FF: 15
Ultimately - this is the result of the out-of-box serializer for ASP.NET Web API, which I thought used JSON.NET, but now appears to be internal where JSON.NET uses IsoDateTimeConverter.
Checking GlobalConfiguration.Configuration.Formatters.JsonFormatter tells me we're using JsonMediaTypeFormatter. Is Web API not using JSON.NET serializer out of the box?
This is a boon for Web API people - at least back in ASP.NET MVC we had a consistent date format (albeit proprietary - /Date(number of ticks)/) via the JavascriptSerializer
ES5 says that ISO 8601 format dates without a time zone should be treated as local(that interpretation has since been revised), but the ed. 6 draft says to treat them as UTC. Some script engines have implemented ed. 6, some ES5 and the rest neither.
The ed. 6 (and later) aren't consistent with the ISO 8601 specification.
The bottom line is don't use Date.parse (or pass strings to the Date constructor), manually parse date strings.
For us, the crux of this issue is that DateTimeStyles.RoundtripKind only works if your DateTime properties set the DateTime.DateTimeKind (other than DateTimeKind.Unspecified - the default) or better yet - using DateTimeOffset which enforces use of the TimeZone specificity.
Since we already had DateTime class properties, we worked around this for now by assigning the JsonSerializerSettings.DateTimeZoneHandling from DateTimeZoneHandling.RoundtripKind (DateTime default) to DateTimeZoneHandling.Utc in our Global.asax.cs. This change essentially appends the "Z" to the end of the DateTime - however there is one more step to convert the Local time to UTC.
The second step is to provide the offset by assigning IsoDateTimeConverter.DateTimeStyles which JSON.NET JsonSerializer will pickup from a SerializerSettings.Converters and automatically convert from Local time to UTC - much like the out-of-the-box ASP.NET MVC does.
Obviously - there are other options, but this is solution worked for us.
Global.asax.cs
protected void Application_Start() {
GlobalConfiguration.Configuration.Formatters.JsonFormatter.SerializerSettings.DateTimeZoneHandling = Newtonsoft.Json.DateTimeZoneHandling.Utc;
GlobalConfiguration.Configuration.Formatters.JsonFormatter.SerializerSettings.Converters.Add(new IsoDateTimeConverter() { DateTimeStyles = DateTimeStyles.AdjustToUniversal });
}
The reason this works is because RoundtripKind honors DateTime's DateTimeKind - which is Unspecified by default. We want to explicitly convert this to UTC - which JavaScriptSerializer used to do for us out of the box for ASP.NET MVC. The regional offset is provided by DateTimeStyles.AdjustToUniversal which converts your Local DateTime to UTC.

formatting ISO date

I have making an API call and getting response.
The response has datetime value like this
20131107T102103,00+01
I guess this is ISO date format. I am not able to format it to human readable format using javascript.
This is indeed ISO 8601, but it's not exactly the most common form of it.
This is the compact form. On the web, we usually see the extended form, which is also described in RFC 3339.
It's using a comma instead of a decimal in the seconds field. While either are allowed by the ISO 8601 specification, most implementations use a decimal point.
While ISO 8601 allows for a shortened form of the offset (+01), typically this is expressed in the compact form as +0100, or in the extended form as +01:00.
Nonetheless, the value is ISO 8601 compliant, so it should be parseable by most newer browsers. But it's not.
Internet Explorer 11
Google Chrome 35
Firefox 30
So, what to do then? You can write a bunch of code to pull out all the individual parts of the string and build a Date object yourself, but that's too much work. Just use moment.js. This is one of the leading libraries for parsing and formatting date and time in JavaScript, and it works in all browsers.
// parse it to a moment object first
var s = "20131107T102103,00+01";
var m = moment(s + "00","YYYYMMDD[T]HHmmss[,]SSZZ");
// then you can output however you like
m.format("...whatever...")
// or perhaps you need a JS Date object
m.toDate()
Notice that I still had to add two extra zeros to the offset. Even moment.js doesn't recognize offsets with only two digits.
date_default_timezone_set('America/New_York');
$d1=new DateTime('20131107T102103,00+01');
$date = DATE_FORMAT($d1,'Y-m-d H:i:s');

Categories

Resources