0

I have some trouble with date manipulation in Javascript.

I have one variable which is firstDay, that's date that I'm operating on.

To firstDay I add X days from one variable, and Y days from another:

var from_date = new Date(firstDay); // firstDay is a string with date: 2012/07/28
var to_date = new Date(firstDay);

var X = 1;
var Y = 5;

from_date.setDate(from_date.getDate() + X);
to_date.setDate(to_date.getDate() + Y);

So from_date now contains date 29.07.2012 and to_date is 02.08.2012. I don't know why date changes properly, but months stay the same.

Where I make something wrong?

Torsten Walter
  • 5,614
  • 23
  • 26
PiKey
  • 628
  • 5
  • 24
  • I guess the edit of Torsten makes the question not a question anymore. :) if `from_date` now contains 29.07.2012 and `to_date` is 02.08.2012, clearly the months are not staying the same, and everything is how expected: `from_date` has 1 day more than the original date, and `to_date` has 5 days more. – ZER0 Jul 28 '12 at 11:50
  • @PiKey which Browser were you testing in? The original question contained `02.06.2012` Which was clearly wrong because the month was smaller than `from_date`. It might be that some browsers don't do the month augmentation. – Torsten Walter Jul 28 '12 at 12:11
  • No browser I know of has such bugs. – Pointy Jul 28 '12 at 12:41
  • Sorry I just messed up dates :) Problem's solved arleady, thanks for all annotations – PiKey Jul 28 '12 at 12:44
  • Using the built–in parser for a format like "2012/07/28" is a bad idea as it is not a format supported by ECMA-262. See [*Why does Date.parse give incorrect results?*](https://stackoverflow.com/questions/2587345/why-does-date-parse-give-incorrect-results) – RobG Aug 23 '19 at 01:23

2 Answers2

1

Copy & pasted your code, it worked as expected: http://jsfiddle.net/kDYdW/4/

The only differences is firstDay, so I assume you have problem with that maybe.

You also say that "months stay the same" but you reported to have July in from_date and June in to_date (29.07.2012 and 02.06.2012).

Update: added the proper revision of the jsfiddle

ZER0
  • 24,846
  • 5
  • 51
  • 54
  • I've just created date object using 3 variables (day, month, year), like in yours example and it's worked for me. Thanks for help – PiKey Jul 28 '12 at 12:42
1

setDate(d) just sets the day of month, for the given month (while e.g. setMonth(m) just changes the month).

You might want to use setTime(t) which sets the complete timestamp, assuming X and Y are days:

from_date.setTime(from_date.getTime() + (X * 24 * 60 * 60 * 1000));
to_date.setTime(to_date.getTime() + (Y * 24 * 60 * 60 * 1000));
jCoder
  • 2,289
  • 23
  • 22
  • 1
    *"If the parameter you specify is outside of the expected range, setDate attempts to update the date information in the Date object accordingly. For example, if you use 0 for dayValue, the date will be set to the last day of the previous month."* See: https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Date/setDate – ZER0 Jul 28 '12 at 11:38
  • While this is true, I read the original question as PiKey wants to add days to a given date and wants the month to turn over correctly. Therefore `setDate()` is the wrong method and `setTime()` should be used which my answer suggests. – jCoder Jul 28 '12 at 11:43
  • If PiKey wants the month to turn over correctly after adding days, `setDate` is the correct method, the documentation is clear about that: `var date = new Date(); date.setDate(date.getDate() + 5);` and you will see the month turned over properly. Or just click on the jsfiddle link I posted. – ZER0 Jul 28 '12 at 11:48
  • The reference docs you linked also suggest that the parameter for `setDate()` shoud be in the range of 1 to 31, and it tries to fix any out-of-range values to give you the excpected result, so I thought that using `setTime()` is more straight-forward as it "clearly" sets the value. Anyway, both methods seem to work, but now the original question gets a little unclear ;) – jCoder Jul 28 '12 at 11:58
  • `setDate` is made for this very purpose: the range is an integer between 1 and 31, but clearly we have months where 31 is out of rage, so what's happen? The method will modify the date accordingly. So it's not an "hack" or something else, it's the proper and documented behavior. Your approach is less readable in my opinion, doesn't take in account leap seconds for instance, and so on. I personally considered more "clear" the `setDate` method – that was always used in that way. – ZER0 Jul 28 '12 at 12:03
  • I think that implementing date calculations correctly is one of the hardest things in programming and I'm glad that every major language provides a ready-to-use implementation. Btw. I tested `setDate(getDate()+5)` for `new Date(2012, 5, 28)` and it doesn't seem to take the leap second on `2012/06/30` in account, too, even if I'm not sure it it should have. Too bad that JavaScript doesn't provide a `addDays()` method itself. – jCoder Jul 28 '12 at 12:18
  • Not sure how that test will test the leap second, however I agree with you: implementing date calculations is hard, that's why should be demand to native implementation. I mentioned leap second to make an example, but I said "so on": your calculation doesn't take in account daylight saving time for instance. Not in all countries we have days of 24 hours during the year. Doing similar calculation manually is too error prone, delegate to native methods it's safer in most of the cases. – ZER0 Jul 28 '12 at 13:44
  • Also, an possible `addDays` method would just do what `setDate` does, internally will call the operator `MakeDay` and `MakeDate` (see ES specs), the only differences for the developer is not calling explicitly `getDate`, so you will have: `date.addDays(5)` instead of `date.setDate(date.getDate() + 5)`, but the internal behavior will be similar. If you want, you could have: `Date.prototype.addDays = function addDays(days) { this.setDate(this.getDate() + days) }` (if you have no issues in modifiying the built-in prototypes) – ZER0 Jul 28 '12 at 13:48