60

I am stuck in a weird situation and unfortunately, even after doing some RnD and googling, I am unable to solve this problem.

I have a date string in ISO format, like 2014-11-03T19:38:34.203Z and i want to convert it into a date object with new Date() method.

But when i do so, output is:

var isoDate = '2014-11-03T19:38:34.203Z';
console.log(new Date(isoDate)); //output is: Tue Nov 04 2014 01:08:34 GMT+0530 (IST)

The date which i passed is of 3 Nov,2014 and the output is 4 Nov,2014 and it's because of GMT +5.30 of our local time(IST).

So, is there any generic method with which i can get the date object which return the date of Nov 3,2014.

NOTE: I don't have any issues with timestamp. We can change time string to zero with setHours() method. The only thing which i want is date object like new Date() having date of 3 Nov,2014.

Flip
  • 6,233
  • 7
  • 46
  • 75
Mohit Pandey
  • 3,679
  • 7
  • 26
  • 38
  • let date = new Date(isoDate); date = new Date(date.getUTCYear(), date.getUTCMonth(), ...) – John Feb 11 '22 at 04:04

10 Answers10

53

Do not pass strings to the Date constructor, it is notoriously bad at parsing strings. IE 8, for one, will not parse ISO 8601 format strings at all and return NaN. It's really simple to write your own parser:

function parseISOString(s) {
  var b = s.split(/\D+/);
  return new Date(Date.UTC(b[0], --b[1], b[2], b[3], b[4], b[5], b[6]));
}

Note also that if the time is 19:38:34.203 UTC and your timezone is UTC +0530, then the time in that timezone is 01:08:34 am on the following day, hence the difference in dates. For example, for a person on the east coast of Australia but not observing daylight saving (i.e. UTC +10), it's equivalent to:

4 November, 2014 05:38:34

Edit

So if you want to return it to an ISO date, you can use the getISO* methods to create whatever format that suits, e.g.

function isoFormatDMY(d) {  
  function pad(n) {return (n<10? '0' :  '') + n}
  return pad(d.getUTCDate()) + '/' + pad(d.getUTCMonth() + 1) + '/' + d.getUTCFullYear();
}

var s = '2014-11-03T19:38:34.203Z';
var date = parseISOString(s);

console.log(isoFormatDMY(date)) // 03/11/2014

or use ES5's toISOString:

 parseISOString('2014-11-03T19:38:34.203Z').toISOString(); // 2014-11-03T19:38:34.203Z

A simple polyfill for pre ES5 browsers:

