I know with a java calendar, you can go back to a previous date, but how do I do that with a javascript date? Lets say I want to go backwards three months, how do I do that? I'm assuming that there has to be some logic to do that, and not just do a setMonth(), since rolling back 3 months may take you back to the previous year, and so the year needs to be updated too.
Why don't you use one of the date libraries such as date.js
http://datejs.com
Date.add(-3).month();
Any rollover date manipulation to a new period (ie new year, month, week, day, etc) is handled automatically
var d = new Date();
-> Tue Oct 01 2013 14:12:21 GMT+1000 (EST)
d.setMonth(d.getMonth() - 3);
-> Mon Jul 01 2013 14:13:43 GMT+1000 (EST)
d.setMonth(d.getMonth() - 10);
-> Sat Sep 01 2012 14:14:31 GMT+1000 (EST)
Using get month you can get the value from 0-11,so if you want to go back to 3 months just chekc if month no. is greater than 3 ,if it is greater than 3 no need to change the year,else decrement the year by 1
MomentJS is a JavaScript library that is great for date manipulation. Using MomentJS, you could do something like:
// Subtract 3 months from the current moment (now)
moment().subtract('months', 3);
If you must use the JavaScript Date object, you can use the setMonth() but it can be unreliable (as you mentioned). As an example:
// Get the next and previous month from now (first day of the month)
var now = new Date();
var futureMonth = now.setMonth(now.getMonth() + 1, 1);
var pastMonth = now.setMonth(now.getMonth() - 1, 1);
Note that you need to specify the second parameter to set the day to 1. This will prevent the "next" month from skipping a month (e.g. adding a month to January 31, 2014 will result in March 3rd, 2014 if you omit the second parameter).
No, you don't need to worry about roll backing the year. Just set the month and remaining it with JS rendering machine.
var date = new Date();
date.setMonth(-10); //+ increase the month or - decrease
alert(date);
JSFiddle
Related
I'm using date-fns library. And I have a specific requirement.
Let's say I have an event every Saturday at 7am UTC.
If there are 24 hours left in the event, I want to say 'Coming Soon'. If more than 24 hours are left, I want to show the calendar days targeting 7am UTC of the next Saturday.
As soon, as it is past 7am UTC of the Saturday, it should show calendar days left to next Saturday 7am UTC.
I'm not sure how I can achieve this.
If it was to check Saturday irrespective of time, I could just use isSaturday(), but that's not the case, I need to target the specific UTC time on the next Saturday (7am UTC).
UPDATE: The main problem I'm facing is to define the target as the next Saturday 7am UTC. Once the target is defined, then I can use differenceInCalendarDays() to get the days left.
Can you please help?
To answer the "main problem" is quite simple without using date-fns - it may be simpler using date-fns but I don't know date-fns - so here is plain ol' javascript Date object solution
function nextSaturday(d = new Date) {
const next = new Date(d);
next.setUTCDate(next.getUTCDate() + (7 - (next.getUTCDay() + 1)) % 7);
next.setUTCHours(7, 0, 0, 0);
if (next <= d) { // if it's currently saturday after 7AM UTC, add 7 days
next.setUTCDate(next.getUTCDate() + 7);
}
return next;
}
console.log(nextSaturday(new Date).toUTCString());
// for future readers
// Saturday March 5th 2022 is a Satruday
// at 06:59:59.999 - next should be Sat, 05 Mar 2022 07:00:00 GMT
console.log(nextSaturday(new Date('2022-03-05T06:59:59.999Z')).toUTCString());
// at 07:00:00 - next should be Sat, 05 Mar 2022 07:00:00 GMT
console.log(nextSaturday(new Date('2022-03-05T07:00:00.000Z')).toUTCString());
console.log(nextSaturday(new Date('2022-05-15T07:00:00.000Z')).toUTCString());
Made the function so calling nextSaturday without an argument will use current date - but if you pass in a date it'll use that - this is just for verifying that it works
with the help of new Date() how i can achieve this.
my code :
var temp =new Date("October 13, 2014 22:34:17");
console.log(new Date(temp-1));
requirement:
before: Aug 4, 2014 11:59pm (EDT)
after: Aug 3, 2014 11:59pm (EDT)
You need to specify what amount of time you are subtracting. At the moment its 1, but 1 what? Therefore, try getting the days using getDate() and then subtract from that and then set the date with setDate().
E.g.
var temp = new Date("October 13, 2014 22:34:17");
temp.setDate(temp.getDate()-1);
The simple answer is that you want to subtract a days worth of milliseconds from it. So something like the following
var today = new Date('October 13, 2014 22:34:17');
var yesterday = new Date(today.getTime() - (24*60*60*1000));
console.log(yesterday);
The problem with this is that this really gives you 24 hours earlier, which isn't always a day earlier due to things such as changes in Daylight Saving Time. If this is what you want, fine. If you want something more sophisticated, check out moment.js
You can simply subtract one day from today date like this:
var yesterday = new Date(new Date().setDate(new Date().getDate()-1));
Simply subtract from one date to the next Date. You can do so by clicking on this link for subtracting the date. following this url.
Tricky one to explain this but could be an interesting challenge to find the simplest method, I spent several hours yesterday trying to refactor a .NET C# bit of code but did not come up with anything elegant.
So anyone with a good JavaScript, Math, Date problem solving head might have a good light bulb moment!!
I basically need to be able to generate the start (and end) for a date range. i.e. Last 12 months, Last 6 months, Last 24 months etc.
BUT it's not just a simple CurrentDate subtract year type problem.
We use period ranges to visualise the data we are presenting, i.e. monthly, bimonthly, quarterly, half yearly. But we also have a reference month where the period ranges should be based from, i.e. the period range should always start on July. So you always get a clean cut quarter starting from 1 July and going to 30 Sept, no matter what the current date etc.
With that in mind we always want the start date to take this reference into account, the reference will always just be a month so all start dates will be the 1st of a month. The end date will be the last day of a month and FYI will most of the time actually be after the current date, because we want the final period range to include today's date.
So we need a function which you can pass in (I have included sample values):
currentDate = 21 NOV 2012
dateRangeInMonths = 12 (Year)
periodRangeInMonths = 3 (Quarterly)
periodRangeReferenceStartMonth = 7 (July)
The answer for the above would be the following because it would fit the following ranges:
01 JAN 2012 - 31 MAR 2012
01 APR 2012 - 31 JUN 2012
01 JUL 2012 - 30 SEP 2012
01 OCT 2012 - 31 DEC 2012
returns startDate = 01 JAN 2012
returns endDate = 31 DEC 2012
So this is correct because we have the period starts in line with the reference month of July, we are including today's date in the final range.
It also needs to be good for overlapping into previous years obviously. So another example could be:
currentDate = 10 FEB 2012
dateRangeInMonths = 6 (Half Year)
periodRangeInMonths = 2 (Bimonthly)
periodRangeReferenceStartMonth = 1 (Jan)
Answer:
01 SEP 2011 - 31 OCT 2011
01 NOV 2011 - 31 DEC 2011
01 JAN 2012 - 29 FEB 2012
returns startDate = 01 SEP 2011
returns endDate = 29 FEB 2012
Also if its of any help this is a c# bit of code that does what I want but is far from elegant, and relies on looping back in time etc. So you might want to just ignore it haha.
if (this.PeriodRangeInMonths > 1)
{
this.StartDate = new DateTime(DateTime.Now.Year, this.PeriodRangeReferenceStartMonth, 1).AddMonths(0 - this.DateRangeInMonths);
var temp = DateTime.Now.AddMonths(0 - this.DateRangeInMonths).AddMonths(this.PeriodRangeInMonths);
while (this.StartDate.AddMonths(this.PeriodRangeInMonths) < temp)
this.StartDate = this.StartDate.AddMonths(this.PeriodRangeInMonths);
}
else this.StartDate = new DateTime(DateTime.Now.AddMonths(1).Year, DateTime.Now.AddMonths(1).Month, 1).AddMonths(0 - this.DateRangeInMonths);
this.EndDate = this.StartDate.AddMonths(this.DateRangeInMonths);
I'm also open to using any 3rd party jquery libraries that might help, with math or date functions etc.
I think I've got the maths down: http://jsfiddle.net/GNn7y/1/
Here's a javascript solution, but this shouldn't be too hard to adapt to another language.
function getDateRange(refDate, monthRange, periodMonths, startMonth) {
var datePeriodOffset = Math.floor((refDate.getMonth() - startMonth)/periodMonths);
var endMonth = startMonth + datePeriodOffset*periodMonths - 1 + periodMonths;
var endDate = new Date(refDate.getFullYear(), endMonth+1, 0); // the 0 sets it to the last day of the previous month (endMonth)
var startDate = new Date(endDate.getFullYear(), endDate.getMonth() - monthRange + 1, 1);
return {
start : startDate,
end : endDate
};
}
I'm curious if anyone has any good solutions for accurately building dates prior to the year 1000 A.D. - particularly the years 1 - 100 AD.
For example, if I want to build a date for the start of the 1st millenium, I can't just do...
new Date(Date.UTC(1,0,1,0,0,0,0));
because it tries to be "smart" and assume that 1 is 1901, which gives me...
Sun Dec 31 1900 18:00:00 GMT-0600 (CST)
The same thing goes for the year 99...
new Date(Date.UTC(99,0,1,0,0,0,0));
which becomes
Thu Dec 31 1998 18:00:00 GMT-0600 (CST)
Thoughts?
i prefer:
var d = new Date(Date.UTC(year, month, day, hour, min, sec, 0));
d.setUTCFullYear(year);
this always works for all supported year values.
the setUTCFullYear() call fixes JavaScript's intentional bug if you ask me.
Have you tried using the setUTC... functions on a date object after its creation?
setUTCDate()
setUTCFullYear()
setUTCMonth()
setUTCHours()
setUTCMinutes()
setUTCSeconds()
Here is the basic solution I came up with. If a date is prior to year 1000, I just add a 1000 to it while constructing the date, then use setUTCFullYear() afterwards.
if (year >= 0 && year < 1000) {
var d = new Date(Date.UTC(year + 1000,mon,day,hour,min,sec,0));
d.setUTCFullYear(d.getFullYear() - 1000);
return d;
}
1000 may be overkill since I was only having problems with pre-100 dates... but, whatever.
You have to set the year again, like setFullYear() or setUTCFullYear().
The Date can store 285 616 years before and after 1. 1. 1970.
var d = new Date( 0000, 1, 29 ); // Thu Mar 01 1900 00:00:00 GMT+0100
d.setFullYear(-0004); // Wed Mar 01 -0004 00:00:00 GMT+0057
d.setFullYear( 0000, 1, 29 ); // Tue Feb 29 0000 00:00:00 GMT+0057
// Yes, year zero was a leap year
Explanation:
new Date( year [4-digit number, 0–99 map to 1900–1999], month [0-11], day [def. 1], hours, minutes, seconds, milisecs ); is same like Date.UTC but in local timezone.
hours, minutes and seconds will be automatically filled with zeros.
the year lower than 1900 is converted to 1900 by default.
the year 1900 is not a leap year, so it is shifted to next closest day 1. Mar.
so, we have to set the year to zero 0000 again (year always must be min. 4-digit in this case), month and day. We use setFullYear() method with optional parameters for month and day; then if the year will be a leap year, it won’t be shifted.
It's exactly what Date.UTC and the Date constructor function (called with numbers as arguments) are supposed to do. A simple workaround is to use Date.parse, which will not apply any corrections
new Date(Date.parse('0001-01-04'));
new Date(Date.parse('0001-01-04T18:00:00Z'));
Make some arbitrary date d and call d.setUTCFullYear(myDate). This seems to be working for me in Chrome's console.
Others have provided hints at a fix. The javascript date object was copied from Java, so has all its bugs too. There is not much point to Gregorian dates before 1582 anyway since before that various other calendars were in use.
I'm in javascript, running this in the console
d = new Date();
d.setMonth(1);
d.setFullYear(2009);
d.setDate(15);
d.toString();
outputs this:
"Sun Mar 15 2009 18:05:46 GMT-0400 (EDT)"
Why would this be happening? It seems like a browser bug.
That's because when you initialize a new Date, it comes with today's date, so today is Oct 30 2008, then you set the month to February, so there is no February 30, so set first the day, then the month, and then the year:
d = new Date();
d.setDate(15);
d.setMonth(1);
d.setFullYear(2009);
But as #Jason W, says it's better to use the Date constructor:
new Date(year, month, date [, hour, minute, second, millisecond ]);
It's probably best to construct a Date object in one step to avoid the Date object being in an ambiguous or invalid state:
d = new Date(2009, 1, 15);
d = new Date();
d.setDate(15);
d.setMonth(1);
d.setFullYear(2009);
d.toString();
This works.
After a bunch of testing in FF3 on XP with Firebug, here are the things I can tell you
Calling Date.setDate() after calling Date.setMonth() will generate this odd behavior.
Date.setMonth() forces the timezone to be CST (or, some non DST-aware zone)
Date.setDate() forces the timezone to be CDT (or, some DST-aware zone)
So, there's definitely something wonky going on with setMonth() and setDate() in respect to the timezone.
The only solution I can offer is this: Set the date before you set the month.
This will work generally to avoid the rollover behavior of the javascript Date API:
d.setDate(1);
d.setFullYear(year);
d.setMonth(month);
d.setDate(day);
Given that year + month + day are in a "valid" combination, e.g. taken from another Date object using getFullYear(), getMonth(), getDate().
The important parts are:
starting with setDate(1) to avoid possible rollover when the current date value is 29, 30 or 31
call setMonth(month) before setDate(day) to avoid the same rollover in case the current month value is "problematic" (because then the initial setDate(1) would be without effect)