Reputation: 1191
i am writing a jquery lib and i need to implement Datetime functions. i need to create a .Date() function which return a new Date object.
How to pass arguments of my .Date(args) function to Date object constructor so to create a new date object?
i tried something like this, me is the plugin namespace, me=$.jqGUI.
//.Date(Value)
/* Return a date object.
* ReturnValue = Date(Value)
*/
me.Date = function(Value){
//pass arguments to Date constructor
var sDate = Date.prototype.constructor.apply(null, arguments);
console.log(sDate);
//create a date object d
var d = new Date(sDate);
//validate date object
if(d.toDateString()=="Invalid Date"){
throw new Error("$.jqGUI.Date: Invalid Date");
}
else{
return d;
}
};
here i pass to Date.prototype.constructor the arguments but i get in any case the current date. if arguments is a date string it is ignored. why?
Upvotes: 4
Views: 8827
Reputation: 37700
A few notes:
eval
, it is dangerous.bind
isn't always available and as pointed out, shims don't work the same.Date.UTC
also takes a variable argument list and returns a scalar that can be used by the Date
constructor.apply
only requires an array like object, not an actual array, so arguments
is good enough.So here is my preferred, browser safe, totally variable method. Notice how it handles no arguments with Date.now()
. Passing a null
is not the same as no arguments so that is allowed to perform the same.
me.Date = function(value){
if (arguments.length < 1) value = Date.now();
else if (arguments.length > 1) value = Date.UTC.apply(null, arguments);
var d = new Date(value);
// ...
}
Upvotes: 0
Reputation: 3568
var args = Array.prototype.concat.apply([null], arguments);
return new (Function.prototype.bind.apply(Date, args));
If your target browser doesn't support ECMAScript 5 Function.prototype.bind, the code won't work. It is not very likely though, see compatibilty table.
Upvotes: 7
Reputation: 11
The accepted answer is not ideal. I can only hope that anyone reading this thread will investigate further. Using 'eval' has a host of side-affects that I don't think you would want in a util-lib.
Here's a rough take at what you could do:
function dateShimmer() {
if(arguments.length === 1){
return new Date(arguments[0]);
}
else if(arguments.length > 1){
return dateArgumentShimmer.apply(null, arguments);
}
return new Date();
}
function dateArgumentShimmer(a1, a2, a3, a4, a5, a6, a7){
//Direct invocation is faster than apply/call
switch(arguments.length){
case 2: return new Date(a1, a2);
case 3: return new Date(a1, a2, a3);
case 4: return new Date(a1, a2, a3, a4);
case 5: return new Date(a1, a2, a3, a4, a5);
case 6: return new Date(a1, a2, a3, a4, a5, a6);
case 7: return new Date(a1, a2, a3, a4, a5, a6, a7);
}
};
Jsfiddle here: http://jsfiddle.net/y7Zmr/
Upvotes: -1
Reputation: 664195
Date.prototype.constructor
is quite useless, just use Date
- the function is the constructor.
.apply(null, ...
You will need to apply a constructor on a newly created object of that type, not on null
. See Use of .apply() with 'new' operator. Is this possible?
However, it is impossible to apply the real Date
constructor (the function used for new
), because EcmaScript specifies that when Date
is called as a function it must return the current UTC time.
Anyway, you should not need this. Instead of receiving a bunch of arguments (of variable size), you should just specify a parameter to be a Date
object. The user of the function can build that how he wants.
Your odd-looking function seems to do exactly the same as the Date
constructor. Throw it away, and let the user apply Date
himself - he knows which format he wants.
Also, you should not use if(d.toDateString()=="Invalid Date")
, this is not standardisized but implementation-dependent. To check for a valid Date
object, just use isNaN
- the internal representation (valueof the Date
instance) of unparsable dates is NaN
.
Suggestion:
me.date = function(d) {
/* gets: a Date object or something that can be transformed to a Date
returns: a valid Date object, else throws an Error */
d = new Date(d); // works also for Date instances, uncouples them
// else creates new one from string or number
if (isNaN(d))
throw new Error("$.jqGUI.Date: Invalid Date");
return d;
};
Upvotes: 2
Reputation: 1191
ok for me the following was worked
var args = [];
for(var i = 0; i < arguments.length; i++)
args.push("arguments[" + i + "]");
var d = eval("new Date(" + args.join(",") + ")");
Upvotes: -2