696

Assigning a Date variable to another one will copy the reference to the same instance. This means that changing one will change the other.

How can I actually clone or copy a Date instance?

EternalObserver
  • 517
  • 7
  • 19

8 Answers8

1032

Use the Date object's getTime() method, which returns the number of milliseconds since 1 January 1970 00:00:00 UTC (epoch time):

var date = new Date();
var copiedDate = new Date(date.getTime());

In Safari 4, you can also write:

var date = new Date();
var copiedDate = new Date(date);

...but I'm not sure whether this works in other browsers. (It seems to work in IE8).

Flimm
  • 136,138
  • 45
  • 251
  • 267
Steve Harrison
  • 121,227
  • 16
  • 87
  • 72
  • 1
    Sometimes people also use JSON serialization and deserialization, but this one is better and much faster. +1 from me. – Robert Koritnik Jul 07 '09 at 07:26
  • 9
    JSON for this snippet? Sounds like these people should get their basics clear... Like mistaking jQuery for JavaScript DOM. – Boldewyn Jul 07 '09 at 07:57
  • 22
    Another way to write this nice solution would be to extend the Date prototype: `Date.prototype.clone = function() { return new Date(this.getTime()); };` Which you could then use as `copiedDate = date.clone();` – Ryan Apr 02 '10 at 08:24
  • 6
    The `copiedDate = new Date(date)` approach works in IE6+. In Firefox the two options are the same speed. – Ryan Dec 23 '10 at 19:06
  • 18
    `new Date(date)` same as `new Date(date.getTime())`, because JS will try to call `date.valueOf()` when it need a number, and `date.valueOf()` is same as `date.getTime()`, reference [Date.valueOf](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/valueOf?redirectlocale=en-US&redirectslug=JavaScript%2FReference%2FGlobal_Objects%2FDate%2FvalueOf) [Object.valueOf](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/valueOf?redirectlocale=en-US&redirectslug=JavaScript%2FReference%2FGlobal_Objects%2FObject%2FvalueOf) – Steely Wing Sep 27 '13 at 07:41
  • 1
    Instead of `date.getTime()`, you can do `+date` to cast it to a number with less characters. – Derek 朕會功夫 Jul 10 '14 at 23:29
  • 2
    What about dates that start before 1970 ? – user2555515 Aug 20 '14 at 23:45
  • 13
    Do not use `new Date(date)`, use `new Date(date.getTime()` or `new Date(date.valueOf)` instead since the first way can lead to differences between the dates in at least Firefox and IE (not Chrome). For example using `toISOString()` on the both dates in Firefox generates `"2015-04-21T04:56:42.000Z"` and `"2015-04-21T04:56:42.337Z"`. – crudh Apr 21 '15 at 04:57
  • 11
    `new Date(dateObject)` is **correct**. See description of [Date(value) constructor](http://www.ecma-international.org/ecma-262/6.0/#sec-date-value) where explicit rules for date object is defined. In the older specs the behavior was to call `ToNumber` on the argument if it wasn't a string so either way this should work in any browser that implements the behavior correctly. – Salman A Feb 22 '19 at 10:27
  • Please don't extend the Date prototype. Please. Picture what would happen if everyone extended prototypes. Nothing good. – doug65536 Nov 12 '21 at 20:55
  • @user2555515 Works for me in chrome: `new Date(new Date().setDate(-100000)).toString()` evaluates to `Tue Jan 16 1748 15:57:44 GMT-0517 (Eastern Standard Time)` – doug65536 Nov 12 '21 at 20:58
  • 1
    @SalmanA—careful. Noting that this answer was written in 2009, prior to ECMA 2011 (ed 5), `ToPrimitive(Date)` returned a string and in IE at least `new Date(Date)` returned a different date in some cases because it didn't correctly parse the string generated by its own *toString* method. Also, where *toString* produced a two digit year or year less than 100, it was shifted to 1900 + year. Hence the use of `new Date(+Date)` to ensure the time value was returned always. Though in 2021 likely it's safe to rely on *ToPrimitive*. :-) – RobG Dec 31 '21 at 09:11
175

This is the cleanest approach

let date = new Date() 
let copyOfDate = new Date(date.valueOf())

console.log(date);
console.log(copyOfDate);
mikemaccana
  • 110,530
  • 99
  • 389
  • 494
