Parse date without timezone javascript
Asked Answered
H

16

240

I want to parse a date without a timezone in JavaScript. I tried:

new Date(Date.parse("2005-07-08T00:00:00+0000"));

Which returned Fri Jul 08 2005 02:00:00 GMT+0200 (Central European Daylight Time):

new Date(Date.parse("2005-07-08 00:00:00 GMT+0000"));

returns the same result and:

new Date(Date.parse("2005-07-08 00:00:00 GMT-0000"));

also returns the same result.

I want to parse time:

  1. without time zone.
  2. without calling a constructor Date.UTC or new Date(year, month, day).
  3. by simply passing a string into the Date constructor (without prototype approaches).

I have to produce a Date object, not a String.

Hedgehog answered 9/7, 2013 at 10:18 Comment(4)
You could just omit the Date.parse btw and directly pass the string to the Date constructor.Allegraallegretto
I'm not sure why you need this but I'm pretty sure Date always has the user's local timezone. If you want your JavaScript to work with other timezones than you will have to use a wrapper object for Date, maybe this will work for you: github.com/mde/timezone-jsBussard
Unfortunatelly, I had to copy Date object to obtain correct object to compare dates in MongoDB: new Date(dateStart.getFullYear(), dateStart.getMonth(), dateStart.getDate())Hedgehog
If you want to parse a date without a time, you need to specify what time zone you want to assume, because "2005-07-08" means different things in different time zones. As of may 2020, the MDN documentation advises against any buit-in Date parsing features because of differences in implementation. However, using Date.parse("2005-07-08") will probably return a time of 00:00 UTC. date-fns parse on the other hand, will return 00:00 local time when parsing the same date stringTrillbee
J
169

The date is parsed correctly, it's just toString that displays the timestamp in your local timezone:

let s = "2005-07-08T11:22:33+0000";
let d = new Date(Date.parse(s));

// this logs for me 
// "Fri Jul 08 2005 13:22:33 GMT+0200 (Central European Summer Time)" 
// and something else for you

console.log(d.toString()) 

// this logs
// Fri, 08 Jul 2005 11:22:33 GMT
// for everyone

console.log(d.toUTCString())

Javascript Date object are time values - they merely contain a number of milliseconds since the epoch. There is no timezone info in a Date object. Which calendar date (day, minutes, seconds) this timestamp represents is a matter of the interpretation (one of to...String methods).

The above example shows that the date is being parsed correctly for offset +0000 - that is, it actually contains an amount of milliseconds corresponding to "2005-07-08T11:22:33" in GMT.

