Bootstrap Datepicker defaults to 1900's when entered with 2 digit year - datepicker

I am using a datepicker in a modal window in my Bootstrap application. I am using the original Datepicker from Stefan Petre. I built it where it works in a desktop and mobile using a mouse and it works fine.
Recently I had a user request to allow it to also work with a keyboard. I removed the readonly property to allow the user to enter a date in the input field. The date-format is set to 'mm/dd/yyyy'.
When I enter a date like today for example like this "12/11/13" then it will default to 1913. This isn't a huge deal as I could just train the users to use 4 digits, but I would rather just have it default to this century.
Note: This only seems to happen for the date-format with a 4 digit year. This also seems to happen in the same manner in the newer forks of Stefan's code.
Note: I am using Bootstrap 2.0.4. I am testing with Firefox.
Here is what it looks like:

In JavaScript, set the datepicker's assumeNearbyYear attribute to true, like this:
$("#dp").datepicker({
assumeNearbyYear: true
});

This happens because the Bootstrap datepicker is using JavaScript Date objects. When you create a new Date object and pass in a two digit year it will output 1900+year (see Why does Javascript evaluate a 2-digit year of 00 as 1900 instead of 2000?)
You could try to tweak the datepicker source code, but that might be too complicated.
From what I can see on http://www.eyecon.ro/bootstrap-datepicker/ there is no option to set a range for the selectable dates, but you could change the format to use two digit years.
On your screenshot I can see, that you are using the datepicker for "Arrival Date" which I assume is in the future. On the website there is an example on how to disable dates in the past.
I hope that helps.
UPDATE
I have written an event handler for your problem which should do the trick.
Javascript on http://jsfiddle.net/pCYbd/1/
$("#dp").datepicker();
$("#dp").on("keyup", function(e) {
var date, day, month, newYear, value, year;
value = e.target.value;
if (value.search(/(.*)\/(.*)\/(.*)/) !== -1) {
date = e.target.value.split("/");
month = date[0];
day = date[1];
year = date[2];
if (year === "") {
year = "0";
}
if (year.length < 4) {
newYear = String(2000 + parseInt(year));
$(this).datepicker("setValue", "" + month + "/" + day + "/" + newYear);
if (year === "0") {
year = "";
}
return $(this).val("" + month + "/" + day + "/" + year);
}
}
});
CoffeeScript on http://jsfiddle.net/pCYbd/2/
$("#dp").datepicker()
$("#dp").on "keyup", (e) ->
value = e.target.value
if value.search(/(.*)\/(.*)\/(.*)/) != -1
date = value.split("/")
month = date[0]
day = date[1]
year = date[2]
year = "0" if year == ""
if year.length < 4
newYear = String(2000 + parseInt(year))
$(#).datepicker("setValue", "#{month}/#{day}/#{newYear}")
year = "" if year == "0"
$(#).val("#{month}/#{day}/#{year}")
My JavaScript skills are not the best, but this should work.

Updating bootstrap-datepicker.js as shown in this post solved it for me https://github.com/eternicode/bootstrap-datepicker/pull/1461/commits/2ea16adad27cbc4d4dfa20b924addfb480e5b036
yyyy: function(d,v){
if (format.parts.indexOf('yyyy') > -1 && v < 1000) v = 2000+v; // this line ***
return d.setUTCFullYear(v);
},

I'm using bootstrap-datepicker v1.5.1 and if you look around line 1741 where it does the year mapping, you will notice this:
yyyy: function (d, v) {
return d.setUTCFullYear(v);
},
yy: function (d, v) {
return d.setUTCFullYear(2000 + v);
},
When you specify that the control uses a four year date "yyyy", it will only do the return d.setUTCFullYear(v);, which will get you the previous century that JavaScript gives you. When you specify that it use the two year date "yy", it will do the correct 2000+ that you need for the current century.
So if you want the correct two year date to be 2016, 2017, etc., you need to set your datepicker to use the "yy" like so:
$('#tbPurchaseDate').datepicker({
format: 'mm/dd/yy',
autoclose: true,
todayBtn: 'linked',
todayHighlight: true,
orientation: 'bottom auto'
});
Or you can change the "yyyy" setting in the bootstrap-datepicker.js to match the "yy" version, but then you'd have to remember to do that every time you update the datepicker js file via nuget. It's much easier to just change your format setting.
Of course, if you want the full 4 digit year to display in the control, then you might want to try one of the elaborate fixes listed here or just set the "yyyy" to what the "yy" is in the js file.
Or just update your code to the latest version (1.6.4 right now) and "yyyy" and "yy" are the same and you use assumeNearbyYear: true as noted in another answer here.

For me, the best solution was to customize parseDate function in bootstrap-datepicker.js file directly. Inside a function, there is variable setters_map with yyyy property which I modified a bit. Here is my solution:
yyyy: function(d,v) {
if (v.toString().length == 2 && v <= 30) {
v = 2000 + parseInt(v);
}
return d.setUTCFullYear(v);
},
In my case it was needed to convert only years that are less or equals 30.

In the update function of bootstrap-datepicker.js I added this block of code:
var str = this.element.prop('value');
var defaulted = false;
if (str.lastIndexOf("/") >= 0 && (str.match(/\//g) || []).length == 2)
{
var yr = str.substring(str.lastIndexOf("/") + 1);
if (yr.length <= 2)
defaulted = true;
}
if (this.date.getFullYear() < 2000 && defaulted) {
this.date.setFullYear(this.date.getFullYear() + 100);
}
right before the viewdate is set on this line:
this.viewDate = new Date(this.date.getFullYear(), this.date.getMonth(), 1, 0, 0, 0, 0);

It will work 100% if you update below two line in UTCDate() of bootstrap-datepicker.js core file:
function UTCDate(){
/* Date defaulted date from 2000 if entered date year less than 4 degit*/
if(arguments!=null && arguments[0].toString().length<4)
arguments[0] = 2000 + arguments[0];
return new Date(Date.UTC.apply(Date, arguments));
}

Related

When I filter by date using .setHours to remove the time, the time is then lost in the filter [duplicate]

Can someone suggest a way to compare the values of two dates greater than, less than, and not in the past using JavaScript? The values will be coming from text boxes.
The Date object will do what you want - construct one for each date, then compare them using the >, <, <= or >=.
The ==, !=, ===, and !== operators require you to use date.getTime() as in
var d1 = new Date();
var d2 = new Date(d1);
var same = d1.getTime() === d2.getTime();
var notSame = d1.getTime() !== d2.getTime();
to be clear just checking for equality directly with the date objects won't work
var d1 = new Date();
var d2 = new Date(d1);
console.log(d1 == d2); // prints false (wrong!)
console.log(d1 === d2); // prints false (wrong!)
console.log(d1 != d2); // prints true (wrong!)
console.log(d1 !== d2); // prints true (wrong!)
console.log(d1.getTime() === d2.getTime()); // prints true (correct)
I suggest you use drop-downs or some similar constrained form of date entry rather than text boxes, though, lest you find yourself in input validation hell.
For the curious, date.getTime() documentation:
Returns the numeric value of the specified date as the number of milliseconds since January 1, 1970, 00:00:00 UTC. (Negative values are returned for prior times.)
Compare < and > just as usual, but anything involving == or === should use a + prefix. Like so:
const x = new Date('2013-05-23');
const y = new Date('2013-05-23');
// less than, greater than is fine:
console.log('x < y', x < y); // false
console.log('x > y', x > y); // false
console.log('x <= y', x <= y); // true
console.log('x >= y', x >= y); // true
console.log('x === y', x === y); // false, oops!
// anything involving '==' or '===' should use the '+' prefix
// it will then compare the dates' millisecond values
console.log('+x === +y', +x === +y); // true
The easiest way to compare dates in javascript is to first convert it to a Date object and then compare these date-objects.
Below you find an object with three functions:
dates.compare(a,b)
Returns a number:
-1 if a < b
0 if a = b
1 if a > b
NaN if a or b is an illegal date
dates.inRange (d,start,end)
Returns a boolean or NaN:
true if d is between the start and end (inclusive)
false if d is before start or after end.
NaN if one or more of the dates are illegal.
dates.convert
Used by the other functions to convert their input to a date object. The input can be
a date-object : The input is returned as is.
an array: Interpreted as [year,month,day]. NOTE month is 0-11.
a number : Interpreted as number of milliseconds since 1 Jan 1970 (a timestamp)
a string : Several different formats is supported, like "YYYY/MM/DD", "MM/DD/YYYY", "Jan 31 2009" etc.
an object: Interpreted as an object with year, month and date attributes. NOTE month is 0-11.
.
// Source: http://stackoverflow.com/questions/497790
var dates = {
convert:function(d) {
// Converts the date in d to a date-object. The input can be:
// a date object: returned without modification
// an array : Interpreted as [year,month,day]. NOTE: month is 0-11.
// a number : Interpreted as number of milliseconds
// since 1 Jan 1970 (a timestamp)
// a string : Any format supported by the javascript engine, like
// "YYYY/MM/DD", "MM/DD/YYYY", "Jan 31 2009" etc.
// an object : Interpreted as an object with year, month and date
// attributes. **NOTE** month is 0-11.
return (
d.constructor === Date ? d :
d.constructor === Array ? new Date(d[0],d[1],d[2]) :
d.constructor === Number ? new Date(d) :
d.constructor === String ? new Date(d) :
typeof d === "object" ? new Date(d.year,d.month,d.date) :
NaN
);
},
compare:function(a,b) {
// Compare two dates (could be of any type supported by the convert
// function above) and returns:
// -1 : if a < b
// 0 : if a = b
// 1 : if a > b
// NaN : if a or b is an illegal date
// NOTE: The code inside isFinite does an assignment (=).
return (
isFinite(a=this.convert(a).valueOf()) &&
isFinite(b=this.convert(b).valueOf()) ?
(a>b)-(a<b) :
NaN
);
},
inRange:function(d,start,end) {
// Checks if date in d is between dates in start and end.
// Returns a boolean or NaN:
// true : if d is between start and end (inclusive)
// false : if d is before start or after end
// NaN : if one or more of the dates is illegal.
// NOTE: The code inside isFinite does an assignment (=).
return (
isFinite(d=this.convert(d).valueOf()) &&
isFinite(start=this.convert(start).valueOf()) &&
isFinite(end=this.convert(end).valueOf()) ?
start <= d && d <= end :
NaN
);
}
}
The relational operators < <= > >= can be used to compare JavaScript dates:
var d1 = new Date(2013, 0, 1);
var d2 = new Date(2013, 0, 2);
d1 < d2; // true
d1 <= d2; // true
d1 > d2; // false
d1 >= d2; // false
However, the equality operators == != === !== cannot be used to compare (the value of) dates because:
Two distinct objects are never equal for either strict or abstract comparisons.
An expression comparing Objects is only true if the operands reference the same Object.
You can compare the value of dates for equality using any of these methods:
var d1 = new Date(2013, 0, 1);
var d2 = new Date(2013, 0, 1);
/*
* note: d1 == d2 returns false as described above
*/
d1.getTime() == d2.getTime(); // true
d1.valueOf() == d2.valueOf(); // true
Number(d1) == Number(d2); // true
+d1 == +d2; // true
Both Date.getTime() and Date.valueOf() return the number of milliseconds since January 1, 1970, 00:00 UTC. Both Number function and unary + operator call the valueOf() methods behind the scenes.
By far the easiest method is to subtract one date from the other and compare the result.
var oDateOne = new Date();
var oDateTwo = new Date();
alert(oDateOne - oDateTwo === 0);
alert(oDateOne - oDateTwo < 0);
alert(oDateOne - oDateTwo > 0);
Comparing dates in JavaScript is quite easy... JavaScript has built-in comparison system for dates which makes it so easy to do the comparison...
Just follow these steps for comparing 2 dates value, for example you have 2 inputs which each has a Date value in String and you to compare them...
1. you have 2 string values you get from an input and you'd like to compare them, they are as below:
var date1 = '01/12/2018';
var date2 = '12/12/2018';
2. They need to be Date Object to be compared as date values, so simply convert them to date, using new Date(), I just re-assign them for simplicity of explanation, but you can do it anyway you like:
date1 = new Date(date1);
date2 = new Date(date2);
3. Now simply compare them, using the > < >= <=
date1 > date2; //false
date1 < date2; //true
date1 >= date2; //false
date1 <= date2; //true
Compare day only (ignoring time component):
Date.prototype.sameDay = function(d) {
return this.getFullYear() === d.getFullYear()
&& this.getDate() === d.getDate()
&& this.getMonth() === d.getMonth();
}
Usage:
if(date1.sameDay(date2)) {
// highlight day on calendar or something else clever
}
I no longer recommend modifying the prototype of built-in objects. Try this instead:
function isSameDay(d1, d2) {
return d1.getFullYear() === d2.getFullYear() &&
d1.getDate() === d2.getDate() &&
d1.getMonth() === d2.getMonth();
}
console.log(isSameDay(new Date('Jan 15 2021 02:39:53 GMT-0800'), new Date('Jan 15 2021 23:39:53 GMT-0800')));
console.log(isSameDay(new Date('Jan 15 2021 10:39:53 GMT-0800'), new Date('Jan 16 2021 10:39:53 GMT-0800')));
N.B. the year/month/day will be returned for your timezone; I recommend using a timezone-aware library if you want to check if two dates are on the same day in a different timezone.
e.g.
> (new Date('Jan 15 2021 01:39:53 Z')).getDate() // Jan 15 in UTC
14 // Returns "14" because I'm in GMT-08
what format?
If you construct a Javascript Date object, you can just subtract them to get a milliseconds difference (edit: or just compare them) :
js>t1 = new Date()
Thu Jan 29 2009 14:19:28 GMT-0500 (Eastern Standard Time)
js>t2 = new Date()
Thu Jan 29 2009 14:19:31 GMT-0500 (Eastern Standard Time)
js>t2-t1
2672
js>t3 = new Date('2009 Jan 1')
Thu Jan 01 2009 00:00:00 GMT-0500 (Eastern Standard Time)
js>t1-t3
2470768442
js>t1>t3
true
Note - Compare Only Date Part:
When we compare two date in javascript. It takes hours, minutes and seconds also into consideration.. So If we only need to compare date only, this is the approach:
var date1= new Date("01/01/2014").setHours(0,0,0,0);
var date2= new Date("01/01/2014").setHours(0,0,0,0);
Now: if date1.valueOf()> date2.valueOf() will work like a charm.
The simple way is,
var first = '2012-11-21';
var second = '2012-11-03';
if (new Date(first) > new Date(second) {
.....
}
SHORT ANSWER
Here is a function that return {boolean} if the from dateTime > to dateTime Demo in action
var from = '08/19/2013 00:00'
var to = '08/12/2013 00:00 '
function isFromBiggerThanTo(dtmfrom, dtmto){
return new Date(dtmfrom).getTime() >= new Date(dtmto).getTime() ;
}
console.log(isFromBiggerThanTo(from, to)); //true
Explanation
jsFiddle
var date_one = '2013-07-29 01:50:00',
date_two = '2013-07-29 02:50:00';
//getTime() returns the number of milliseconds since 01.01.1970.
var timeStamp_date_one = new Date(date_one).getTime() ; //1375077000000
console.log(typeof timeStamp_date_one);//number
var timeStamp_date_two = new Date(date_two).getTime() ;//1375080600000
console.log(typeof timeStamp_date_two);//number
since you are now having both datetime in number type
you can compare them with any Comparison operations
( >, < ,= ,!= ,== ,!== ,>= AND <=)
Then
if you are familiar with C# Custom Date and Time Format String this library should do the exact same thing and help you format your date and time dtmFRM whether you are passing in date time string or unix format
Usage
var myDateTime = new dtmFRM();
alert(myDateTime.ToString(1375077000000, "MM/dd/yyyy hh:mm:ss ampm"));
//07/29/2013 01:50:00 AM
alert(myDateTime.ToString(1375077000000,"the year is yyyy and the day is dddd"));
//this year is 2013 and the day is Monday
alert(myDateTime.ToString('1/21/2014', "this month is MMMM and the day is dd"));
//this month is january and the day is 21
DEMO
all you have to do is passing any of these format pacified in the library js file
You can use this code:
var firstValue = "2012-05-12".split('-');
var secondValue = "2014-07-12".split('-');
var firstDate=new Date();
firstDate.setFullYear(firstValue[0],(firstValue[1] - 1 ),firstValue[2]);
var secondDate=new Date();
secondDate.setFullYear(secondValue[0],(secondValue[1] - 1 ),secondValue[2]);
if (firstDate > secondDate)
{
alert("First Date is greater than Second Date");
}
else
{
alert("Second Date is greater than First Date");
}
And also check the MDN article for the Date class.
function datesEqual(a, b)
{
return (!(a>b || b>a))
}
var date = new Date(); // will give you todays date.
// following calls, will let you set new dates.
setDate()
setFullYear()
setHours()
setMilliseconds()
setMinutes()
setMonth()
setSeconds()
setTime()
var yesterday = new Date();
yesterday.setDate(...date info here);
if(date>yesterday) // will compare dates
BEWARE THE TIMEZONE
A javascript date has no notion of timezone. It's a moment in time (ticks since the epoch) with handy functions for translating to and from strings in the "local" timezone. If you want to work with dates using date objects, as everyone here is doing, you want your dates to represent UTC midnight at the start of the date in question. This is a common and necessary convention that lets you work with dates regardless of the season or timezone of their creation. So you need to be very vigilant to manage the notion of timezone, particularly when you create your midnight UTC Date object.
Most of the time, you will want your date to reflect the timezone of the user. Click if today is your birthday. Users in NZ and US click at the same time and get different dates. In that case, do this...
// create a date (utc midnight) reflecting the value of myDate and the environment's timezone offset.
new Date(Date.UTC(myDate.getFullYear(),myDate.getMonth(), myDate.getDate()));
Sometimes, international comparability trumps local accuracy. In that case, do this...
// the date in London of a moment in time. Device timezone is ignored.
new Date(Date.UTC(myDate.getUTCYear(), myDate.getyUTCMonth(), myDate.getUTCDate()));
Now you can directly compare your date objects as the other answers suggest.
Having taken care to manage timezone when you create, you also need to be sure to keep timezone out when you convert back to a string representation. So you can safely use...
toISOString()
getUTCxxx()
getTime() //returns a number with no time or timezone.
.toLocaleDateString("fr",{timezone:"UTC"}) // whatever locale you want, but ALWAYS UTC.
And totally avoid everything else, especially...
getYear(),getMonth(),getDate()
Via Moment.js
Jsfiddle: http://jsfiddle.net/guhokemk/1/
function compare(dateTimeA, dateTimeB) {
var momentA = moment(dateTimeA,"DD/MM/YYYY");
var momentB = moment(dateTimeB,"DD/MM/YYYY");
if (momentA > momentB) return 1;
else if (momentA < momentB) return -1;
else return 0;
}
alert(compare("11/07/2015", "10/07/2015"));
The method returns 1 if dateTimeA is greater than dateTimeB
The method returns 0 if dateTimeA equals dateTimeB
The method returns -1 if dateTimeA is less than dateTimeB
Just to add yet another possibility to the many existing options, you could try:
if (date1.valueOf()==date2.valueOf()) .....
...which seems to work for me. Of course you do have to ensure that both dates are not undefined...
if ((date1?date1.valueOf():0)==(date2?date2.valueOf():0) .....
This way we can ensure that a positive comparison is made if both are undefined also, or...
if ((date1?date1.valueOf():0)==(date2?date2.valueOf():-1) .....
...if you prefer them not to be equal.
If following is your date format, you can use this code:
var first = '2012-11-21';
var second = '2012-11-03';
if(parseInt(first.replace(/-/g,""),10) > parseInt(second.replace(/-/g,""),10)){
//...
}
It will check whether 20121121 number is bigger than 20121103 or not.
Subtract two date get the difference in millisecond, if you get 0 it's the same date
function areSameDate(d1, d2){
return d1 - d2 === 0
}
Say you got the date objects A and B, get their EPOC time value, then subtract to get the difference in milliseconds.
var diff = +A - +B;
That's all.
One way to compare two dates is to use the dates.js library.
The Date.compare(Date date1, Date date2) method that returns a number which means the one of following result:
-1 = date1 is less than date2.
0 = values are equal.
1 = date1 is greater than date2.
Performance
Today 2020.02.27 I perform tests of chosen solutions on Chrome v80.0, Safari v13.0.5 and Firefox 73.0.1 on MacOs High Sierra v10.13.6
Conclusions
solutions d1==d2 (D) and d1===d2 (E) are fastest for all browsers
solution getTime (A) is faster than valueOf (B) (both are medium fast)
solutions F,L,N are slowest for all browsers
Details
In below snippet solutions used in performance tests are presented. You can perform test in you machine HERE
function A(d1,d2) {
return d1.getTime() == d2.getTime();
}
function B(d1,d2) {
return d1.valueOf() == d2.valueOf();
}
function C(d1,d2) {
return Number(d1) == Number(d2);
}
function D(d1,d2) {
return d1 == d2;
}
function E(d1,d2) {
return d1 === d2;
}
function F(d1,d2) {
return (!(d1>d2 || d2>d1));
}
function G(d1,d2) {
return d1*1 == d2*1;
}
function H(d1,d2) {
return +d1 == +d2;
}
function I(d1,d2) {
return !(+d1 - +d2);
}
function J(d1,d2) {
return !(d1 - d2);
}
function K(d1,d2) {
return d1 - d2 == 0;
}
function L(d1,d2) {
return !((d1>d2)-(d1<d2));
}
function M(d1,d2) {
return d1.getFullYear() === d2.getFullYear()
&& d1.getDate() === d2.getDate()
&& d1.getMonth() === d2.getMonth();
}
function N(d1,d2) {
return (isFinite(d1.valueOf()) && isFinite(d2.valueOf()) ? !((d1>d2)-(d1<d2)) : false );
}
// TEST
let past= new Date('2002-12-24'); // past
let now= new Date('2020-02-26'); // now
console.log('Code d1>d2 d1<d2 d1=d2')
var log = (l,f) => console.log(`${l} ${f(now,past)} ${f(past,now)} ${f(now,now)}`);
log('A',A);
log('B',B);
log('C',C);
log('D',D);
log('E',E);
log('G',G);
log('H',H);
log('I',I);
log('J',J);
log('K',K);
log('L',L);
log('M',M);
log('N',N);
p {color: red}
<p>This snippet only presents tested solutions (it not perform tests itself)</p>
Results for chrome
In order to create dates from free text in JavaScript you need to parse it into the Date object.
You could use Date.parse() which takes free text and tries to convert it into a new date but if you have control over the page I would recommend using HTML select boxes instead or a date picker such as the YUI calendar control or the jQuery UI Datepicker.
Once you have a date, as other people have pointed out, you can use simple arithmetic to subtract the dates and convert it back into a number of days by dividing the number (in seconds) by the number of seconds in a day (60*60*24 = 86400).
var date_today=new Date();
var formated_date = formatDate(date_today);//Calling formatDate Function
var input_date="2015/04/22 11:12 AM";
var currentDateTime = new Date(Date.parse(formated_date));
var inputDateTime = new Date(Date.parse(input_date));
if (inputDateTime <= currentDateTime){
//Do something...
}
function formatDate(date) {
var hours = date.getHours();
var minutes = date.getMinutes();
var ampm = hours >= 12 ? 'PM' : 'AM';
hours = hours % 12;
hours = hours ? hours : 12; // the hour '0' should be '12'
hours = hours < 10 ? '0'+hours : hours ;
minutes = minutes < 10 ? '0'+minutes : minutes;
var strTime = hours+":"+minutes+ ' ' + ampm;
return date.getFullYear()+ "/" + ((date.getMonth()+1) < 10 ? "0"+(date.getMonth()+1) :
(date.getMonth()+1) ) + "/" + (date.getDate() < 10 ? "0"+date.getDate() :
date.getDate()) + " " + strTime;
}
An Improved version of the code posted by "some"
/* Compare the current date against another date.
*
* #param b {Date} the other date
* #returns -1 : if this < b
* 0 : if this === b
* 1 : if this > b
* NaN : if a or b is an illegal date
*/
Date.prototype.compare = function(b) {
if (b.constructor !== Date) {
throw "invalid_date";
}
return (isFinite(this.valueOf()) && isFinite(b.valueOf()) ?
(this>b)-(this<b) : NaN
);
};
usage:
var a = new Date(2011, 1-1, 1);
var b = new Date(2011, 1-1, 1);
var c = new Date(2011, 1-1, 31);
var d = new Date(2011, 1-1, 31);
assertEquals( 0, a.compare(b));
assertEquals( 0, b.compare(a));
assertEquals(-1, a.compare(c));
assertEquals( 1, c.compare(a));
I usually store Dates as timestamps(Number) in databases.
When I need to compare, I simply compare among those timestamps or
convert it to Date Object and then compare with > <if necessary.
Note that == or === does not work properly unless your variables are references of the same Date Object.
Convert those Date objects to timestamp(number) first and then compare equality of them.
Date to Timestamp
var timestamp_1970 = new Date(0).getTime(); // 1970-01-01 00:00:00
var timestamp = new Date().getTime(); // Current Timestamp
Timestamp to Date
var timestamp = 0; // 1970-01-01 00:00:00
var DateObject = new Date(timestamp);
Before comparing the Dates object, try setting both of their milliseconds to zero like Date.setMilliseconds(0);.
In some cases where the Date object is dynamically created in javascript, if you keep printing the Date.getTime(), you'll see the milliseconds changing, which will prevent the equality of both dates.
Let's suppose that you deal with this 2014[:-/.]06[:-/.]06 or this 06[:-/.]06[:-/.]2014 date format, then you may compare dates this way
var a = '2014.06/07', b = '2014-06.07', c = '07-06/2014', d = '07/06.2014';
parseInt(a.replace(/[:\s\/\.-]/g, '')) == parseInt(b.replace(/[:\s\/\.-]/g, '')); // true
parseInt(c.replace(/[:\s\/\.-]/g, '')) == parseInt(d.replace(/[:\s\/\.-]/g, '')); // true
parseInt(a.replace(/[:\s\/\.-]/g, '')) < parseInt(b.replace(/[:\s\/\.-]/g, '')); // false
parseInt(c.replace(/[:\s\/\.-]/g, '')) > parseInt(d.replace(/[:\s\/\.-]/g, '')); // false
As you can see, we strip separator(s) and then compare integers.
My simple answer for this question
checkDisabled(date) {
const today = new Date()
const newDate = new Date(date._d)
if (today.getTime() > newDate.getTime()) {
return true
}
return false
}
If both of your dates come in the format "YYYY-MM-DD", you can skip the Date object and compare strings directly.
This works because of how the strings are compared in JS
let date1 = '2022-12-13';
let date2 = '2022-02-13';
console.log(`${date1} > ${date2}`, date1 > date2);
console.log(`${date1} < ${date2}`, date1 < date2);
console.log(`${date1} == ${date2}`, date1 == date2);

Apparently identical dates fail test for equivalency [duplicate]

Can someone suggest a way to compare the values of two dates greater than, less than, and not in the past using JavaScript? The values will be coming from text boxes.
The Date object will do what you want - construct one for each date, then compare them using the >, <, <= or >=.
The ==, !=, ===, and !== operators require you to use date.getTime() as in
var d1 = new Date();
var d2 = new Date(d1);
var same = d1.getTime() === d2.getTime();
var notSame = d1.getTime() !== d2.getTime();
to be clear just checking for equality directly with the date objects won't work
var d1 = new Date();
var d2 = new Date(d1);
console.log(d1 == d2); // prints false (wrong!)
console.log(d1 === d2); // prints false (wrong!)
console.log(d1 != d2); // prints true (wrong!)
console.log(d1 !== d2); // prints true (wrong!)
console.log(d1.getTime() === d2.getTime()); // prints true (correct)
I suggest you use drop-downs or some similar constrained form of date entry rather than text boxes, though, lest you find yourself in input validation hell.
For the curious, date.getTime() documentation:
Returns the numeric value of the specified date as the number of milliseconds since January 1, 1970, 00:00:00 UTC. (Negative values are returned for prior times.)
Compare < and > just as usual, but anything involving == or === should use a + prefix. Like so:
const x = new Date('2013-05-23');
const y = new Date('2013-05-23');
// less than, greater than is fine:
console.log('x < y', x < y); // false
console.log('x > y', x > y); // false
console.log('x <= y', x <= y); // true
console.log('x >= y', x >= y); // true
console.log('x === y', x === y); // false, oops!
// anything involving '==' or '===' should use the '+' prefix
// it will then compare the dates' millisecond values
console.log('+x === +y', +x === +y); // true
The easiest way to compare dates in javascript is to first convert it to a Date object and then compare these date-objects.
Below you find an object with three functions:
dates.compare(a,b)
Returns a number:
-1 if a < b
0 if a = b
1 if a > b
NaN if a or b is an illegal date
dates.inRange (d,start,end)
Returns a boolean or NaN:
true if d is between the start and end (inclusive)
false if d is before start or after end.
NaN if one or more of the dates are illegal.
dates.convert
Used by the other functions to convert their input to a date object. The input can be
a date-object : The input is returned as is.
an array: Interpreted as [year,month,day]. NOTE month is 0-11.
a number : Interpreted as number of milliseconds since 1 Jan 1970 (a timestamp)
a string : Several different formats is supported, like "YYYY/MM/DD", "MM/DD/YYYY", "Jan 31 2009" etc.
an object: Interpreted as an object with year, month and date attributes. NOTE month is 0-11.
.
// Source: http://stackoverflow.com/questions/497790
var dates = {
convert:function(d) {
// Converts the date in d to a date-object. The input can be:
// a date object: returned without modification
// an array : Interpreted as [year,month,day]. NOTE: month is 0-11.
// a number : Interpreted as number of milliseconds
// since 1 Jan 1970 (a timestamp)
// a string : Any format supported by the javascript engine, like
// "YYYY/MM/DD", "MM/DD/YYYY", "Jan 31 2009" etc.
// an object : Interpreted as an object with year, month and date
// attributes. **NOTE** month is 0-11.
return (
d.constructor === Date ? d :
d.constructor === Array ? new Date(d[0],d[1],d[2]) :
d.constructor === Number ? new Date(d) :
d.constructor === String ? new Date(d) :
typeof d === "object" ? new Date(d.year,d.month,d.date) :
NaN
);
},
compare:function(a,b) {
// Compare two dates (could be of any type supported by the convert
// function above) and returns:
// -1 : if a < b
// 0 : if a = b
// 1 : if a > b
// NaN : if a or b is an illegal date
// NOTE: The code inside isFinite does an assignment (=).
return (
isFinite(a=this.convert(a).valueOf()) &&
isFinite(b=this.convert(b).valueOf()) ?
(a>b)-(a<b) :
NaN
);
},
inRange:function(d,start,end) {
// Checks if date in d is between dates in start and end.
// Returns a boolean or NaN:
// true : if d is between start and end (inclusive)
// false : if d is before start or after end
// NaN : if one or more of the dates is illegal.
// NOTE: The code inside isFinite does an assignment (=).
return (
isFinite(d=this.convert(d).valueOf()) &&
isFinite(start=this.convert(start).valueOf()) &&
isFinite(end=this.convert(end).valueOf()) ?
start <= d && d <= end :
NaN
);
}
}
The relational operators < <= > >= can be used to compare JavaScript dates:
var d1 = new Date(2013, 0, 1);
var d2 = new Date(2013, 0, 2);
d1 < d2; // true
d1 <= d2; // true
d1 > d2; // false
d1 >= d2; // false
However, the equality operators == != === !== cannot be used to compare (the value of) dates because:
Two distinct objects are never equal for either strict or abstract comparisons.
An expression comparing Objects is only true if the operands reference the same Object.
You can compare the value of dates for equality using any of these methods:
var d1 = new Date(2013, 0, 1);
var d2 = new Date(2013, 0, 1);
/*
* note: d1 == d2 returns false as described above
*/
d1.getTime() == d2.getTime(); // true
d1.valueOf() == d2.valueOf(); // true
Number(d1) == Number(d2); // true
+d1 == +d2; // true
Both Date.getTime() and Date.valueOf() return the number of milliseconds since January 1, 1970, 00:00 UTC. Both Number function and unary + operator call the valueOf() methods behind the scenes.
By far the easiest method is to subtract one date from the other and compare the result.
var oDateOne = new Date();
var oDateTwo = new Date();
alert(oDateOne - oDateTwo === 0);
alert(oDateOne - oDateTwo < 0);
alert(oDateOne - oDateTwo > 0);
Comparing dates in JavaScript is quite easy... JavaScript has built-in comparison system for dates which makes it so easy to do the comparison...
Just follow these steps for comparing 2 dates value, for example you have 2 inputs which each has a Date value in String and you to compare them...
1. you have 2 string values you get from an input and you'd like to compare them, they are as below:
var date1 = '01/12/2018';
var date2 = '12/12/2018';
2. They need to be Date Object to be compared as date values, so simply convert them to date, using new Date(), I just re-assign them for simplicity of explanation, but you can do it anyway you like:
date1 = new Date(date1);
date2 = new Date(date2);
3. Now simply compare them, using the > < >= <=
date1 > date2; //false
date1 < date2; //true
date1 >= date2; //false
date1 <= date2; //true
Compare day only (ignoring time component):
Date.prototype.sameDay = function(d) {
return this.getFullYear() === d.getFullYear()
&& this.getDate() === d.getDate()
&& this.getMonth() === d.getMonth();
}
Usage:
if(date1.sameDay(date2)) {
// highlight day on calendar or something else clever
}
I no longer recommend modifying the prototype of built-in objects. Try this instead:
function isSameDay(d1, d2) {
return d1.getFullYear() === d2.getFullYear() &&
d1.getDate() === d2.getDate() &&
d1.getMonth() === d2.getMonth();
}
console.log(isSameDay(new Date('Jan 15 2021 02:39:53 GMT-0800'), new Date('Jan 15 2021 23:39:53 GMT-0800')));
console.log(isSameDay(new Date('Jan 15 2021 10:39:53 GMT-0800'), new Date('Jan 16 2021 10:39:53 GMT-0800')));
N.B. the year/month/day will be returned for your timezone; I recommend using a timezone-aware library if you want to check if two dates are on the same day in a different timezone.
e.g.
> (new Date('Jan 15 2021 01:39:53 Z')).getDate() // Jan 15 in UTC
14 // Returns "14" because I'm in GMT-08
what format?
If you construct a Javascript Date object, you can just subtract them to get a milliseconds difference (edit: or just compare them) :
js>t1 = new Date()
Thu Jan 29 2009 14:19:28 GMT-0500 (Eastern Standard Time)
js>t2 = new Date()
Thu Jan 29 2009 14:19:31 GMT-0500 (Eastern Standard Time)
js>t2-t1
2672
js>t3 = new Date('2009 Jan 1')
Thu Jan 01 2009 00:00:00 GMT-0500 (Eastern Standard Time)
js>t1-t3
2470768442
js>t1>t3
true
Note - Compare Only Date Part:
When we compare two date in javascript. It takes hours, minutes and seconds also into consideration.. So If we only need to compare date only, this is the approach:
var date1= new Date("01/01/2014").setHours(0,0,0,0);
var date2= new Date("01/01/2014").setHours(0,0,0,0);
Now: if date1.valueOf()> date2.valueOf() will work like a charm.
The simple way is,
var first = '2012-11-21';
var second = '2012-11-03';
if (new Date(first) > new Date(second) {
.....
}
SHORT ANSWER
Here is a function that return {boolean} if the from dateTime > to dateTime Demo in action
var from = '08/19/2013 00:00'
var to = '08/12/2013 00:00 '
function isFromBiggerThanTo(dtmfrom, dtmto){
return new Date(dtmfrom).getTime() >= new Date(dtmto).getTime() ;
}
console.log(isFromBiggerThanTo(from, to)); //true
Explanation
jsFiddle
var date_one = '2013-07-29 01:50:00',
date_two = '2013-07-29 02:50:00';
//getTime() returns the number of milliseconds since 01.01.1970.
var timeStamp_date_one = new Date(date_one).getTime() ; //1375077000000
console.log(typeof timeStamp_date_one);//number
var timeStamp_date_two = new Date(date_two).getTime() ;//1375080600000
console.log(typeof timeStamp_date_two);//number
since you are now having both datetime in number type
you can compare them with any Comparison operations
( >, < ,= ,!= ,== ,!== ,>= AND <=)
Then
if you are familiar with C# Custom Date and Time Format String this library should do the exact same thing and help you format your date and time dtmFRM whether you are passing in date time string or unix format
Usage
var myDateTime = new dtmFRM();
alert(myDateTime.ToString(1375077000000, "MM/dd/yyyy hh:mm:ss ampm"));
//07/29/2013 01:50:00 AM
alert(myDateTime.ToString(1375077000000,"the year is yyyy and the day is dddd"));
//this year is 2013 and the day is Monday
alert(myDateTime.ToString('1/21/2014', "this month is MMMM and the day is dd"));
//this month is january and the day is 21
DEMO
all you have to do is passing any of these format pacified in the library js file
You can use this code:
var firstValue = "2012-05-12".split('-');
var secondValue = "2014-07-12".split('-');
var firstDate=new Date();
firstDate.setFullYear(firstValue[0],(firstValue[1] - 1 ),firstValue[2]);
var secondDate=new Date();
secondDate.setFullYear(secondValue[0],(secondValue[1] - 1 ),secondValue[2]);
if (firstDate > secondDate)
{
alert("First Date is greater than Second Date");
}
else
{
alert("Second Date is greater than First Date");
}
And also check the MDN article for the Date class.
function datesEqual(a, b)
{
return (!(a>b || b>a))
}
var date = new Date(); // will give you todays date.
// following calls, will let you set new dates.
setDate()
setFullYear()
setHours()
setMilliseconds()
setMinutes()
setMonth()
setSeconds()
setTime()
var yesterday = new Date();
yesterday.setDate(...date info here);
if(date>yesterday) // will compare dates
BEWARE THE TIMEZONE
A javascript date has no notion of timezone. It's a moment in time (ticks since the epoch) with handy functions for translating to and from strings in the "local" timezone. If you want to work with dates using date objects, as everyone here is doing, you want your dates to represent UTC midnight at the start of the date in question. This is a common and necessary convention that lets you work with dates regardless of the season or timezone of their creation. So you need to be very vigilant to manage the notion of timezone, particularly when you create your midnight UTC Date object.
Most of the time, you will want your date to reflect the timezone of the user. Click if today is your birthday. Users in NZ and US click at the same time and get different dates. In that case, do this...
// create a date (utc midnight) reflecting the value of myDate and the environment's timezone offset.
new Date(Date.UTC(myDate.getFullYear(),myDate.getMonth(), myDate.getDate()));
Sometimes, international comparability trumps local accuracy. In that case, do this...
// the date in London of a moment in time. Device timezone is ignored.
new Date(Date.UTC(myDate.getUTCYear(), myDate.getyUTCMonth(), myDate.getUTCDate()));
Now you can directly compare your date objects as the other answers suggest.
Having taken care to manage timezone when you create, you also need to be sure to keep timezone out when you convert back to a string representation. So you can safely use...
toISOString()
getUTCxxx()
getTime() //returns a number with no time or timezone.
.toLocaleDateString("fr",{timezone:"UTC"}) // whatever locale you want, but ALWAYS UTC.
And totally avoid everything else, especially...
getYear(),getMonth(),getDate()
Via Moment.js
Jsfiddle: http://jsfiddle.net/guhokemk/1/
function compare(dateTimeA, dateTimeB) {
var momentA = moment(dateTimeA,"DD/MM/YYYY");
var momentB = moment(dateTimeB,"DD/MM/YYYY");
if (momentA > momentB) return 1;
else if (momentA < momentB) return -1;
else return 0;
}
alert(compare("11/07/2015", "10/07/2015"));
The method returns 1 if dateTimeA is greater than dateTimeB
The method returns 0 if dateTimeA equals dateTimeB
The method returns -1 if dateTimeA is less than dateTimeB
Just to add yet another possibility to the many existing options, you could try:
if (date1.valueOf()==date2.valueOf()) .....
...which seems to work for me. Of course you do have to ensure that both dates are not undefined...
if ((date1?date1.valueOf():0)==(date2?date2.valueOf():0) .....
This way we can ensure that a positive comparison is made if both are undefined also, or...
if ((date1?date1.valueOf():0)==(date2?date2.valueOf():-1) .....
...if you prefer them not to be equal.
If following is your date format, you can use this code:
var first = '2012-11-21';
var second = '2012-11-03';
if(parseInt(first.replace(/-/g,""),10) > parseInt(second.replace(/-/g,""),10)){
//...
}
It will check whether 20121121 number is bigger than 20121103 or not.
Subtract two date get the difference in millisecond, if you get 0 it's the same date
function areSameDate(d1, d2){
return d1 - d2 === 0
}
Say you got the date objects A and B, get their EPOC time value, then subtract to get the difference in milliseconds.
var diff = +A - +B;
That's all.
One way to compare two dates is to use the dates.js library.
The Date.compare(Date date1, Date date2) method that returns a number which means the one of following result:
-1 = date1 is less than date2.
0 = values are equal.
1 = date1 is greater than date2.
Performance
Today 2020.02.27 I perform tests of chosen solutions on Chrome v80.0, Safari v13.0.5 and Firefox 73.0.1 on MacOs High Sierra v10.13.6
Conclusions
solutions d1==d2 (D) and d1===d2 (E) are fastest for all browsers
solution getTime (A) is faster than valueOf (B) (both are medium fast)
solutions F,L,N are slowest for all browsers
Details
In below snippet solutions used in performance tests are presented. You can perform test in you machine HERE
function A(d1,d2) {
return d1.getTime() == d2.getTime();
}
function B(d1,d2) {
return d1.valueOf() == d2.valueOf();
}
function C(d1,d2) {
return Number(d1) == Number(d2);
}
function D(d1,d2) {
return d1 == d2;
}
function E(d1,d2) {
return d1 === d2;
}
function F(d1,d2) {
return (!(d1>d2 || d2>d1));
}
function G(d1,d2) {
return d1*1 == d2*1;
}
function H(d1,d2) {
return +d1 == +d2;
}
function I(d1,d2) {
return !(+d1 - +d2);
}
function J(d1,d2) {
return !(d1 - d2);
}
function K(d1,d2) {
return d1 - d2 == 0;
}
function L(d1,d2) {
return !((d1>d2)-(d1<d2));
}
function M(d1,d2) {
return d1.getFullYear() === d2.getFullYear()
&& d1.getDate() === d2.getDate()
&& d1.getMonth() === d2.getMonth();
}
function N(d1,d2) {
return (isFinite(d1.valueOf()) && isFinite(d2.valueOf()) ? !((d1>d2)-(d1<d2)) : false );
}
// TEST
let past= new Date('2002-12-24'); // past
let now= new Date('2020-02-26'); // now
console.log('Code d1>d2 d1<d2 d1=d2')
var log = (l,f) => console.log(`${l} ${f(now,past)} ${f(past,now)} ${f(now,now)}`);
log('A',A);
log('B',B);
log('C',C);
log('D',D);
log('E',E);
log('G',G);
log('H',H);
log('I',I);
log('J',J);
log('K',K);
log('L',L);
log('M',M);
log('N',N);
p {color: red}
<p>This snippet only presents tested solutions (it not perform tests itself)</p>
Results for chrome
In order to create dates from free text in JavaScript you need to parse it into the Date object.
You could use Date.parse() which takes free text and tries to convert it into a new date but if you have control over the page I would recommend using HTML select boxes instead or a date picker such as the YUI calendar control or the jQuery UI Datepicker.
Once you have a date, as other people have pointed out, you can use simple arithmetic to subtract the dates and convert it back into a number of days by dividing the number (in seconds) by the number of seconds in a day (60*60*24 = 86400).
var date_today=new Date();
var formated_date = formatDate(date_today);//Calling formatDate Function
var input_date="2015/04/22 11:12 AM";
var currentDateTime = new Date(Date.parse(formated_date));
var inputDateTime = new Date(Date.parse(input_date));
if (inputDateTime <= currentDateTime){
//Do something...
}
function formatDate(date) {
var hours = date.getHours();
var minutes = date.getMinutes();
var ampm = hours >= 12 ? 'PM' : 'AM';
hours = hours % 12;
hours = hours ? hours : 12; // the hour '0' should be '12'
hours = hours < 10 ? '0'+hours : hours ;
minutes = minutes < 10 ? '0'+minutes : minutes;
var strTime = hours+":"+minutes+ ' ' + ampm;
return date.getFullYear()+ "/" + ((date.getMonth()+1) < 10 ? "0"+(date.getMonth()+1) :
(date.getMonth()+1) ) + "/" + (date.getDate() < 10 ? "0"+date.getDate() :
date.getDate()) + " " + strTime;
}
An Improved version of the code posted by "some"
/* Compare the current date against another date.
*
* #param b {Date} the other date
* #returns -1 : if this < b
* 0 : if this === b
* 1 : if this > b
* NaN : if a or b is an illegal date
*/
Date.prototype.compare = function(b) {
if (b.constructor !== Date) {
throw "invalid_date";
}
return (isFinite(this.valueOf()) && isFinite(b.valueOf()) ?
(this>b)-(this<b) : NaN
);
};
usage:
var a = new Date(2011, 1-1, 1);
var b = new Date(2011, 1-1, 1);
var c = new Date(2011, 1-1, 31);
var d = new Date(2011, 1-1, 31);
assertEquals( 0, a.compare(b));
assertEquals( 0, b.compare(a));
assertEquals(-1, a.compare(c));
assertEquals( 1, c.compare(a));
I usually store Dates as timestamps(Number) in databases.
When I need to compare, I simply compare among those timestamps or
convert it to Date Object and then compare with > <if necessary.
Note that == or === does not work properly unless your variables are references of the same Date Object.
Convert those Date objects to timestamp(number) first and then compare equality of them.
Date to Timestamp
var timestamp_1970 = new Date(0).getTime(); // 1970-01-01 00:00:00
var timestamp = new Date().getTime(); // Current Timestamp
Timestamp to Date
var timestamp = 0; // 1970-01-01 00:00:00
var DateObject = new Date(timestamp);
Before comparing the Dates object, try setting both of their milliseconds to zero like Date.setMilliseconds(0);.
In some cases where the Date object is dynamically created in javascript, if you keep printing the Date.getTime(), you'll see the milliseconds changing, which will prevent the equality of both dates.
Let's suppose that you deal with this 2014[:-/.]06[:-/.]06 or this 06[:-/.]06[:-/.]2014 date format, then you may compare dates this way
var a = '2014.06/07', b = '2014-06.07', c = '07-06/2014', d = '07/06.2014';
parseInt(a.replace(/[:\s\/\.-]/g, '')) == parseInt(b.replace(/[:\s\/\.-]/g, '')); // true
parseInt(c.replace(/[:\s\/\.-]/g, '')) == parseInt(d.replace(/[:\s\/\.-]/g, '')); // true
parseInt(a.replace(/[:\s\/\.-]/g, '')) < parseInt(b.replace(/[:\s\/\.-]/g, '')); // false
parseInt(c.replace(/[:\s\/\.-]/g, '')) > parseInt(d.replace(/[:\s\/\.-]/g, '')); // false
As you can see, we strip separator(s) and then compare integers.
My simple answer for this question
checkDisabled(date) {
const today = new Date()
const newDate = new Date(date._d)
if (today.getTime() > newDate.getTime()) {
return true
}
return false
}
If both of your dates come in the format "YYYY-MM-DD", you can skip the Date object and compare strings directly.
This works because of how the strings are compared in JS
let date1 = '2022-12-13';
let date2 = '2022-02-13';
console.log(`${date1} > ${date2}`, date1 > date2);
console.log(`${date1} < ${date2}`, date1 < date2);
console.log(`${date1} == ${date2}`, date1 == date2);

How to change format of date in Meteor/MongoDB [duplicate]

How do I format a Date object to a string?
If you need slightly less control over formatting than the currently accepted answer, Date#toLocaleDateString can be used to create standard locale-specific renderings. The locale and options arguments let applications specify the language whose formatting conventions should be used, and allow some customization of the rendering.
Options key examples:
day:
The representation of the day.
Possible values are "numeric", "2-digit".
weekday:
The representation of the weekday.
Possible values are "narrow", "short", "long".
year:
The representation of the year.
Possible values are "numeric", "2-digit".
month:
The representation of the month.
Possible values are "numeric", "2-digit", "narrow", "short", "long".
hour:
The representation of the hour.
Possible values are "numeric", "2-digit".
minute:
The representation of the minute.
Possible values are "numeric", "2-digit".
second:
The representation of the second.
Possible values are "numeric", 2-digit".
All these keys are optional. You can change the number of options values based on your requirements, and this will also reflect the presence of each date time term.
Note: If you would only like to configure the content options, but still use the current locale, passing null for the first parameter will cause an error. Use undefined instead.
For different languages:
"en-US": For American English
"en-GB": For British English
"hi-IN": For Hindi
"ja-JP": For Japanese
You can use more language options.
For example
var options = { weekday: 'long', year: 'numeric', month: 'long', day: 'numeric' };
var today = new Date();
console.log(today.toLocaleDateString("en-US")); // 9/17/2016
console.log(today.toLocaleDateString("en-US", options)); // Saturday, September 17, 2016
console.log(today.toLocaleDateString("hi-IN", options)); // शनिवार, 17 सितंबर 2016
You can also use the toLocaleString() method for the same purpose. The only difference is this function provides the time when you don't pass any options.
// Example
9/17/2016, 1:21:34 PM
References:
toLocaleString()
toLocaleDateString()
For custom-delimited date formats, you have to pull out the date (or time)
components from a DateTimeFormat object (which is part of the
ECMAScript Internationalization API), and then manually create a string
with the delimiters you want.
To do this, you can use DateTimeFormat#formatToParts. You could
destructure the array, but that is not ideal, as the array output depends on the
locale:
{ // example 1
let f = new Intl.DateTimeFormat('en');
let a = f.formatToParts();
console.log(a);
}
{ // example 2
let f = new Intl.DateTimeFormat('hi');
let a = f.formatToParts();
console.log(a);
}
Better would be to map a format array to resultant strings:
function join(t, a, s) {
function format(m) {
let f = new Intl.DateTimeFormat('en', m);
return f.format(t);
}
return a.map(format).join(s);
}
let a = [{day: 'numeric'}, {month: 'short'}, {year: 'numeric'}];
let s = join(new Date, a, '-');
console.log(s);
You can also pull out the parts of a DateTimeFormat one-by-one using
DateTimeFormat#format, but note that when using this method, as of March
2020, there is a bug in the ECMAScript implementation when it comes to
leading zeros on minutes and seconds (this bug is circumvented by the approach
above).
let d = new Date(2010, 7, 5);
let ye = new Intl.DateTimeFormat('en', { year: 'numeric' }).format(d);
let mo = new Intl.DateTimeFormat('en', { month: 'short' }).format(d);
let da = new Intl.DateTimeFormat('en', { day: '2-digit' }).format(d);
console.log(`${da}-${mo}-${ye}`);
When working with dates and times, it is usually worth using a library (eg. luxon, date-fns, moment.js is not recommended for new projects) because of the many hidden complexities of the field.
Note that the ECMAScript Internationalization API, used in the solutions above
is not supported in IE10 (0.03% global browser market share in Feb
2020).
If you need to quickly format your date using plain JavaScript, use getDate, getMonth + 1, getFullYear, getHours and getMinutes:
var d = new Date();
var datestring = d.getDate() + "-" + (d.getMonth()+1) + "-" + d.getFullYear() + " " +
d.getHours() + ":" + d.getMinutes();
// 16-5-2015 9:50
Or, if you need it to be padded with zeros:
var datestring = ("0" + d.getDate()).slice(-2) + "-" + ("0"+(d.getMonth()+1)).slice(-2) + "-" +
d.getFullYear() + " " + ("0" + d.getHours()).slice(-2) + ":" + ("0" + d.getMinutes()).slice(-2);
// 16-05-2015 09:50
Use the date.format library:
var dateFormat = require('dateformat');
var now = new Date();
dateFormat(now, "dddd, mmmm dS, yyyy, h:MM:ss TT");
returns:
Saturday, June 9th, 2007, 5:46:21 PM
dateformat on npm
http://jsfiddle.net/phZr7/1/
Well, what I wanted was to convert today's date to a MySQL friendly date string like 2012-06-23, and to use that string as a parameter in one of my queries. The simple solution I've found is this:
var today = new Date().toISOString().slice(0, 10);
Keep in mind that the above solution does not take into account your timezone offset.
You might consider using this function instead:
function toJSONLocal (date) {
var local = new Date(date);
local.setMinutes(date.getMinutes() - date.getTimezoneOffset());
return local.toJSON().slice(0, 10);
}
This will give you the correct date in case you are executing this code around the start/end of the day.
var date = new Date();
function toLocal(date) {
var local = new Date(date);
local.setMinutes(date.getMinutes() - date.getTimezoneOffset());
return local.toJSON();
}
function toJSONLocal(date) {
var local = new Date(date);
local.setMinutes(date.getMinutes() - date.getTimezoneOffset());
return local.toJSON().slice(0, 10);
}
// check out your devtools console
console.log(date.toJSON());
console.log(date.toISOString());
console.log(toLocal(date));
console.log(toJSONLocal(date));
Date.toISOString
Date.toJSON
String.slice
External example
Custom formatting function:
For fixed formats, a simple function make the job. The following example generates the international format YYYY-MM-DD:
function dateToYMD(date) {
var d = date.getDate();
var m = date.getMonth() + 1; //Month from 0 to 11
var y = date.getFullYear();
return '' + y + '-' + (m<=9 ? '0' + m : m) + '-' + (d <= 9 ? '0' + d : d);
}
console.log(dateToYMD(new Date(2017,10,5))); // Nov 5
The OP format may be generated like:
function dateToYMD(date) {
var strArray=['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];
var d = date.getDate();
var m = strArray[date.getMonth()];
var y = date.getFullYear();
return '' + (d <= 9 ? '0' + d : d) + '-' + m + '-' + y;
}
console.log(dateToYMD(new Date(2017,10,5))); // Nov 5
Note: It is, however, usually not a good idea to extend the JavaScript standard libraries (e.g. by adding this function to the prototype of Date).
A more advanced function could generate configurable output based on a format parameter.
If to write a formatting function is too long, there are plenty of libraries around which does it. Some other answers already enumerate them. But increasing dependencies also has it counter-part.
Standard ECMAScript formatting functions:
Since more recent versions of ECMAScript, the Date class has some specific formatting functions:
toDateString: Implementation dependent, show only the date.
https://262.ecma-international.org/#sec-date.prototype.todatestring
new Date().toDateString(); // e.g. "Fri Nov 11 2016"
toISOString: Show ISO 8601 date and time.
https://262.ecma-international.org/#sec-date.prototype.toisostring
new Date().toISOString(); // e.g. "2016-11-21T08:00:00.000Z"
toJSON: Stringifier for JSON.
https://262.ecma-international.org/#sec-date.prototype.tojson
new Date().toJSON(); // e.g. "2016-11-21T08:00:00.000Z"
toLocaleDateString: Implementation dependent, a date in locale format.
https://262.ecma-international.org/#sec-date.prototype.tolocaledatestring
new Date().toLocaleDateString(); // e.g. "21/11/2016"
toLocaleString: Implementation dependent, a date&time in locale format.
https://262.ecma-international.org/#sec-date.prototype.tolocalestring
new Date().toLocaleString(); // e.g. "21/11/2016, 08:00:00 AM"
toLocaleTimeString: Implementation dependent, a time in locale format.
https://262.ecma-international.org/#sec-date.prototype.tolocaletimestring
new Date().toLocaleTimeString(); // e.g. "08:00:00 AM"
toString: Generic toString for Date.
https://262.ecma-international.org/#sec-date.prototype.tostring
new Date().toString(); // e.g. "Fri Nov 21 2016 08:00:00 GMT+0100 (W. Europe Standard Time)"
Note: it is possible to generate custom output out of those formatting >
new Date().toISOString().slice(0,10); //return YYYY-MM-DD
Examples snippets:
console.log("1) "+ new Date().toDateString());
console.log("2) "+ new Date().toISOString());
console.log("3) "+ new Date().toJSON());
console.log("4) "+ new Date().toLocaleDateString());
console.log("5) "+ new Date().toLocaleString());
console.log("6) "+ new Date().toLocaleTimeString());
console.log("7) "+ new Date().toString());
console.log("8) "+ new Date().toISOString().slice(0,10));
Specifying the locale for standard functions:
Some of the standard functions listed above are dependent on the locale:
toLocaleDateString()
toLocaleTimeString()
toLocalString()
This is because different cultures make uses of different formats, and express their date or time in different ways.
The function by default will return the format configured on the device it runs, but this can be specified by setting the arguments (ECMA-402).
toLocaleDateString([locales[, options]])
toLocaleTimeString([locales[, options]])
toLocaleString([locales[, options]])
//e.g. toLocaleDateString('ko-KR');
The option second parameter, allow for configuring more specific format inside the selected locale. For instance, the month can be show as full-text or abreviation.
toLocaleString('en-GB', { month: 'short' })
toLocaleString('en-GB', { month: 'long' })
Examples snippets:
console.log("1) "+ new Date().toLocaleString('en-US'));
console.log("2) "+ new Date().toLocaleString('ko-KR'));
console.log("3) "+ new Date().toLocaleString('de-CH'));
console.log("4) "+ new Date().toLocaleString('en-GB', { hour12: false }));
console.log("5) "+ new Date().toLocaleString('en-GB', { hour12: true }));
Some good practices regarding locales:
Most people don't like their dates to appear in a foreigner format, consequently, keep the default locale whenever possible (over setting 'en-US' everywhere).
Implementing conversion from/to UTC can be challenging (considering DST, time-zone not multiple of 1 hour, etc.). Use a well-tested library when possible.
Don't assume the locale correlate to a country: several countries have many of them (Canada, India, etc.)
Avoid detecting the locale through non-standard ways. Here you can read about the multiple pitfalls: detecting the keyboard layout, detecting the locale by the geographic location, etc..
If you are already using jQuery UI in your project you could do it this way:
var formatted = $.datepicker.formatDate("M d, yy", new Date("2014-07-08T09:02:21.377"));
// formatted will be 'Jul 8, 2014'
Some datepicker date format options to play with are available here.
Note (2022-10): toLocaleFormat has been deprecated for some time and was removed from Firefox as of version 58. See toLocaleFormat
I think you can just use the non-standard Date method toLocaleFormat(formatString)
formatString: A format string in the same format expected by the strftime() function in C.
var today = new Date();
today.toLocaleFormat('%d-%b-%Y'); // 30-Dec-2011
References:
toLocaleFormat
strftime
Plain JavaScript is the best pick for small onetimers.
On the other hand, if you need more date stuff, MomentJS is a great solution.
For example:
moment().format('YYYY-MM-DD HH:m:s'); // now() -> 2015-03-24 14:32:20
moment("20111031", "YYYYMMDD").fromNow(); // 3 years ago
moment("20120620", "YYYYMMDD").fromNow(); // 3 years ago
moment().startOf('day').fromNow(); // 11 hours ago
moment().endOf('day').fromNow(); // in 13 hours
In modern browsers (*), you can just do this:
var today = new Date().toLocaleDateString('en-GB', {
day : 'numeric',
month : 'short',
year : 'numeric'
}).split(' ').join('-');
Output if executed today (january 24ᵗʰ, 2016):
'24-Jan-2016'
(*) According to MDN, "modern browsers" means Chrome 24+, Firefox 29+, Internet Explorer 11, Edge 12+, Opera 15+ & Safari nightly build.
Requested format in one line - no libraries and no Date methods, just regex:
var d = (new Date()).toString().replace(/\S+\s(\S+)\s(\d+)\s(\d+)\s.*/,'$2-$1-$3');
// date will be formatted as "14-Oct-2015" (pass any date object in place of 'new Date()')
In my testing, this works reliably in the major browsers (Chrome, Safari, Firefox and IE.) As #RobG pointed out, the output of Date.prototype.toString() is implementation-dependent, so for international or non-browser implementations, just test the output to be sure it works right in your JavaScript engine. You can even add some code to test the string output and make sure it's matching what you expect before you do the regex replace.
Packaged Solution: Luxon or date-fns
If you want to use a one solution to fit all, I recommend using date-fns or Luxon.
Luxon is hosted on the Moment.js website and developed by a Moment.js developer because Moment.js has limitations that the developer wanted to address but couldn't.
To install:
npm install luxon or yarn add luxon (visit link for other installation methods)
Example:
luxon.DateTime.fromISO('2010-08-10').toFormat('yyyy-LLL-dd');
Yields:
10-Aug-2010
Manual Solution
Using similar formatting as Moment.js, Class DateTimeFormatter (Java), and Class SimpleDateFormat (Java), I implemented a comprehensive solution formatDate(date, patternStr) where the code is easy to read and modify. You can display date, time, AM/PM, etc. See code for more examples.
Example:
formatDate(new Date(), 'EEEE, MMMM d, yyyy HH:mm:ss:S')
(formatDate is implemented in the code snippet below)
Yields:
Friday, October 12, 2018 18:11:23:445
Try the code out by clicking "Run code snippet."
Date and Time Patterns
yy = 2-digit year; yyyy = full year
M = digit month; MM = 2-digit month; MMM = short month name; MMMM = full month name
EEEE = full weekday name; EEE = short weekday name
d = digit day; dd = 2-digit day
h = hours am/pm; hh = 2-digit hours am/pm; H = hours; HH = 2-digit hours
m = minutes; mm = 2-digit minutes; aaa = AM/PM
s = seconds; ss = 2-digit seconds
S = miliseconds
var monthNames = [
"January", "February", "March", "April", "May", "June", "July",
"August", "September", "October", "November", "December"
];
var dayOfWeekNames = [
"Sunday", "Monday", "Tuesday",
"Wednesday", "Thursday", "Friday", "Saturday"
];
function formatDate(date, patternStr){
if (!patternStr) {
patternStr = 'M/d/yyyy';
}
var day = date.getDate(),
month = date.getMonth(),
year = date.getFullYear(),
hour = date.getHours(),
minute = date.getMinutes(),
second = date.getSeconds(),
miliseconds = date.getMilliseconds(),
h = hour % 12,
hh = twoDigitPad(h),
HH = twoDigitPad(hour),
mm = twoDigitPad(minute),
ss = twoDigitPad(second),
aaa = hour < 12 ? 'AM' : 'PM',
EEEE = dayOfWeekNames[date.getDay()],
EEE = EEEE.substr(0, 3),
dd = twoDigitPad(day),
M = month + 1,
MM = twoDigitPad(M),
MMMM = monthNames[month],
MMM = MMMM.substr(0, 3),
yyyy = year + "",
yy = yyyy.substr(2, 2)
;
// checks to see if month name will be used
patternStr = patternStr
.replace('hh', hh).replace('h', h)
.replace('HH', HH).replace('H', hour)
.replace('mm', mm).replace('m', minute)
.replace('ss', ss).replace('s', second)
.replace('S', miliseconds)
.replace('dd', dd).replace('d', day)
.replace('EEEE', EEEE).replace('EEE', EEE)
.replace('yyyy', yyyy)
.replace('yy', yy)
.replace('aaa', aaa);
if (patternStr.indexOf('MMM') > -1) {
patternStr = patternStr
.replace('MMMM', MMMM)
.replace('MMM', MMM);
}
else {
patternStr = patternStr
.replace('MM', MM)
.replace('M', M);
}
return patternStr;
}
function twoDigitPad(num) {
return num < 10 ? "0" + num : num;
}
console.log(formatDate(new Date()));
console.log(formatDate(new Date(), 'dd-MMM-yyyy')); //OP's request
console.log(formatDate(new Date(), 'EEEE, MMMM d, yyyy HH:mm:ss.S aaa'));
console.log(formatDate(new Date(), 'EEE, MMM d, yyyy HH:mm'));
console.log(formatDate(new Date(), 'yyyy-MM-dd HH:mm:ss.S'));
console.log(formatDate(new Date(), 'M/dd/yyyy h:mmaaa'));
Thank you #Gerry for bringing up Luxon.
#Sébastien -- alternative all browser support
new Date(parseInt(496407600)*1000).toLocaleDateString('de-DE', {
year: 'numeric',
month: '2-digit',
day: '2-digit'
}).replace(/\./g, '/');
Documentation:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/toLocaleDateString
High-order tagged template literal example based on Date.toLocaleDateString:
const date = new Date(Date.UTC(2020, 4, 2, 3, 23, 16, 738));
const fmt = (dt, lc = "en-US") => (str, ...expr) =>
str.map((str, i) => str + (expr[i]?dt.toLocaleDateString(lc, expr[i]) :'')).join('')
console.log(fmt(date)`${{year: 'numeric'}}-${{month: '2-digit'}}-${{day: '2-digit'}}`);
// expected output: "2020-05-02"
OK, we have got something called Intl which is very useful for formatting a date in JavaScript these days:
Your date as below:
var date = '10/8/2010';
And you change to Date by using new Date() like below:
date = new Date(date);
And now you can format it any way you like using a list of locales like below:
date = new Intl.DateTimeFormat('en-AU').format(date); // Australian date format: "8/10/2010"
date = new Intl.DateTimeFormat('en-US').format(date); // USA date format: "10/8/2010"
date = new Intl.DateTimeFormat('ar-EG').format(date); // Arabic date format: "٨‏/١٠‏/٢٠١٠"
If you exactly want the format you mentioned above, you can do:
date = new Date(Date.UTC(2010, 7, 10, 0, 0, 0));
var options = {year: "numeric", month: "short", day: "numeric"};
date = new Intl.DateTimeFormat("en-AU", options).format(date).replace(/\s/g, '-');
And the result is going to be:
"10-Aug-2010"
For more see the Intl API and Intl.DateTimeFormat documentation.
Using an ECMAScript Edition 6 (ES6/ES2015) string template:
let d = new Date();
let formatted = `${d.getFullYear()}-${d.getMonth() + 1}-${d.getDate()}`;
If you need to change the delimiters:
const delimiter = '/';
let formatted = [d.getFullYear(), d.getMonth() + 1, d.getDate()].join(delimiter);
The Date constructor (and Date.parse()) only accepts one format as a parameter when constructing a date and that is ISO 8601:
// new Date('YYYY-MM-DDTHH:mm:ss.sssZ')
const date = new Date('2017-08-15')
But parsing a from a string is strongly discouraged (MDN recommends against creating date with date strings) due to browser differences and inconsistencies.
The recommended alternative would be building your Date instance directly from the numeric data like this:
new Date(2017, 7, 15) // Month is zero-indexed
That is parsing. Now, to format your date to the string you desire you have several options that are native of the Date object (although I believe none is compliant to the format you require):
date.toString() // 'Wed Jan 23 2019 17:23:42 GMT+0800 (Singapore Standard Time)'
date.toDateString() // 'Wed Jan 23 2019'
date.toLocaleString() // '23/01/2019, 17:23:42'
date.toGMTString() // 'Wed, 23 Jan 2019 09:23:42 GMT'
date.toUTCString() // 'Wed, 23 Jan 2019 09:23:42 GMT'
date.toISOString() // '2019-01-23T09:23:42.079Z'
For other formatting options I'm afraid you'll have to turn to libraries such as Moment.js, day.js and the like.
Credit to Zell Liew from this article for the date formatting tips.
Here's is some code I just wrote to handle the date formatting for a project I'm working on. It mimics the PHP date formatting functionality to suit my needs. Feel free to use it, it's just extending the already existing Date() object. This may not be the most elegant solution but it's working for my needs.
var d = new Date();
d_string = d.format("m/d/Y h:i:s");
/**************************************
* Date class extension
*
*/
// Provide month names
Date.prototype.getMonthName = function(){
var month_names = [
'January',
'February',
'March',
'April',
'May',
'June',
'July',
'August',
'September',
'October',
'November',
'December'
];
return month_names[this.getMonth()];
}
// Provide month abbreviation
Date.prototype.getMonthAbbr = function(){
var month_abbrs = [
'Jan',
'Feb',
'Mar',
'Apr',
'May',
'Jun',
'Jul',
'Aug',
'Sep',
'Oct',
'Nov',
'Dec'
];
return month_abbrs[this.getMonth()];
}
// Provide full day of week name
Date.prototype.getDayFull = function(){
var days_full = [
'Sunday',
'Monday',
'Tuesday',
'Wednesday',
'Thursday',
'Friday',
'Saturday'
];
return days_full[this.getDay()];
};
// Provide full day of week name
Date.prototype.getDayAbbr = function(){
var days_abbr = [
'Sun',
'Mon',
'Tue',
'Wed',
'Thur',
'Fri',
'Sat'
];
return days_abbr[this.getDay()];
};
// Provide the day of year 1-365
Date.prototype.getDayOfYear = function() {
var onejan = new Date(this.getFullYear(),0,1);
return Math.ceil((this - onejan) / 86400000);
};
// Provide the day suffix (st,nd,rd,th)
Date.prototype.getDaySuffix = function() {
var d = this.getDate();
var sfx = ["th","st","nd","rd"];
var val = d%100;
return (sfx[(val-20)%10] || sfx[val] || sfx[0]);
};
// Provide Week of Year
Date.prototype.getWeekOfYear = function() {
var onejan = new Date(this.getFullYear(),0,1);
return Math.ceil((((this - onejan) / 86400000) + onejan.getDay()+1)/7);
}
// Provide if it is a leap year or not
Date.prototype.isLeapYear = function(){
var yr = this.getFullYear();
if ((parseInt(yr)%4) == 0){
if (parseInt(yr)%100 == 0){
if (parseInt(yr)%400 != 0){
return false;
}
if (parseInt(yr)%400 == 0){
return true;
}
}
if (parseInt(yr)%100 != 0){
return true;
}
}
if ((parseInt(yr)%4) != 0){
return false;
}
};
// Provide Number of Days in a given month
Date.prototype.getMonthDayCount = function() {
var month_day_counts = [
31,
this.isLeapYear() ? 29 : 28,
31,
30,
31,
30,
31,
31,
30,
31,
30,
31
];
return month_day_counts[this.getMonth()];
}
// format provided date into this.format format
Date.prototype.format = function(dateFormat){
// break apart format string into array of characters
dateFormat = dateFormat.split("");
var date = this.getDate(),
month = this.getMonth(),
hours = this.getHours(),
minutes = this.getMinutes(),
seconds = this.getSeconds();
// get all date properties ( based on PHP date object functionality )
var date_props = {
d: date < 10 ? '0'+date : date,
D: this.getDayAbbr(),
j: this.getDate(),
l: this.getDayFull(),
S: this.getDaySuffix(),
w: this.getDay(),
z: this.getDayOfYear(),
W: this.getWeekOfYear(),
F: this.getMonthName(),
m: month < 10 ? '0'+(month+1) : month+1,
M: this.getMonthAbbr(),
n: month+1,
t: this.getMonthDayCount(),
L: this.isLeapYear() ? '1' : '0',
Y: this.getFullYear(),
y: this.getFullYear()+''.substring(2,4),
a: hours > 12 ? 'pm' : 'am',
A: hours > 12 ? 'PM' : 'AM',
g: hours % 12 > 0 ? hours % 12 : 12,
G: hours > 0 ? hours : "12",
h: hours % 12 > 0 ? hours % 12 : 12,
H: hours,
i: minutes < 10 ? '0' + minutes : minutes,
s: seconds < 10 ? '0' + seconds : seconds
};
// loop through format array of characters and add matching data else add the format character (:,/, etc.)
var date_string = "";
for(var i=0;i<dateFormat.length;i++){
var f = dateFormat[i];
if(f.match(/[a-zA-Z]/g)){
date_string += date_props[f] ? date_props[f] : '';
} else {
date_string += f;
}
}
return date_string;
};
/*
*
* END - Date class extension
*
************************************/
This may help with the problem:
var d = new Date();
var options = {
day: 'numeric',
month: 'long',
year: 'numeric'
};
console.log(d.toLocaleDateString('en-ZA', options));
A useful and flexible way for formatting the DateTimes in JavaScript is Intl.DateTimeFormat:
var date = new Date();
var options = { year: 'numeric', month: 'short', day: '2-digit'};
var _resultDate = new Intl.DateTimeFormat('en-GB', options).format(date);
// The _resultDate is: "12 Oct 2017"
// Replace all spaces with - and then log it.
console.log(_resultDate.replace(/ /g,'-'));
Result Is: "12-Oct-2017"
The date and time formats can be customized using the options argument.
The Intl.DateTimeFormat object is a constructor for objects that enable language sensitive date and time formatting.
Syntax
new Intl.DateTimeFormat([locales[, options]])
Intl.DateTimeFormat.call(this[, locales[, options]])
Parameters
locales
Optional. A string with a BCP 47 language tag, or an array of such strings. For the general form and interpretation of the locales argument, see the Intl page. The following Unicode extension keys are allowed:
nu
Numbering system. Possible values include: "arab", "arabext", "bali", "beng", "deva", "fullwide", "gujr", "guru", "hanidec", "khmr", "knda", "laoo", "latn", "limb", "mlym", "mong", "mymr", "orya", "tamldec", "telu", "thai", "tibt".
ca
Calendar. Possible values include: "buddhist", "chinese", "coptic", "ethioaa", "ethiopic", "gregory", "hebrew", "indian", "islamic", "islamicc", "iso8601", "japanese", "persian", "roc".
Options
Optional. An object with some or all of the following properties:
localeMatcher
The locale matching algorithm to use. Possible values are "lookup" and "best fit"; the default is "best fit". For information about this option, see the Intl page.
timeZone
The time zone to use. The only value implementations must recognize is "UTC"; the default is the runtime's default time zone. Implementations may also recognize the time zone names of the IANA time zone database, such as "Asia/Shanghai", "Asia/Kolkata", "America/New_York".
hour12
Whether to use 12-hour time (as opposed to 24-hour time). Possible values are true and false; the default is locale dependent.
formatMatcher
The format matching algorithm to use. Possible values are "basic" and "best fit"; the default is "best fit". See the following paragraphs for information about the use of this property.
The following properties describe the date-time components to use in formatted output and their desired representations. Implementations are required to support at least the following subsets:
weekday, year, month, day, hour, minute, second
weekday, year, month, day
year, month, day
year, month
month, day
hour, minute, second
hour, minute
Implementations may support other subsets, and requests will be negotiated against all available subset-representation combinations to find the best match. Two algorithms are available for this negotiation and selected by the formatMatcher property: A fully specified "basic" algorithm and an implementation dependent "best fit" algorithm.
weekday
The representation of the weekday. Possible values are "narrow", "short", "long".
era
The representation of the era. Possible values are "narrow", "short", "long".
year
The representation of the year. Possible values are "numeric", "2-digit".
month
The representation of the month. Possible values are "numeric", "2-digit", "narrow", "short", "long".
day
The representation of the day. Possible values are "numeric", "2-digit".
hour
The representation of the hour. Possible values are "numeric", "2-digit".
minute
The representation of the minute. Possible values are "numeric", "2-digit".
second
The representation of the second. Possible values are "numeric", "2-digit".
timeZoneName
The representation of the time zone name. Possible values are "short", "long".
The default value for each date-time component property is undefined, but if all component properties are undefined, then the year, month and day are assumed to be "numeric".
Check Online
More Details
A JavaScript solution without using any external libraries:
var now = new Date()
months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']
var formattedDate = now.getDate() + "-" + months[now.getMonth()] + "-" + now.getFullYear()
alert(formattedDate)
new Date().toLocaleDateString()
// "3/21/2018"
More documentation at developer.mozilla.org
We have lots of solutions for this, but I think the best of them is Moment.js. So I personally suggest to use Moment.js for date and time operations.
console.log(moment().format('DD-MMM-YYYY'));
<script src="//cdnjs.cloudflare.com/ajax/libs/moment.js/2.14.1/moment.min.js"></script>
If you are using jQuery UI in your code, there is an inbuilt function called formatDate(). I am using it this way to format today's date:
var testdate = Date();
testdate = $.datepicker.formatDate( "d-M-yy",new Date(testdate));
alert(testdate);
You can see many other examples of formatting date in the jQuery UI documentation.
This is how I implemented for my npm plugins
var monthNames = [
"January", "February", "March",
"April", "May", "June", "July",
"August", "September", "October",
"November", "December"
];
var Days = [
"Sunday", "Monday", "Tuesday", "Wednesday",
"Thursday", "Friday", "Saturday"
];
var formatDate = function(dt,format){
format = format.replace('ss', pad(dt.getSeconds(),2));
format = format.replace('s', dt.getSeconds());
format = format.replace('dd', pad(dt.getDate(),2));
format = format.replace('d', dt.getDate());
format = format.replace('mm', pad(dt.getMinutes(),2));
format = format.replace('m', dt.getMinutes());
format = format.replace('MMMM', monthNames[dt.getMonth()]);
format = format.replace('MMM', monthNames[dt.getMonth()].substring(0,3));
format = format.replace('MM', pad(dt.getMonth()+1,2));
format = format.replace(/M(?![ao])/, dt.getMonth()+1);
format = format.replace('DD', Days[dt.getDay()]);
format = format.replace(/D(?!e)/, Days[dt.getDay()].substring(0,3));
format = format.replace('yyyy', dt.getFullYear());
format = format.replace('YYYY', dt.getFullYear());
format = format.replace('yy', (dt.getFullYear()+"").substring(2));
format = format.replace('YY', (dt.getFullYear()+"").substring(2));
format = format.replace('HH', pad(dt.getHours(),2));
format = format.replace('H', dt.getHours());
return format;
}
pad = function(n, width, z) {
z = z || '0';
n = n + '';
return n.length >= width ? n : new Array(width - n.length + 1).join(z) + n;
}
You should have a look at DayJs It's a remake of momentJs but modular architecture oriented so lighter.
Fast 2kB alternative to Moment.js with the same modern API
Day.js is a minimalist JavaScript library that parses, validates, manipulates, and displays dates and times for modern browsers with a largely Moment.js-compatible API. If you use Moment.js, you already know how to use Day.js.
var date = Date.now();
const formatedDate = dayjs(date).format("YYYY-MM-DD")
console.log(formatedDate);
<script src="https://cdnjs.cloudflare.com/ajax/libs/dayjs/1.8.16/dayjs.min.js" crossorigin="anonymous"></script>
var today = new Date();
var formattedToday = today.toLocaleDateString() + ' ' + today.toLocaleTimeString();
Inspired by JD Smith's marvellous regular expression solution, I suddenly had this head-splitting idea:
var D = Date().toString().split(" ");
console.log(D[2] + "-" + D[1] + "-" + D[3]);
For any one looking for a really simple ES6 solution to copy, paste and adopt:
const dateToString = d => `${d.getFullYear()}-${('00' + (d.getMonth() + 1)).slice(-2)}-${('00' + d.getDate()).slice(-2)}`
// how to use:
const myDate = new Date(Date.parse('04 Dec 1995 00:12:00 GMT'))
console.log(dateToString(myDate)) // 1995-12-04
As of 2019, it looks like you can get toLocaleDateString to return only certain parts and then you can join them as you wish:
var date = new Date();
console.log(date.toLocaleDateString("en-US", { day: 'numeric' })
+ "-"+ date.toLocaleDateString("en-US", { month: 'short' })
+ "-" + date.toLocaleDateString("en-US", { year: 'numeric' }) );
> 16-Nov-2019
console.log(date.toLocaleDateString("en-US", { month: 'long' })
+ " " + date.toLocaleDateString("en-US", { day: 'numeric' })
+ ", " + date.toLocaleDateString("en-US", { year: 'numeric' }) );
> November 16, 2019
It works same in Internet Explorer 11, Firefox, and Chrome (Chrome 80.x shows 12 hours format when en-UK selected).
const d = new Date('2010/08/05 23:45') // 26.3.2020
const dtfUK = new Intl.DateTimeFormat('UK', { year: 'numeric', month: '2-digit', day: '2-digit',
hour: '2-digit',minute: '2-digit', second: '2-digit' }); //
const dtfUS = new Intl.DateTimeFormat('en', { year: 'numeric', month: '2-digit', day: '2-digit',
hour: '2-digit',minute: '2-digit', second: '2-digit' }); //
console.log(dtfUS.format(d)); // 08/05/2010 11:45:00 PM
console.log(dtfUK.format(d)); // 05.08.2010 23:45:00
/* node.js:
08/05/2010, 11:45:00 PM
2010-08-05 23:45:00
*/
What about something more general?
var d = new Date('2010-08-10T10:34:56.789Z');
var str = d.toDateString() + // Tue Aug 10 2010
' ' + d.toTimeString().split(' ')[0] + // 12:34:56, GMT+0x00 (GMT+0x:00)
' ' + (d.getMonth() + 101) + // 108
' ' + d.getMilliseconds(); // 789
console.log(str); // Tue Aug 10 2010 12:34:56 108 789
console.log(// $1 Tue $2 Aug $3 11 $4 2020 $5 12 $6 34 $7 56 $8 108 $9 789
str.replace(/(\S{3}) (\S{3}) (\d{1,2}) (\d{4}) (\d{2}):(\d{2}):(\d{2}) 1(\d{2}) (\d{1,3})/, '$3-$2-$4 $5:$6.$9 ($1)')
); // 10-Aug-2010 12:34.789 (Tue)
/*
$1: Tue Week Day string
$2: Aug Month short text
$3: 11 Day
$4: 2010 Year
$5: 12 Hour
$6: 34 Minute
$7: 56 Seconds
$8: 08 Month
$9: 789 Milliseconds
*/
Or for example 1-line IIFE "library" ;-)
console.log(
(function (frm, d) { return [d.toDateString(), d.toTimeString().split(' ')[0], (d.getMonth() + 101), d.getMilliseconds()].join(' ').replace(/(\S{3}) (\S{3}) (\d{1,2}) (\d{4}) (\d{2}):(\d{2}):(\d{2}) 1(\d{2}) (\d{1,3})/, frm); })
('$4/$8/$3 $5:$6 ($1)', new Date())
);
You can remove useless parts and / or change indexes if you do not need them.

Google Sheets: Session.getEffectiveUser() returns wrong values... twice

So what I'm trying to do is to log the edits of a spreadsheet on a corresponding column.
http://i.imgur.com/P8qrJOe.gif
The last column is the autogenerated text from the embedded script.
Here's the code:
function triggeredEdit () {
// set sheet variables
var activeSheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
var activeRange = activeSheet.getActiveRange();
// last updated
// LAST EDITED FOR SCRIPTS (check M3 if "Latest Row Modifications")
if (activeSheet.getRange("M3").getValue() == "Latest Row Modifications") {
for (var i = 1; i <= activeRange.getHeight(); i++) {
// modified TL column
if (activeRange.getCell(i, 1).getRow() > 4 && activeRange.getColumn() >= 6 && activeRange.getLastColumn() <= 6) {
activeSheet.getRange(activeRange.getCell(i, 1).getRow(), 13)
.setValue(Session.getEffectiveUser() + "\n" + Utilities.formatDate(new Date(), "GMT", "dd MMM YY, HH:mm:ss"));
}
// modified TLC column
else if (activeRange.getCell(i, 1).getRow() > 4 && activeRange.getColumn() >= 8 && activeRange.getLastColumn() <= 8) {
activeSheet.getRange(activeRange.getCell(i, 1).getRow(), 14)
.setValue(Session.getEffectiveUser() + "\n" + Utilities.formatDate(new Date(), "GMT", "dd MMM YY, HH:mm:ss"));
}
// modified edit column
else if (activeRange.getCell(i, 1).getRow() > 4 && activeRange.getColumn() >= 10 && activeRange.getLastColumn() <= 10) {
activeSheet.getRange(activeRange.getCell(i, 1).getRow(), 15)
.setValue(Session.getEffectiveUser() + "\n" + Utilities.formatDate(new Date(), "GMT", "dd MMM YY, HH:mm:ss"));
}
// modified QC column
else if (activeRange.getCell(i, 1).getRow() > 4 && activeRange.getColumn() >= 11 && activeRange.getLastColumn() <= 11) {
activeSheet.getRange(activeRange.getCell(i, 1).getRow(), 16)
.setValue(Session.getEffectiveUser() + "\n" + Utilities.formatDate(new Date(), "GMT", "dd MMM YY, HH:mm:ss"));
}
}
}
}`
The function triggeredEdit is run through a project trigger, which is also dynamically created in another function. As you can see in the gif, it seems like the triggeredEdit is called twice (since it changes twice). What's worse is that the correct email to be displayed is the first one, but then it gets replaced with the wrong one.
How do I go around fixing this? I'm quite stuck with this problem.
From what you explained in the comments It seems that you have 2 triggers on that spreadsheet that work simultaneously.
When you call Session.getEffectiveUser in a function triggered by onEdit, it returns the email of the user that installed the trigger. If you want to get the user at the keyboard then use Session.getActiveUser. Note that this will work only if you are in a domain, nothing is returned in normal gmail accounts.
To test that I used this small code :
function triggeredEdit () {
var activeSheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
var activeRange = activeSheet.getActiveRange();
Logger.log('xx');
activeSheet.getRange(1, 1).setValue('effective = '+Session.getEffectiveUser() + "\n" + Utilities.formatDate(new Date(), "GMT", "dd MMM YY, HH:mm:ss"));
activeSheet.getRange(1, 3).setValue('active = '+Session.getActiveUser() + "\n" + Utilities.formatDate(new Date(), "GMT", "dd MMM YY, HH:mm:ss"));
}
and here is what I get when I edit a cell (Serge created the trigger and Lambda was the user at the keyboard.
:
If I use the spreadsheet with my gmail account then I get this result below : no value as activeUser
and, finally, if I create a second trigger with my gmail account I have a double instance like yours.(I didn't capture the gif, sorry ;)
All this seems quite logical after all when I refer to the documentation about script authorization : triggers run under the authority of the user that creates it.
The soluion in your case will probably to change the way the triggers are created to avoid that anyone can do it... or try to filter execution in some way but I'm not sure that can be done.

Working with Dates in Google Apps Script

What I am trying to do here is this - I want to give index to only the workdays in each week.
So, if in a week, Monday and Wednesday are holidays, then Tuesday should get 1, Thursday should get 2, Friday should get the index 3. Otherwise, in a normal week without any holidays, Monday should get 1, Tuesday 2, Wednesday 3, and so on ...
Here is the code I have written (I haven't coded in years now, so please pardon the crude approach)
Sheet 'Holidays' contains a list of holidays in the column B starting from row 2
Variable date is the date for which I want to find out the index for
Variable dayOfTheWeek is the number of day of 'date' counted from last Sunday, so if date is a Monday, dayOfTheWeek is 1; if date is Tuesday, dayOfTheWeek is 2, and so on ...
function indexOfWorkdayOfTheWeek (date, dayOfTheWeek, lastSundayDate)
{
var activeSheet = SpreadsheetApp.getActiveSpreadsheet();
var activeCell = activeSheet.getActiveRange();
var activeRow = activeCell.getRowIndex();
var activeColumn = activeCell.getColumn();
var count = 1;
for (var j = 1; j < dayOfTheWeek; j++)
{
var date2 = lastSundayDate.valueOf() + j*86400;
Logger.log('Date ' + j + ' is:' + date2);
Logger.log('Last Sunday is:' + lastSundayDate);
if (holidayOrNot(date2) == true)
{
}
else
{
count = count + 1;
}
}
return count;
}
function holidayOrNot(date2)
{
var holidaysSheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Holidays');
var listOfHolidays = holidaysSheet.getSheetValues(2, 2, 95, 1);
var isDateMatch = false;
for (var k = 0; k < 90; k++)
{
if (date2 == listOfHolidays[k].valueOf())
{
isDateMatch = true;
break;
}
else
{
continue;
}
}
return isDateMatch;
}
I think the problem is two-fold here:
The date2 calculation isn't working for some reason (var date2 = lastSundayDate.valueOf() + j*86400;)
The function holidayOrNot is returning false, no matter what, even if it encounters a holiday ... the condition date2 == listOfHolidays[k] isn't working for some reason...
Help would be appreciated!
maybe this method below could help you in your calculations, it returns an integer corresponding to the day of the year so if you apply this to your holidays days and compare to the days of interest it could be a good way to find matches.
here it is, just add these lines outside of any function in your script (so you can use it anywhere) then use it like this :
var d = new Date().getDOY();
Logger.log(d)
Here the method :
Date.prototype.getDOY = function() {
var onejan = new Date(this.getFullYear(),0,1);
return Math.ceil((this - onejan) / 86400000);
}
Assuming that lastSundayDate is being passed around correctly, I see a glaring problem:
lastSundayDate.valueOf().
valueOf() on Date objects returns the primitive value... it looks like you're going for adding a day to the date (86400 seconds * j)? I can't tell what the logic is supposed to be here. But the valueOf() date2 is definitely giving you an integer something like: 1384628769399 (see here).
What you really want to accomplish is something like Date.getDay(), or something similar so that you can add hours, days, etc. to the original Date. This is likely the source of all your problems.
What you can do is read the Mozilla Developer Network documentation on Date objects to see all of the functions on Dates and their uses. You can greatly simplify what you're trying to do by using these functions, instead of doing abstract operations like j * 86400.
It should also be noted that you can do simple operations such as the following, to add 4 hours to the current Date (time):
var myDate = new Date();
Logger.log(myDate); // ~ console.write
var laterDate = new Date(myDate.setHours(myDate.getHours() + 4));
Logger.log(laterDate); // ~ console.write
which gives the following:
[13-11-16 14:13:38:947 EST] Sat Nov 16 14:13:38 GMT-05:00 2013
[13-11-16 14:13:38:954 EST] Sat Nov 16 18:13:38 GMT-05:00 2013
Working with dates can be tricky - but it's always best to use the simplest methods that are available, which are built into the Date objects themselves. There are also numerous other libraries that provide extended functionality for Dates such as Date js.
If you're still running into your problem after attempting to try using methods I displayed above, please run your script and post both the Execution Transcript and the content of the Logger so that I can help you narrow down the issue :)