if (!Date.prototype.toISOString) {

  Date.prototype.toISOString = function() {

    var d = this;

    // Padding functions 
    function pad(n) {return (n<10? '0' :  '') + n}
    function padd(n){return (n<100? '0' : '') + pad(n)}

    return d.getUTCFullYear() + '-' + pad(d.getUTCMonth() + 1) + '-' + pad(d.getUTCDate()) +
           'T' + pad(d.getUTCHours()) + ':' + pad(d.getUTCMinutes()) + ':' + 
           pad(d.getUTCSeconds()) + '.' + padd(d.getMilliseconds()) + 'Z';
  }
}
RobG
  • 142,382
  • 31
  • 172
  • 209
  • You are right. But as per my requirement, i need to show ISO date (in my case, its 3 Nov,2014). – Mohit Pandey Nov 19 '14 at 09:50
  • 3
    do we still need to do this 2019?, specifically nodejs. I should be fine with "new Date(s)" – PathToLife Nov 13 '19 at 11:53
  • 1
    @Pathfinder—yes, no. There are two formats supported by ECMA-262 that should be OK in a controlled environment, but elsewhere avoid the built–in parser for all strings. – RobG Nov 13 '19 at 23:02
  • 1
    @RobG I am using this similar script of yours found here on stack:```function parseDate(s) { var b = s.split(/\D/); return new Date(b[0], b[1]-1, b[2], b[3], b[4], b[5]);}``` I am trying to **shift** the time **one hour forward** for **timezone change** and the only thing that seems to work is ```return new Date(b[0], b[1]-1, b[2], b[3], b[4], 36+b[5]);}``` because it appears that each unit increment **before** ```b[5]``` equals 100 seconds, so 3600/100=36. Is there a more methodic way to do this or simply some reference to understand better instead of avancing by trial & error? – John Galassi Jan 03 '20 at 20:15
  • If you want to shift forward by 1 hour, then `Number(b[3]) + 1` should do. You're working with strings so should convert to number for `+` to be addition not concatenation. `36 + b[5]` will prepend the string literal "36" to whatever the value of b[5] is. If it's "00" you'll get "3600" which I guess ads an hour but it's a bit of a kludge to me. – RobG Jan 04 '20 at 03:58
  • [Here](https://tc39.es/ecma262/multipage/numbers-and-dates.html#sec-date.prototype.toisostring) could be the new - ECMA6? - doc of `toIsoString()` – Timo Apr 18 '22 at 12:10
18

You can use "getUTCDate()" to get actual date.

var d = new Date('2014-11-03T19:38:34.203Z');
var n = d.getUTCDate();

But it will return only date. to get month "getUTCMonth()" and to get year "getUTCFullYear()". Then construct all in to your format. For example

var n=[];
var d = new Date('2014-11-03T19:38:34.203Z');
var s = d.getUTCDate();
n.push(s);
s=d.getUTCMonth();
n.push(s);
s=d.getUTCFullYear();
n.push(s);

Finally make n as an object.

Community
  • 1
  • 1
7

I also did not care about timestamp/timezone as I am returning only dates from SQL in ISO format. To avoid the day being either one ahead or one behind when converting to Date object, this works:

moment(ISOStringHere, 'YYYY-MM-DD HH:mm'); // leaving off Z makes it UTC to match database

This requires the Moment JS library located here:

https://momentjs.com/

CaptainDingle
  • 97
  • 1
  • 3
3

Here's a function that works well for those that need to support older browsers and adjust correctly for timezones in the date strings. I used RobG's answer as a starting point, but had to modify it heavily because it wasn't working for me with strings that had offsets for the timezone like "-07:00" (i.e. strings that don't end in "Z").

// Parse an ISO date string (i.e. "2019-01-18T00:00:00.000Z",
// "2019-01-17T17:00:00.000-07:00", or "2019-01-18T07:00:00.000+07:00",
// which are the same time) and return a JavaScript Date object with the
// value represented by the string.
function isoStringToDate( isoString ) {

    // Split the string into an array based on the digit groups.
    var dateParts = isoString.split( /\D+/ );

    // Set up a date object with the current time.
    var returnDate = new Date();

    // Manually parse the parts of the string and set each part for the
    // date. Note: Using the UTC versions of these functions is necessary
    // because we're manually adjusting for time zones stored in the
    // string.
    returnDate.setUTCFullYear( parseInt( dateParts[ 0 ] ) );

    // The month numbers are one "off" from what normal humans would expect
    // because January == 0.
    returnDate.setUTCMonth( parseInt( dateParts[ 1 ] ) - 1 );
    returnDate.setUTCDate( parseInt( dateParts[ 2 ] ) );

    // Set the time parts of the date object.
    returnDate.setUTCHours( parseInt( dateParts[ 3 ] ) );
    returnDate.setUTCMinutes( parseInt( dateParts[ 4 ] ) );
    returnDate.setUTCSeconds( parseInt( dateParts[ 5 ] ) );
    returnDate.setUTCMilliseconds( parseInt( dateParts[ 6 ] ) );

    // Track the number of hours we need to adjust the date by based
    // on the timezone.
    var timezoneOffsetHours = 0;

    // If there's a value for either the hours or minutes offset.
    if ( dateParts[ 7 ] || dateParts[ 8 ] ) {

        // Track the number of minutes we need to adjust the date by
        // based on the timezone.
        var timezoneOffsetMinutes = 0;

        // If there's a value for the minutes offset.
        if ( dateParts[ 8 ] ) {

            // Convert the minutes value into an hours value.
            timezoneOffsetMinutes = parseInt( dateParts[ 8 ] ) / 60;
        }

        // Add the hours and minutes values to get the total offset in
        // hours.
        timezoneOffsetHours = parseInt( dateParts[ 7 ] ) + timezoneOffsetMinutes;

        // If the sign for the timezone is a plus to indicate the
        // timezone is ahead of UTC time.
        if ( isoString.substr( -6, 1 ) == "+" ) {

            // Make the offset negative since the hours will need to be
            // subtracted from the date.
            timezoneOffsetHours *= -1;
        }
    }

    // Get the current hours for the date and add the offset to get the
    // correct time adjusted for timezone.
    returnDate.setHours( returnDate.getHours() + timezoneOffsetHours );

    // Return the Date object calculated from the string.
    return returnDate;
}