Jaynejaynell answered 9/7, 2013 at 10:26 Comment(14)
Unfortunatelly I have to produce Date object, not String.Hedgehog
I had checked it. I have passed the parsed date into MongoDB query new Date(Date.parse("2005-07-08T11:22:33+0000")), and date copied via constructor: new Date(dateStart.getFullYear(), dateStart.getMonth(), dateStart.getDate()). Both solutions, different results, second correct! Your reply was usefull, just mentioned in hunlock.com/blogs/Javascript_Dates-The_Complete_Reference. Up.Hedgehog
Worked perfectly for me - .toUTCString() was the ticket that gave me the correct time back from the original given string. i.e. new Date("2016-08-22T19:45:00.0000000").toUTCString()Wetzel
Firefox and Chrome genuinely behave differently here.Alunite
The root of all evil in JavaScript dates and time is contained in your first sentence... It's just toString that CONVERTS it to your local timezone... Where is single responsibility in this? toString method should just stringify the result and not convert it. If I want the date to be converted I should have other methods to do that.Meridithmeriel
It still returns a string rather than a date object. Not the solution to OP's question.Andersen
And yet at the end of your answer you say - 'in GMT'. That assumes there is a timezone given to the string - WHICH THERE IS. If there was no time zone given then conversion wouldn't be possible.Monkshood
Warn: parse time zone without : between hour and minute will result in invalid date on safari. '+0000' don't work, but '+00:00' doesCadet
the new part is soooo importantHunan
If your date string is just the date like "2021-01-05", then append to the string 00:00 for the hour like below: var x=d+' 00:00'; var dd=new Date(Date.parse(x));Culbreth
@anchor—there is no conversion. The date and time is displayed in the local timezone, the Date object is not altered.Caulfield
@Caulfield Javascript does not have a Date and Time concept, it only stores timestamp. When you send Date object through a wire, it does a toJSON() to that Date object and effectively converts that timestamp in a form of readable JSON format string. In that process it can shift the date. E.g. You live in Berlin which is UTC+2 currently (summer time). If you create a date like this new Date(‘2023-08-15T00:00:00’) it will assume that you mean local time. When you send this to the server, the server will accepted this as 2023-08-14T22:00:00.000Z. So in essence the date was shifted for one day.Meridithmeriel
@Caulfield to fix the issue of shifted date, good practice is to set the time to noon to your newly created Date object. e.g. new Date('2023-08:15T12:00:00'). In this way you will bypass any issues with timezones, daylight saving time and toJSON conversion.Meridithmeriel
@anchor—I wrote "The date and time is displayed…", not that it is stored in the Date object. Setting the time to noon is a terrible idea, it doesn't avoid timezone issues as there are a number of IANA representative locations with offsets of +12 and greater (e.g. Pacific/Kiritimati is +14). If you set the time to 12:00, how do you know the timestamp represents a date only and not date with a specific time? Dates can be sent in format you like, there is no compulsion to use toJSON or any other particular format.Caulfield
E
202

I have the same issue. I get a date as a String, for example: '2016-08-25T00:00:00', but I need to have Date object with correct time. To convert String into object, I use getTimezoneOffset:

var date = new Date('2016-08-25T00:00:00')
var userTimezoneOffset = date.getTimezoneOffset() * 60000;
new Date(date.getTime() - userTimezoneOffset);

getTimezoneOffset() will return ether negative or positive value. This must be subtracted to work in every location in world.

Entablement answered 29/8, 2016 at 15:25 Comment(9)
I have the same issue and found this to be helpful. However, I found that this doesn't handle time zone offsets due to daylight savings time. Example: I'm in PST so my current offset (in March) from GMT is -8:00, but in May it would be -7:00. My solution was to calculate var userTimezoneOffset = date.getTimezoneOffset()*60000;Linskey
Unless I'm a complete idiot, this actually returns the wrong time. getTimezoneOffset() returns the number of minutes in the opposite direction that you'd think--my timezone is UTC-4 right now but getTimezoneOffset() returns a positive 240. Therefore userTimezoneOffset should be subtracted from date.getTime(), not added to it.Dyeline
I will agree with @Dyeline you should substracted. wakwa's solution works only when you are correct side of Greenwich. Wakwas should correct it.Hat
Ah! spoke too soon. It doesn't work for most of the timezones. I can confirm that it returns a wrong date when offsetting AEST & CEST times with GMT time.Andersen
@Dyeline now the result is the same as new Date('2016-08-25T00:00:00Z') I think the point was to manipulate new Date('2016-08-25T00:00:00Z') so that local time is displayed with time 0:00 but this code missed ZRusch
Just to confirm, now this date is UTC time, and the valueOf() on it will return Unix Timestamp, correct?Police
It should be new Date(date.getTime() + userTimezoneOffset); as - will affect the timezone ahead of utc.Assentor
This is a good answer, but it's incomplete depending on the offset value. Here is a function for this task: ` /** * Remove timezone offset from date. */ function removeTimezoneOffset(date) { let userTimezoneOffset = date.getTimezoneOffset() * 60000; if(userTimezoneOffset >= 0) { return new Date(date.getTime() - userTimezoneOffset); } return new Date(date.getTime() + userTimezoneOffset); } `Pistole
@Pistole you could avoid the if statement by using Math.sign: return new Date(date.getTime() + userTimezoneOffset * Math.sign(userTimezoneOffset));Hydroid
J
169

