11

For the following code:

var d = new Date("2013-07-01");
console.log(d.toDateString());

It outputs Sun Jun 30 2013, which is one day less of what was input. What happened to the object? What date is actually stored?

Matt Johnson-Pint
  • 230,703
  • 74
  • 448
  • 575
whileone
  • 2,495
  • 3
  • 21
  • 30

4 Answers4

10

The date is parsed as UTC date, but the toDateString() outputs what that time is in the local timezone.

Try this instead

var d = new Date(2013, 6, 1); //6 instead of 7 because the mont argument is  zero-based
console.log(d.toDateString());

What date is actually stored?

2013-07-01 00:00:00 UTC

Esailija
  • 138,174
  • 23
  • 272
  • 326
  • 1
    Your last comment destroys your answer!—As you reasonably change the code to parse in the local time zone (and print it in the local time zone), the actually stored date can _not_ be determined without knowing the local time zone! – Robert Siemer Feb 11 '20 at 14:25
8

Parsing a Date from a string can yield different results depending on what browser/runtime you are using. There is a chart here that lists some of the browsers and what they support.

But in general, a string like "2013-07-01" is treated as if it were at midnight in UTC.

If you wanted to parse it in local time, you could use "2013/07/01". But that's a bit strange. You might be tempted to use "07/01/2013", but that might be interpreted as either Jan 7th or July 1st. Any of these are still implementation specific.

If you want a general purpose, "works everywhere" solution, you have a few different options:

Option 1

Don't parse it. Use the constructor that accept integers.

var d = new Date(2013,6,1);    // watch out for the zero-based month
console.log(d.toDateString());

// output:  "Mon Jul 01 2013"

With this code, the actual UTC time stored is going to vary depending on your own time zone. But since .toDateString() also takes that time into account, then you should be ok.

Option 2

Parse it as UTC, and display it as UTC/GMT:

var d = new Date("2013-07-01");
console.log(d.toUTCString());

// output:  "Mon, 01 Jul 2013 00:00:00 GMT"

But this output probably has more than you were looking for, and it may still look different in various browsers.

Option 3

Use the moment.js library, where you can control the formatting exactly however you desire.

var m = moment("2013-07-01", "YYYY-MM-DD");  // explicit input format
console.log(m.format("ddd MMM DD YYYY"));    // explicit output format

// output:  "Mon Jul 01 2013"

IMHO, this is the best solution. But it does require you use a library.

Matt Johnson-Pint
  • 230,703
  • 74
  • 448
  • 575
  • 4
    Nowadays there is an improved “option 2”: `d.toLocaleString('en-US', {timeZone: "UTC", day: "2-digit", month: "short", year: "numeric", weekday: "short"})`. The exact output is implementation dependent, but I don’t see the problem: here it is `"Mon, Jul 01, 2013"`. If you don’t like the commas, well in Ireland they don’t like them either: use `en-IE` as locale. – Robert Siemer Feb 12 '20 at 03:08
  • @RobertSiemer - Good point. Feel free to add your own answer with this. – Matt Johnson-Pint Feb 12 '20 at 16:12
4

Option 4

This approach works pretty good and doesn't require 3rd party libraries.

    var parts ='2013-07-01'.split('-');
    var mydate = new Date(Date.UTC(parts[0],parts[1]-1,parts[2])); //please put attention to the month
Roman Podlinov
  • 23,806
  • 7
  • 41
  • 60
  • Suggesting the conversion of a date with unknown time zone to a date with a specific time zone is only reasonable if both input and output is discussed.—Before your edit, the Date object was only reasonable if used with the local time zone, after your edit it is only reasonable if used with UTC. And @1_bug was wrongly reading your local time object as UTC. – Robert Siemer Feb 12 '20 at 04:32
0

You can simply append your timezone before parsing as well.

var d = new Date("2013-07-01" + "T00:00:00.000-05:00");
console.log(d.toDateString()); 
ycr
  • 12,828
  • 2
  • 25
  • 45