Usage/a couple tests:

// All three of these tests output the same date (relative to your
// timezone) as they should, which in my case is:
// "Thu Jan 17 2019 17:00:00 GMT-0700 (Mountain Standard Time)".
console.log( isoStringToDate( "2019-01-18T00:00:00.000Z" ) );
console.log( isoStringToDate( "2019-01-17T17:00:00.000-07:00" ) );
console.log( isoStringToDate( "2019-01-18T07:00:00.000+07:00" ) );
Clément Prévost
  • 8,000
  • 2
  • 36
  • 51
kevinmicke
  • 5,038
  • 2
  • 20
  • 22
2

I started of with kevinmicke's excellent answer, but since I needed this for a code generator, I was concerned with code size. Eventually I ended up with this:

const parseDate = dateString => {
  const b = dateString.split(/\D+/);
  const offsetMult = dateString.indexOf('+') !== -1 ? -1 : 1;
  const hrOffset = offsetMult * (+b[7] || 0);
  const minOffset = offsetMult * (+b[8] || 0);  
  return new Date(Date.UTC(+b[0], +b[1] - 1, +b[2], +b[3] + hrOffset, +b[4] + minOffset, +b[5], +b[6] || 0));
};
Michal Filip
  • 870
  • 8
  • 9
1

Well it depends on what you want to do with the object later. You can always refer to "UTC" date functions of javascript.

Check the reference: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date

Lashus
  • 399
  • 1
  • 9
  • I want a `date` object which i further used in kendo charts to represent the data. With `Date.UTC`,i guess, i am not able to get the `date` object. – Mohit Pandey Nov 19 '14 at 09:20
  • Well you don't have to change the object itself. You just can use the method for getting for an ex. utc string - .toUTCString() – Lashus Nov 19 '14 at 09:23
1
new Date(this.datePipe.transform(isoDate,'yyyy-MM-dd HH:mm:ss', 'UTC'));

Angular datepipe transform will convert it to a simple date time format as specified with no timezone. In case of ISO string format, the date constructor would have treated it as UTC time, but now, the Date constructor treats it as the local time.

Example in my case(IST):

input string: 2020-04-19T09:15:00.000Z
after transform this.datePipe.transform(input string)
2020-04-19 09:15:00
Date object 
new Date(this.datePipe.transform(isoDate,'yyyy-MM-dd HH:mm:ss', 'UTC'));//treats the transformed date as local timezone date when creating the date object
Sun Apr 19 2020 09:15:00 GMT+0530 (India Standard Time)
David Buck
  • 3,752
  • 35
  • 31
  • 35
Akshay
  • 11
  • 2
-1

how to get time and date from iso string javascript

var isoDate = '2014-11-03T19:38:34.203Z';
isoDate.getFullYear()+'-' + (isoDate.getMonth()+1) + '-'+isoDate.getDate();

iso to date javascript

date = new Date(isoDate);
date.getFullYear()+'-' + (date.getMonth()+1) + '-'+date.getDate();
MD SHAYON
  • 7,001
  • 45
  • 38
-1

i have used moment js to convert to UTC - REFERENCE LINK

https://momentjs.com/docs/#/parsing/utc/

let dateRange = moment.utc("2021-11-11T20:00:00Z").format("YYYY-MM-DD")

let dateRange = moment.utc("2021-11-11T20:00:00Z").format("YYYY-MM-DD")
alert(new Date(dateRange))
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.20.1/moment.min.js"></script>
-4

For display purposes, you could simply do this... Given 'Date' in ISO format you could implement,

<div> {{Date | date:"dd MMM yy hh:mm a" }} </div>

A nifty trick to display (only display) the date in required format.

Hope it helps!

AnweshCR7
  • 68
  • 1
  • 6
  • 1
    Does you see question's description and question's tag, all include pure javascript code. there no Angular Usage or any JS framework include Bind data So your answer out of topic – ahmed hamdy Mar 23 '20 at 20:11