Generating a date from a string

Given two strings, `2017-03-15` (date) and `12:26` (time), the objective is to create a localized date object without relying on any library.

Assuming the current date and time are: `Tue Mar 14 2017 12:26:33 GMT+0800 (AWST)`, using the code:

new Date( date + 'T' + time )

Results in an incorrect output as the date is interpreted as UTC:

Wed Mar 15 2017 20:26:00 GMT+0800 (AWST)

If a space is used instead:

new Date( date + ' ' + time )

The result is correct:

Wed Mar 15 2017 12:26:00 GMT+0800 (AWST)

However, this method will not function correctly on Safari (without the T). In fact, Safari will throw an error!

It is acknowledged that parsing date strings varies by implementation. Therefore, the most accurate approach would be:

var timeSplit = time.split(':');
var dateSplit = date.split('-');

new Date( dateSplit[0], dateSplit[1] - 1, dateSplit[2], timeSplit[ 0 ], timeSplit[ 1 ] )

Nevertheless, this solution may seem cumbersome. Is there a more efficient method that works consistently across different browsers?

Answer №1

The result is incorrect due to the consideration of the date as UTC:

This issue stemmed from a mistake in the ES5 specification, which stated that no timezone indicator meant UTC, contrary to the ISO-8601 standard it was supposed to adhere to. ES2015 rectified this by defining that no timezone indicator implied local time (in alignment with ISO-8601), but this would have caused compatibility issues when used on strings containing dates only (like "2018-01-17"). Subsequently, ES2016 made further adjustments, leading to stability since then. In cases where there is no timezone indicator:

  • A date-only string (e.g., "2019-05-20") is parsed in UTC
  • A date/time string (e.g., "2019-05-20T10:00") is parsed in local time

Due to these specification inconsistencies, various JavaScript engines initially exhibited behaviors aligned with old specifications (ES5), ES2015, or ES2016. Notably, iOS continues to maintain an incorrect behavior.