The date is parsed correctly, it's just toString that displays the timestamp in your local timezone:

let s = "2005-07-08T11:22:33+0000";
let d = new Date(Date.parse(s));

// this logs for me 
// "Fri Jul 08 2005 13:22:33 GMT+0200 (Central European Summer Time)" 
// and something else for you

console.log(d.toString()) 

// this logs
// Fri, 08 Jul 2005 11:22:33 GMT
// for everyone

console.log(d.toUTCString())

Javascript Date object are time values - they merely contain a number of milliseconds since the epoch. There is no timezone info in a Date object. Which calendar date (day, minutes, seconds) this timestamp represents is a matter of the interpretation (one of to...String methods).

The above example shows that the date is being parsed correctly for offset +0000 - that is, it actually contains an amount of milliseconds corresponding to "2005-07-08T11:22:33" in GMT.

Jaynejaynell answered 9/7, 2013 at 10:26 Comment(14)
Unfortunatelly I have to produce Date object, not String.Hedgehog
I had checked it. I have passed the parsed date into MongoDB query new Date(Date.parse("2005-07-08T11:22:33+0000")), and date copied via constructor: new Date(dateStart.getFullYear(), dateStart.getMonth(), dateStart.getDate()). Both solutions, different results, second correct! Your reply was usefull, just mentioned in hunlock.com/blogs/Javascript_Dates-The_Complete_Reference. Up.Hedgehog
Worked perfectly for me - .toUTCString() was the ticket that gave me the correct time back from the original given string. i.e. new Date("2016-08-22T19:45:00.0000000").toUTCString()Wetzel
Firefox and Chrome genuinely behave differently here.Alunite
The root of all evil in JavaScript dates and time is contained in your first sentence... It's just toString that CONVERTS it to your local timezone... Where is single responsibility in this? toString method should just stringify the result and not convert it. If I want the date to be converted I should have other methods to do that.Meridithmeriel
It still returns a string rather than a date object. Not the solution to OP's question.Andersen
And yet at the end of your answer you say - 'in GMT'. That assumes there is a timezone given to the string - WHICH THERE IS. If there was no time zone given then conversion wouldn't be possible.Monkshood
Warn: parse time zone without : between hour and minute will result in invalid date on safari. '+0000' don't work, but '+00:00' doesCadet
the new part is soooo importantHunan
If your date string is just the date like "2021-01-05", then append to the string 00:00 for the hour like below: var x=d+' 00:00'; var dd=new Date(Date.parse(x));Culbreth
@anchor—there is no conversion. The date and time is displayed in the local timezone, the Date object is not altered.Caulfield
@Caulfield Javascript does not have a Date and Time concept, it only stores timestamp. When you send Date object through a wire, it does a toJSON() to that Date object and effectively converts that timestamp in a form of readable JSON format string. In that process it can shift the date. E.g. You live in Berlin which is UTC+2 currently (summer time). If you create a date like this new Date(‘2023-08-15T00:00:00’) it will assume that you mean local time. When you send this to the server, the server will accepted this as 2023-08-14T22:00:00.000Z. So in essence the date was shifted for one day.Meridithmeriel
@Caulfield to fix the issue of shifted date, good practice is to set the time to noon to your newly created Date object. e.g. new Date('2023-08:15T12:00:00'). In this way you will bypass any issues with timezones, daylight saving time and toJSON conversion.Meridithmeriel
@anchor—I wrote "The date and time is displayed…", not that it is stored in the Date object. Setting the time to noon is a terrible idea, it doesn't avoid timezone issues as there are a number of IANA representative locations with offsets of +12 and greater (e.g. Pacific/Kiritimati is +14). If you set the time to 12:00, how do you know the timestamp represents a date only and not date with a specific time? Dates can be sent in format you like, there is no compulsion to use toJSON or any other particular format.Caulfield
Z
18