AnthonyWJones
  • 187,081
  • 35
  • 232
  • 306
  • 12
    The "valueOf()" method for "Date" objects produces the same result as its "getTime()" method (the number of milliseconds since epoch time). – Steve Harrison Jul 07 '09 at 07:32
  • 51
    @Steve: true, but getTime() could "looks" like it only returns the time and not include the date as well hence my reference to "cleanest". Frankly the Date type in Javascript is a bit of disaster zone, it should never have been mutable in the first place. – AnthonyWJones Jul 07 '09 at 08:34
  • 1
    @AnthonyWJones: Right, I see what you mean. – Steve Harrison Jul 07 '09 at 11:11
  • 4
    I agree that .valueOf() is more clear. Sometimes I forget and use .getMilliseconds() b/c to me that sounds like it means mean milliseconds since epoch time. – Tom Wayson Jan 10 '12 at 19:05
  • 2
    +1 to Steve Harrison: I was wondering if that was the case, thanks for the clarification. – Brian Lacy Jul 13 '12 at 17:25
67

Update for 2021

In one respect the notion of cloning a Date object sounds grander than it really is. As far as I can tell, there’s only one piece of instance data, and that is the stored time. What we’re really doing is making a new object with the same time.

Whatever may have been the case in the past, the new Date() constructor definitely accepts a Date object as a single argument:

const date = new Date();        // With or without an argument.
const date2 = new Date(date);   // Clone original date.

The Specification at https://tc39.es/ecma262/multipage/numbers-and-dates.html#sec-date at step 4(b) indicates that a Date object is definitely acceptable, and that this is equivalent to new Date(date.valueOf()), as suggested by some of the answers above. As I said, all you’re really doing is making a new Date object with the same time as the other.

You’ll also find that the documentation at https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/Date has been updated to include this.

Manngo
  • 14,066
  • 10
  • 88
  • 110
40

var orig = new Date();
var copy = new Date(+orig);

console.log(orig, copy);
OXiGEN
  • 2,041
  • 25
  • 19
Dave
  • 433
  • 4
  • 2
15

Simplified version:

Date.prototype.clone = function () {
    return new Date(this.getTime());
}
Zhaph - Ben Duguid
  • 26,785
  • 5
  • 80
  • 117
Berezh
  • 942
  • 9
  • 12
  • 98
    thou shalt not mess with built-in objects – Pawel Aug 05 '14 at 10:02
  • 4
    Thou shalt not mess with objects thou dost not owneth. You should make a new copy and call it SuperDate or something, withing your scope. Lots of hard to test for bugs are caused by object functionality changing unexpectedly. – Ray Foss Jan 28 '16 at 13:29
  • This would work, but for maintainability reasons, This approach would be considered as a code smell. I have written an approach that I usually use in my coding: https://actuts.wordpress.com/2017/01/10/cloning-javascript-date-instances/ – Allan Chua Jan 10 '17 at 15:33
  • 1
    Also I don't see this need for trying to add methods to built-ins in the first place. Study [functional programming](https://opensource.com/article/17/6/functional-javascript) and discover why a good old-fashioned function is actually much more powerful than methods on the object itself. It's also shorter: `const cloneDate = d => new Date(d.getTime())`. – Stijn de Witt Sep 14 '17 at 14:14
10

I found out that this simple assignmnent also works:

dateOriginal = new Date();
cloneDate = new Date(dateOriginal);

But I don't know how "safe" it is. Successfully tested in IE7 and Chrome 19.

L K
  • 109
  • 1
  • 2
  • 10
    Do not use `new Date(date)`, use `new Date(date.getTime()` or `new Date(date.valueOf)` instead since the first way can lead to differences between the dates in at least Firefox and IE (not Chrome). For example using `toISOString()` on the both dates in Firefox generates `"2015-04-21T04:56:42.000Z"` and `"2015-04-21T04:56:42.337Z"`. – crudh Apr 21 '15 at 04:58
  • 5
    That may have been true on old versions of firefox, but on the latest version, `new Date(date)` works fine. Try it: `let date = '2015-04-21T04:56:42.337Z'; new Date(date).toISOString()`. Result is the same as input: `"2015-04-21T04:56:42.337Z"` – TetraDev Sep 11 '20 at 18:59
  • 3
    To anyone reading this nowadays, this **works**, please ignore old comments stating that `.getTime` must be used. – Wiktor Zychla Dec 01 '21 at 13:57
1
function cloneMyDate(oldDate){
  var newDate = new Date(this.oldDate);
}

I was passing oldDate to function and generating newDate from this.oldDate, but it was changing this.oldDate also.So i used the above solution and it worked.

Tejas Pawar
  • 371
  • 3
  • 2
-2

For chrome it works:

//Thu Nov 03 2022 11:43:00

**const date = new Date(2022,10,03,11,43,0);

const date2 = new Date(date);**

now changing date2 will have no impact on the date

Safwan
  • 7
  • 3
  • Please learn how to [use markdown](https://stackoverflow.com/editing-help) and adjust your answer accordingly. – Aaron Meese Nov 06 '22 at 18:12
  • The formatting isn’t the only problem with this answer. It contains something that has already been covered by all previous answers. – Sebastian Simon Nov 07 '22 at 00:29