As of May 20th, 2019, the situation is as follows:

  • Desktop versions of Chrome, Firefox, Edge, and even IE11 all correctly adhere to the ES2016+ specification.
  • Safari (on desktop or iOS) erroneously parses date/time strings without timezone indicators as UTC.
  • All current iOS browsers (including Safari, Chrome, Firefox, Brave, Dolphin...) also parse date/time strings without timezone indicators as UTC due to the use of JavaScriptCore (JSC) on iOS. The limitation arises because non-Apple iOS applications cannot allocate executable memory for other optimizing engines like V8 or SpiderMonkey, hence resorting to JSC. (Chrome's V8 may transition away from JSC towards a "JIT-less" interpreter.)

You can verify your browser's behavior through the following code snippet:

var may20 = new Date("2019-05-20");
// If parsed in UTC, UTC hours should be 0
console.log(may20.getUTCHours() === 0 ? "OK:" : "Error:", may20.toLocaleString());

var may20At10 = new Date("2019-05-20T10:00");
// If parsed in local time, local hours should be 10
console.log(may20At10.getHours() === 10 ? "OK:" : "Error:", may20At10.toLocaleString());

(The accuracy of this check depends on the differentiation between UTC and local time on May 20th, 2019. It works in regions like the UK [GMT+0100] or New York [not on GMT], but not in locations observing GMT year-round like Timbuktu.)

Note, Safari does not support this without the T.

Indeed, the only mandatory date/time format supported by JavaScript engines is the ISO-8601 subset defined here (along with the output of toString, albeit its specifics are unspecified). Current observations as of May 20th, 2019, indicate Safari's deviation from this specification.

However, isn't there a more elegant solution compatible across different browsers?

The process may seem complex, but that's the necessary mechanism within the Date constructor. By incorporating it into your standard library, you ensure seamless functionality.

Answer №2

My results are incorrect because the date is being treated as UTC:

Consider this:

new Date('2017-03-15T12:26')

Internet Explorer up to version 8 sees it as an invalid string, while IE 9+ and Firefox 38 treat it as UTC.

Using a space instead... yields the correct result

However, Safari returns an invalid date without the 'T'.

In fact, Safari will throw an error if you try without the 'T'

All versions of ECMAScript handle this consistently. Safari rejects it as a valid ISO 8601 string, while others fallback on implementation-specific methods.

The lesson learned here is to avoid using Date constructor for parsing strings (or Date.parse).

To do it correctly, manual parsing is the only option...

You can use libraries for convenience, but they essentially do the same thing.

Is there a universal solution that works on all browsers?

No. Push for better standards by joining the ECMA TC39 committee and advocating for a more robust Date object with a proper parser and formatter. There are plenty of good implementations available in other languages and existing JavaScript libraries.

Unfortunately, parsing has been overlooked and ECMA-402 now handles formatting inadequately for dates.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Explore our product gallery with just a simple hover

I am looking to design a product list page with a mouseover gallery similar to the one showcased on [this page][1]. I attempted to use a vertical carousel like the one illustrated in this Fiddle, but unfortunately, it does not function like Zalando and jc ...

What makes a single numerical value in an array suitable for basic arithmetic operations?

I find it puzzling how an empty array or an array with just one "numerical" value can be used in various calculations. [] * [] === 0 // true [2] * [2] === 4 // true ["2"] * ["2"] === 4 // true Interestingly, not every operator behaves in the same way. ...

Developing a Chessboard Using JavaScript

Seeking help with a Javascript chessboard project. I have successfully created the board itself, but facing difficulty assigning appropriate classes (black or white) to each square. Managed to assign classes for the first row, struggling with the remainin ...

Maximizing the use of JavaScript's prototype.js library: Passing parameters to callback functions

My understanding of JavaScript is limited to using it for Dynamic HTML. However, I am now exploring Ajax and facing an issue with the code below (taken from and modified to suit my requirements). I need to pass the update_id parameter to the onSubmit fun ...

Tips for integrating the C++ icon into a ReactJs project

For a ReactJs project, I needed to include icons of different Languages and Tools. When adding a Python icon, I used: <ListItem> <ListItemIcon className={classes.icon}> <span className="iconify" data-icon= ...

I am encountering the ERR_STREAM_WRITE_AFTER_END error in my Node.js API. Does anyone know how to resolve this problem?

When I try to upload a file using the API from the UI, I encounter the following issue. I am interacting with a Node.js API from React.js and then making calls to a public API from the Node.js server. https://i.stack.imgur.com/2th8H.png Node version: 10. ...

Iterate through each selection from the multiple chosen in Select2, and utilize jQuery to add the text value of the

When I click a button, I want to add the selected item(s) to a div #list <select class="select2" multiple="multiple" name="string_items[]" id="string_items"> <option>value I want to add</option> </select> Transition from this: ...

Enhancing User Experience: Creating a Vue Button Component for Adding Items to Cart with the Power of Axios and Laravel Backend Integration

I have recently developed a Vue3 shopping cart with an "Add One" button feature. When the user clicks this button, it updates an input field of type "number" and sends a request to update the database using Axios along with Laravel's createOrUpdate me ...

Get the base64 encoding of a File object by utilizing the FileReader.readAsDataURL() method

Currently, I am facing an issue with converting a JS File object into a base64 value and returning that value within a JSON object. My approach involves using FileReader.readAsDataURL(), however, due to the asynchronous nature of this process, it appears t ...

Add the component view to the webpage's body section

Using Angular 7 and ngx-bootstrap 4.0.1 Dependencies: "bootstrap": "3.3.7", "bootstrap-colorpicker": "2.5.1", "bootstrap-duallistbox": "3.0.6", "bootstrap-markdown": "2.10.0", "bootstrap-progressbar": "0.9.0", "bootstrap-slider": "9.8.0", "bootstrap-tags ...

Headers can't be set after they have been sent. This issue arises when calling create(data,cb) function

I am a beginner in Node.js and I am attempting to create a model in MongoDB. However, when I make a call to localhost:3000/a, I notice that the request is being sent twice in the console and I am encountering an error stating "Can't set headers after ...

Hide the popup menu when the user clicks outside of it

I am presenting the following code <!DOCTYPE html> <html> <head> <title>GalacticCraft</title> <link rel="stylesheet" type="text/css" href="style.css" /> <link rel="shortcut icon" type="image/png" href="fa ...

Utilize PHP to transform JSON data into JavaScript

Hello, I am a newcomer to Stackoverflow and I need some assistance. My issue involves converting JSON with PHP to JavaScript. I am using PHP to fetch data from a database and create JSON, which I then want to convert for use in JavaScript as an object (obj ...

What is the process for displaying node_modules directories in a json/javascript document?

Exploring ways to showcase the dependencies within my d3.js tree, I am curious if it's possible to dynamically list the dependencies' names in a JSON file or directly within the javascript file. I'm puzzled by how JavaScript can access folde ...

How can I retrieve an updated object array within an extended class in JavaScript?

Hey everyone, I am new to working with ES6 classes. Currently, I am trying to inherit an initialized object (this._obj) with updated data in the class B, but I am encountering an issue where I am getting the length of the initialized object instead of the ...

Ensure there is a sufficient gap between the top and bottom icons within the Material-UI Drawer

I'm having difficulty articulating this, but I'd like to add two different sets of icons to the Drawer component. Set 1 should be displayed at the top in a standard column format, similar to the examples provided by them. Set 2 should go at the b ...

The module in the relative path cannot be located by Node.js

Node.js is giving me some trouble with exporting and importing classes from multiple files. In one file, I have two classes that I'm exporting using the following code: module.exports = {TrigInter, Hilbert}; However, when I try to import these classe ...

Problem with jQueryUI Sortable cancel property preventing input editing

Currently, I am utilizing jquery-3.2.1.min.js and jquery-ui.min.js version 1.12.1 The task at hand is to create a sortable list where certain elements are not sortable (specifically, other sortable lists). It is crucial that the input elements remain edit ...

Generate a line chart adorned with dots and customized labels utilizing a pair of distinct data sets

Is there a way to enhance my line graph with labeled dots using two separate data sets, one of which is from an API? For reference, I would like the graph to resemble the sample image linked here: https://i.sstatic.net/yUcWw.jpg Here are the details of th ...

Populating options in <select> for Internet Explorer version 5

Let me address the first question here. The reason why I am using IE5 is because I am working on a Windows CE device which limits me to this browser. My application involves a webpage with various elements. In my HTML code, I have two text fields and a se ...