69

The date returned by date picker is off by one day. Is it a problem in my code or is it a bug?

The date sent to date_picker is 2012-03-21. The date returned by datepicker is Tue Mar 20 2012.

    var end_date = end_calendar.getFormatedDate("%Y-%m-%d");
    end_date = $.datepicker.formatDate('D M dd yy', new Date(end_date));

I've struggled with this issue also and discovered a salient point on the issue so I thought I'd add a code snippet that displays the problem.

The following code only:

  1. sets the valueAsDate property
  2. reads the valueAsDate property

But on my systems it always shows wrong date when I read the property.

function initDate(){
document.querySelector("#mainDate").valueAsDate = new Date();
}
function showDate(){
    alert(document.querySelector("#mainDate").valueAsDate);
  }
<body onload="initDate()">
    <h2>Reading the property we set gets different value</h2>
    <p> Notice that the code only:
    <ul><li>sets the value using valueAsDate property</li>
    <li>reads the same property valueAsDate </li>
    </ul>
    <input type="date" id="mainDate">
    <button onclick="showDate()">show date</button>
  </body>

Here's a snapshot of the value I get that shows that I always get a date that is one day less than the value that the control displays. Value is one day less than displayed in control

raddevus
  • 8,142
  • 7
  • 66
  • 87
user823527
  • 3,644
  • 17
  • 66
  • 110
  • You sure this is datepicker related at all? `document.write(new Date('2012-03-21'))` prints `Tue Mar 20 2012 20:00:00 GMT-0400 (Eastern Daylight Time)` for me. Leap year bug? – Wesley Murch Mar 01 '12 at 01:32
  • Something to do with the formatting too, check this out: http://jsfiddle.net/fkSC5/ Passing `2012-03-21` and `2012/03/21` to `Date()` gives results that are 4 hours apart. – Wesley Murch Mar 01 '12 at 01:38
  • That's true. new Date('...') is off by one day. – user823527 Mar 01 '12 at 01:57
  • This must be a bug with Date(). 2012/03/21 seems more right than 2012-03-21. – user823527 Mar 01 '12 at 02:14
  • 1
    Which highlights that you should never trust the built-in date string parser. They differ between implementations, so always parse the input and create the date manually. – RobG Mar 01 '12 at 02:37
  • 8
    This isn't a bug. When you provide the date in standard UTC format, Date assumes that you are providing a UTC time, which is independent of your local time. The reason you're off by day is because UTC time is for a timezone that is ahead of yours. (Since you didn't also provide a time, 0:0:0 was assumed.) Supplying a date in a format other than UTC indicates use of a local timezone. I happened across this problem in another context, with YAML interpreting my UTC format date off by a day. – Joe Lapp Feb 18 '16 at 20:42

15 Answers15

37

It is not the datepicker,

console.log(new Date('2012-03-21')); //prints Tue Mar 20 2012 20:00:00 GMT-0400 (Eastern Daylight Time)

The Javascript Date object can accept one of the following syntax as below,

  1. new Date()
  2. new Date(milliseconds)
  3. new Date(dateString)
  4. new Date(year, month, day [, hour, minute, second, millisecond ])

So in your case it is going to call the dateString and parse. So try appending the time as below,

new Date ('2012-03-21T00:00:00') //should return you Wed Mar 21 2012

DEMO

or Better to use as below,

new Date (2012, 2, 21). 

year - Integer value representing the year. For compatibility (in order to avoid the Y2K problem), you should always specify the year in full; use 1998, rather than 98.

month - Integer value representing the month, beginning with 0 for January to 11 for December.

day - Integer value representing the day of the month (1-31).

Selvakumar Arumugam
  • 79,297
  • 15
  • 120
  • 134
  • 1
    Can you shed any light on my comments above? Why does `new Date('2012-03-21)` return a date that has `20:00:00` form time and is the wrong day, as you state in the first line of your post? – Wesley Murch Mar 01 '12 at 01:44
  • 2
    @Madmartigan I am trying to understand the same myself. It seems like new Date('2012-03-21T00:00:00') yields same result as new Date('2012/03/21'). However I have no explanation if using / defaults time to 00:00:00 – Selvakumar Arumugam Mar 01 '12 at 01:52
  • 2
    `new Date ('2012-03-21T00:00:00')` returns `Tue Mar 20 2012 20:00:00 GMT-0400 (EDT)` – Brian Risk Jan 19 '16 at 19:18
  • 1
    @SelvakumarArumugam You should update your answer. The line `new Date ('2012-03-21T00:00:00')` does **NOT** produce Mar 21 2012. It will produce Mar 20 2012. – AperioOculus Dec 21 '16 at 18:05
  • flawed. is it possible to pull request against this with a fix? wasted a couple of hours with this nonsense. – zero_cool Apr 24 '18 at 20:05
32

Seems to be a bug. If the string sent to Date() is formatted as 2012/03/21 instead of 2012-03-21. The date seems right.

Paolo
  • 20,112
  • 21
  • 72
  • 113
user823527
  • 3,644
  • 17
  • 66
  • 110
26

This is not a bug, but definitely confusing.

Most of the answers on this page are confused and contain some mis-information.

The real issue is in how the javascript Date object parses date strings.

The best answer I have found is this stack-O answer. Check out its' excellent write-up.

Below is a very pertinent comment from the answer mentioned above. (credit: @Mizstik)

All of this is due to the behavior of the underlying Date.parse() trying to follow ISO 8601. When the date string follows the yyyy-mm-dd format, it's assumed to be ISO 8601 with implicit UTC 00:00. When the string deviates from the format (e.g. mm-dd-yyyy or slash instead of hyphen), it falls back to the looser parser according to RFC 2822 which uses local time when the timezone is absent. Admittedly, this will all be quite arcane to an average person.

David
  • 13,133
  • 1
  • 30
  • 39
16

You can add the difference to the date which will essentially ignore whatever the timezone is.

d.setTime( d.getTime() + d.getTimezoneOffset()*60*1000 );
jeremyforan
  • 1,417
  • 18
  • 25
  • 2
    thanks your answer help here http://stackoverflow.com/questions/32469269/javascript-date-give-wrong-date-off-by-one-hour just i use minus `-` and i use the current time to get time zone offset like this `d.setTime( d.getTime() - new Date().getTimezoneOffset()*60*1000 );` – Hayi Sep 09 '15 at 20:45
13

I don't know why this works but what I've found is whether you use forward slashes or dashes affects the answer. Take a look.

new Date ('2012/03/21'); // returns: "Wed Mar 21 2012 00:00:00 GMT-0500 (CDT)"
new Date ('2012-03-21'); // returns: "Tue Mar 20 2012 19:00:00 GMT-0500 (CDT)" WHA!

So to fix my issue I did a simple regex on my input date to always replace the first three dashes with forward slashes.

var strInputValue = control.value, // <-- get my date string
    dteCurrent;

strInputValue = strInputValue.replace(/-/, '/')  // replace 1st "-" with "/"
                             .replace(/-/, '/'); // replace 2nd "-" with "/"

dteCurrent = new Date(strInputValue);

I did a very quick google search for why this would happen and no answer. But this should fix your issue. All you have to do is replace the dashes with forward slashes before you pass them to where you want them.

Edit: sorry I didn't notice the already accepted answer before posting, please disregard this answer.

Michael
  • 410
  • 4
  • 9
  • One of the question's comment explains correctly why this is the case. The format difference seems to dictate Date to assume some values as zero in UTC which is not the case when you use forward slashes – fkl Nov 15 '16 at 07:46
13

It is happening due to difference in timezone with date format- yyyy-mm-dd

new Date ('2015/07/10'); // returns: "Fri Jul 10 2015 00:00:00 GMT-0700 (Pacific Daylight Time)"

new Date ('2012-07-10'); // returns: "Thu Jul 09 2015 17:00:00 GMT-0700 (Pacific Daylight Time)" 

yyyy/mm/dd - is not considering timezone while calculating local time.But
yyyy-mm-dd - is considering timezeone while calculating local time in java script date function.
This can be reproducible when client(browser) and server time zones are different and having timezone/date difference by 1 day.

You can try this on your machine by changing time to different time zones where time gap b/w should be >=12 hours.

user158
  • 12,852
  • 7
  • 62
  • 94
Venu Morigadi
  • 589
  • 6
  • 4
4

After trying many solutions the following code worked for me taken from (https://stackoverflow.com/a/14006555/1736785)

   function createDateAsUTC(date) {
    return new Date(Date.UTC(date.getFullYear(), date.getMonth(), date.getDate(), date.getHours(), date.getMinutes(), date.getSeconds()));
}
Community
  • 1
  • 1
cbyte
  • 681
  • 7
  • 12
3

To avoid getting one day off, I replaced the - with / using .replace() on the creation of the date variable like this

var startDate = new Date(data[3].replace(/-/g, '\/'));
cdena
  • 31
  • 2
1

I don't have the reputation to comment, but Venu M gave me good insight. My project is having the same issue where depending on the syntax of my date input, the date returns as input or off one day. Expanding out and looking at the full date format, my different input date formats are returning in either UTC or my local time zone, depending on the syntax. I am using Moment JS to parse my dates then returning a date object for validation with Breeze. I have either an input modal or a table in which to edit, so now I need to make sure both are parsed and validated identically. I suggest verifying your date object is being created the same way regardless of its input syntax or input location.

torple
  • 27
  • 1
  • 7
1
var myDate = $.datepicker.parseDate("yy-mm-dd", "2013-10-21");
..//do whatever with myDate now
Andrei
  • 42,814
  • 35
  • 154
  • 218
Toskan
  • 13,911
  • 14
  • 95
  • 185
0

After experiencing the same issue and landing on this page, it turned out in my case it was caused by invalid labeling of the days. I started the week on Monday, instead of Sunday. I hope this helps somebody.

digifrog
  • 77
  • 12
0

In my case I was getting this issue because the time zone of my country is UTC+01:00 but in my DatePicker (I'm using MUI with react) was GMT+0200

hakima maarouf
  • 1,010
  • 1
  • 9
  • 26
0

check your spelling of .getFormatedDate and change it to .getFormattedDate it's a trivial change but tweak it and see if any fixture results.

scud bomb
  • 415
  • 3
  • 19
-1

As said Javascript January equals 0 so this would work for datepicker or input type date.

 end_date = end_date.split('-');
 end_date = new Date(end_date[0],Number(end_date[1])-1,end_date[2]);
lisandro
  • 454
  • 4
  • 12
-3

Try out this,

ranges": {
    'Today': [moment().hours(0).minutes(0).seconds(0).milliseconds(0), moment().hours(23).minutes(59).seconds(59).milliseconds(999)],
    'Yesterday': [moment().subtract(1, 'days').hours(0).minutes(0).seconds(0).milliseconds(0), moment().subtract(1, 'days').hours(23).minutes(59).seconds(59).milliseconds(999)],
    'Last 7 Days': [moment().subtract(6, 'days').hours(0).minutes(0).seconds(0).milliseconds(0), moment().hours(23).minutes(59).seconds(59).milliseconds(999)],
    'Last 30 Days': [moment().subtract(29, 'days').hours(0).minutes(0).seconds(0).milliseconds(0), moment().hours(23).minutes(59).seconds(59).milliseconds(999)],
    'This Month': [moment().startOf('month').hours(0).minutes(0).seconds(0).milliseconds(0), moment().endOf('month').hours(23).minutes(59).seconds(59).milliseconds(999)],
    'Last Month': [moment().subtract(1, 'month').startOf('month').hours(0).minutes(0).seconds(0).milliseconds(0), moment().subtract(1, 'month').endOf('month').hours(23).minutes(59).seconds(59).milliseconds(999)]
},

ranges": { 'Today': [moment().hours(0).minutes(0).seconds(0).milliseconds(0), moment().hours(23).minutes(59).seconds(59).milliseconds(999)], 'Yesterday': [moment().subtract(1, 'days').hours(0).minutes(0).seconds(0).milliseconds(0), moment().subtract(1, 'days').hours(23).minutes(59).seconds(59).milliseconds(999)], 'Last 7 Days': [moment().subtract(6, 'days').hours(0).minutes(0).seconds(0).milliseconds(0), moment().hours(23).minutes(59).seconds(59).milliseconds(999)], 'Last 30 Days': [moment().subtract(29, 'days').hours(0).minutes(0).seconds(0).milliseconds(0), moment().hours(23).minutes(59).seconds(59).milliseconds(999)], 'This Month': [moment().startOf('month').hours(0).minutes(0).seconds(0).milliseconds(0), moment().endOf('month').hours(23).minutes(59).seconds(59).milliseconds(999)], 'Last Month': [moment().subtract(1, 'month').startOf('month').hours(0).minutes(0).seconds(0).milliseconds(0), moment().subtract(1, 'month').endOf('month').hours(23).minutes(59).seconds(59).milliseconds(999)] },

  • 3
    This may provide a solution to the problem, but with no description it will not be very helpful – Cleptus Feb 28 '19 at 12:37