I ran into the same problem and then remembered something wonky about a legacy project I was working on and how they handled this issue. I didn't understand it at the time and didn't really care until I ran into the problem myself

var date = '2014-01-02T00:00:00.000Z'
date = date.substring(0,10).split('-')
date = date[1] + '-' + date[2] + '-' + date[0]

new Date(date) #Thu Jan 02 2014 00:00:00 GMT-0600

For whatever reason passing the date in as "01-02-2014" sets the timezone to zero and ignores the user's timezone. This may be a fluke in the Date class but it existed some time ago and exists today. And it seems to work cross-browser. Try it for yourself.

This code is implemented in a global project where timezones matter a lot but the person looking at the date did not care about the exact moment it was introduced.

Zipnick answered 4/1, 2015 at 18:17 Comment(5)
I think it's intentional because the "Z" designates UTC which JS then converts, but given no time zone it can't convert it so it essentially assumes user's time zone. Would love to get some confirmation or better explanation though.Fluoric
The wonky behavior is due to the dashes. Chrome, Firefox, and IE11 all interpret 2014/5/31 and 2014/05/31 as Sat May 31 2014 00:00:00 GMT-0600 (Mountain Daylight Time)` (MDT being my current timezone). With dashes... all browsers interpret 2014-05-31 as Fri May 30 2014 18:00:00 GMT-0600 (Mountain Daylight Time). Oddly, with 2014-5-31, Chrome returns Saturday, Firefox returns Friday, and IE11 says the date is invalid. Seems like a date.replace('-','/') might do the trick.Eurystheus
@Eurystheus I tried this today as I was running into this issue - totally fixed it! Can this be an answer and upvoted for some to see?Hughmanick
Same here! this answer saved me! should be the accepted answer!Slippy
""01-02-2014" sets the timezone to zero". That format is not supported by ECMA-262, so parsing is implementation dependent and may not only do something you don't expect, results may also vary across platforms. If you want reliable results, manually parse timestamps (a library can help).Caulfield
S
18

Since it is really a formatting issue when displaying the date (e.g. displays in local time), I like to use the new(ish) Intl.DateTimeFormat object to perform the formatting as it is more explicit and provides more output options:

const dateOptions = { timeZone: 'UTC', month: 'long', day: 'numeric', year: 'numeric' };

const dateFormatter = new Intl.DateTimeFormat('en-US', dateOptions);
const dateAsFormattedString = dateFormatter.format(new Date('2019-06-01T00:00:00.000+00:00'));

console.log(dateAsFormattedString) // "June 1, 2019"

As shown, by setting the timeZone to 'UTC' it will not perform local conversions. As a bonus, it also allows you to create more polished outputs. You can read more about the Intl.DateTimeFormat object in Mozilla - Intl.DateTimeFormat.

The same functionality can be achieved without creating a new Intl.DateTimeFormat object. Simply pass the locale and date options directly into the toLocaleDateString() function.

const dateOptions = { timeZone: 'UTC', month: 'long', day: 'numeric', year: 'numeric' };
const myDate = new Date('2019-06-01T00:00:00.000+00:00');
myDate.toLocaleDateString('en-US', dateOptions); // "June 1, 2019"
Shuffleboard answered 30/3, 2020 at 13:37 Comment(2)
saved my day. This is a really clean way to propagate the time tags as they are with no timezone modifications. It solves also the issue with time switching due to daylight saving which would be integrated with current GMT/localtime timeoffset compensations.Equitation
The format produced by Intl.DateTimeFormagt is not necessarily consistent across platforms and can be influenced in surprising ways by factors like the host system language and regional settings. For reliable formatting, use a library where you can specify exactly the format you want.Caulfield
L
14

I found JavaScript Date Object and Time Zones | Fixing an "off by 1 day" bug on YouTube. This fixes/resets the offset for the local timezone. There's a great explanation to this problem in the video.

// date as YYYY-MM-DDT00:00:00Z

let dateFormat = new Date(date)

// Methods on Date Object will convert from UTC to users timezone
// Set minutes to current minutes (UTC) + User local time UTC offset

dateFormat.setMinutes(dateFormat.getMinutes() + dateFormat.getTimezoneOffset())

// Now we can use methods on the date obj without the timezone conversion

let dateStr = dateFormat.toDateString();
Lippmann answered 19/5, 2021 at 8:24 Comment(1)
This video is pure gold.Prosecutor
J
7

The Date object itself will contain timezone anyway, and the returned result is the effect of converting it to string in a default way. I.e. you cannot create a date object without timezone. But what you can do is mimic the behavior of Date object by creating your own one. This is, however, better to be handed over to libraries like moment.js.

Judo answered 9/7, 2013 at 10:25 Comment(1)
Unfortunatelly I have to produce Date object, not String.Hedgehog
L
6

Date in JavaScript is just keeping it simple inside, so the date-time data is stored in UTC Unix epoch (milliseconds or ms).

If you want to have a "fixed" time that doesn't change in whatever timezone you are on the earth, you can adjust the time in UTC to match your current local timezone and save it. And when retrieving it, in whatever your local timezone you are in, it will show the adjusted UTC time based on the one who saved it and then add the local timezone offset to get the "fixed" time.

To save date (in ms):

toUTC(datetime) {
  const myDate = (typeof datetime === 'number')
    ? new Date(datetime)
    : datetime;

  if (!myDate || (typeof myDate.getTime !== 'function')) {
    return 0;
  }

  const getUTC = myDate.getTime();
  const offset = myDate.getTimezoneOffset() * 60000; // It's in minutes so convert to ms
  return getUTC - offset; // UTC - OFFSET
}

To retrieve/show date (in ms):

fromUTC(datetime) {
  const myDate = (typeof datetime === 'number')
    ? new Date(datetime)
    : datetime;

  if (!myDate || (typeof myDate.getTime !== 'function')) {
    return 0;
  }

  const getUTC = myDate.getTime();
  const offset = myDate.getTimezoneOffset() * 60000; // It's in minutes so convert to ms
  return getUTC + offset; // UTC + OFFSET
}

Then you can:

const saveTime = new Date(toUTC(Date.parse("2005-07-08T00:00:00+0000")));
// SEND TO DB....

// FROM DB...
const showTime = new Date(fromUTC(saveTime));
Liquidize answered 23/3, 2020 at 10:43 Comment(0)
B
5

You can use this code

var stringDate = "2005-07-08T00:00:00+0000";
var dTimezone = new Date();
var offset = dTimezone.getTimezoneOffset() / 60;
var date = new Date(Date.parse(stringDate));
date.setHours(date.getHours() + offset);
Birthstone answered 10/9, 2019 at 15:58 Comment(2)
I don't believe this takes into account daylight savingsPeptide
It helps more if you supply an explanation why this is the preferred solution and explain how it works. We want to educate, not just provide code.Coaction
M
4

Here's a simple solution:

const handler1 = {
  construct(target, args) {
    let newDate = new target(...args);
    var tzDifference = newDate.getTimezoneOffset();
    return new target(newDate.getTime() + tzDifference * 60 * 1000);
  }
};

Date = new Proxy(Date, handler1);
Malnourished answered 7/3, 2018 at 16:11 Comment(1)
It helps more if you supply an explanation why this is the preferred solution and explain how it works. We want to educate, not just provide code.Coaction
F
4

The solution is almost the same as @wawka's, however it handles different timezones with plus and minus sings using Math.abs:

const date = new Date("2021-05-24T22:00:18.512Z")
const userTimezoneOffset = Math.abs(date.getTimezoneOffset() * 60000);
new Date(date.getTime() - userTimezoneOffset);
Fils answered 28/5, 2021 at 15:49 Comment(0)
P
4

I would personally prefer @wawka's answer, however, I also came up with a not so clean trick to solve this problem, which is simpler and can work if you are sure about the format of the strings you want to convert.

Look at the code snippet below:

var dateString = '2021-08-02T00:00:00'

var dateObj = new Date(dateString + 'Z')
console.log("No Timezone manipulation: ", dateObj)

var dateObjWithTZ = new Date(dateString)
console.log("Normal conversion: ", dateObjWithTZ)

This works in this case, because adding a Z to the end of the date time string will make JS treat this string to be a UTC date string, so it does not add timezone difference to it.

Prestidigitation answered 3/8, 2021 at 2:28 Comment(0)
S
4

The only time new Date() does the time zone conversion is when you pass the time zone reference. For e.g. in the following string "2022-08-16T10:54:12Z" the Z at the end is a reference to timezone. If the object is passing this variable at the end, you can use the following code to get a new date object without time conversion:

const dateStr = '2022-07-21T09:35:31.820Z';



const date = new Date(dateStr);
console.log(date); // 👉️ Thu Jul 21 2022 12:35:31 GMT+0300



const result = new Date(date.toISOString().slice(0, -1));
console.log(result); // 👉️ Thu Jul 21 2022 09:35:31 GMT+0300
Sava answered 16/8, 2022 at 9:23 Comment(1)
source: bobbyhadz.com/blog/javascript-create-date-without-timezoneMegmega
M
0

Timezone is a part of Javascript. I used the following code to adjust the date according to the timezone.

var dt = new Date("Fri Mar 11, 2022  4:03 PM");
dt.setTime(dt.getTime() - dt.getTimezoneOffset() *60 * 1000); //Adjust for Timezone
document.write(dt.toISOString());
 
Mortification answered 29/6, 2022 at 7:12 Comment(0)
A
-1

This is the solution that I came up with for this problem which works for me.


library used: momentjs with plain javascript Date class.

Step 1. Convert String date to moment object (PS: moment retains the original date and time as long as toDate() method is not called):

const dateMoment = moment("2005-07-08T11:22:33+0000");

Step 2. Extract hours and minutes values from the previously created moment object:

  const hours = dateMoment.hours();
  const mins = dateMoment.minutes();

Step 3. Convert moment to Date(PS: this will change the original date based on the timezone of your browser/machine, but don't worry and read step 4.):

  const dateObj = dateMoment.toDate();

Step 4. Manually set the hours and minutes extracted in Step 2.

  dateObj.setHours(hours);
  dateObj.setMinutes(mins);

Step 5. dateObj will now have show the original Date without any timezone difference. Even the Daylight time changes won't have any effect on the date object as we are manually setting the original hours and minutes.

Hope this helps.

Andersen answered 13/11, 2018 at 18:17 Comment(0)
L
-2

(new Date().toString()).replace(/ \w+-\d+ \(.*\)$/,"")

This will have output: Tue Jul 10 2018 19:07:11

(new Date("2005-07-08T11:22:33+0000").toString()).replace(/ \w+-\d+ \(.*\)$/,"")

This will have output: Fri Jul 08 2005 04:22:33

Note: The time returned will depend on your local timezone

Ligament answered 11/7, 2018 at 2:7 Comment(0)
U
-7

There are some inherent problems with date parsing that are unfortunately not addressed well by default.

-Human readable dates have implicit timezone in them
-There are many widely used date formats around the web that are ambiguous

To solve these problems easy and clean one would need a function like this:

>parse(whateverDateTimeString,expectedDatePattern,timezone)
"unix time in milliseconds"

I have searched for this, but found nothing like that!

So I created: https://github.com/zsoltszabo/timestamp-grabber

Enjoy!

Unfleshly answered 20/2, 2014 at 0:1 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.