admin管理员组文章数量:1134247
I'm writing an equipment rental application where clients are charged a fee for renting equipment based on the duration (in days) of the rental. So, basically, (daily fee * number of days) = total charge.
For instant feedback on the client side, I'm trying to use Javascript to figure out the difference in two calendar dates. I've searched around, but nothing I've found is quite what I'm looking for. Most solutions I've seen are of the form:
function dateDiff1(startDate, endDate) {
return ((endDate.getTime() - startDate.getTime()) / 1000*60*60*24);
}
My problem is that equipment can be checked out and returned at any time of day during those two dates with no additional charge. The above code is calculating the number of 24 hour periods between the two dates, when I'm really interested in the number of calendar days.
For example, if someone checked out equipment at 6am on July 6th and returned it at 10pm on July 7th, the above code would calculate that more than one 24 hour period had passed, and would return 2. The desired result is 1, since only one calendar date has elapsed (i.e. the 6th to the 7th).
The closest solution I've found is this function:
function dateDiff2(startDate, endDate) {
return endDate.getDate() - startDate.getDate();
}
which does exactly what I want, as long as the two dates are within the same month. However, since getDate() only returns the day of month (i.e. 1-31), it doesn't work when the dates span multiple months (e.g. July 31 to August 1 is 1 day, but the above calcuates 1 - 31, or -29).
On the backend, in PHP, I'm using gregoriantojd(), which seems to work just fine (see this post for an example). I just can't find an equivalent solution in Javascript.
Anyone have any ideas?
I'm writing an equipment rental application where clients are charged a fee for renting equipment based on the duration (in days) of the rental. So, basically, (daily fee * number of days) = total charge.
For instant feedback on the client side, I'm trying to use Javascript to figure out the difference in two calendar dates. I've searched around, but nothing I've found is quite what I'm looking for. Most solutions I've seen are of the form:
function dateDiff1(startDate, endDate) {
return ((endDate.getTime() - startDate.getTime()) / 1000*60*60*24);
}
My problem is that equipment can be checked out and returned at any time of day during those two dates with no additional charge. The above code is calculating the number of 24 hour periods between the two dates, when I'm really interested in the number of calendar days.
For example, if someone checked out equipment at 6am on July 6th and returned it at 10pm on July 7th, the above code would calculate that more than one 24 hour period had passed, and would return 2. The desired result is 1, since only one calendar date has elapsed (i.e. the 6th to the 7th).
The closest solution I've found is this function:
function dateDiff2(startDate, endDate) {
return endDate.getDate() - startDate.getDate();
}
which does exactly what I want, as long as the two dates are within the same month. However, since getDate() only returns the day of month (i.e. 1-31), it doesn't work when the dates span multiple months (e.g. July 31 to August 1 is 1 day, but the above calcuates 1 - 31, or -29).
On the backend, in PHP, I'm using gregoriantojd(), which seems to work just fine (see this post for an example). I just can't find an equivalent solution in Javascript.
Anyone have any ideas?
Share Improve this question asked Jun 24, 2009 at 6:44 AlanAlan 1,1981 gold badge9 silver badges17 bronze badges 1 |15 Answers
Reset to default 57If you want whole days for your student camera rental example ...
function daysBetween(first, second) {
// Copy date parts of the timestamps, discarding the time parts.
var one = new Date(first.getFullYear(), first.getMonth(), first.getDate());
var two = new Date(second.getFullYear(), second.getMonth(), second.getDate());
// Do the math.
var millisecondsPerDay = 1000 * 60 * 60 * 24;
var millisBetween = two.getTime() - one.getTime();
var days = millisBetween / millisecondsPerDay;
// Round down.
return Math.floor(days);
}
I just had this problem and solved it after finding this question, so I came back to post this. This will get the total days regardless of time. And DST doesn't mess it up:
date1 = Date.UTC(date1.getFullYear(), date1.getMonth(), date1.getDate());
date2 = Date.UTC(date2.getFullYear(), date2.getMonth(), date2.getDate());
var ms = Math.abs(date1-date2);
return Math.floor(ms/1000/60/60/24); //floor should be unnecessary, but just in case
The trick is converting to a UTC date that doesn't even know about the times of the original dates.
What I would do is set the two date's times to the same time. For example, set endDate's time to 12:00am and startDate's time to 12:00 am also. Then get the difference between them.
On a side note, since I too am in the rental equipment software industry, it seems like you're losing rental revenue by not counting the hours. Per your example if someone picked up the equipment on July 6th at 6am and returned it on july 7th at 10pm. They had two full days to use the equipment and possibly incur an excess meter charge too...
There is a bug in the given solutions!
This applies to date differences where the time is disregarded AND you want an integer result, that is, whole number of days.
In many of the examples above we see Math.floor other instances I've seen Math.ceil other places as well. These are done to round the result to an integer number of days. The problem is daylight savings time will give a wrong result in the fall using Math.ceil--Your result will be one day too large or in the spring if you use Math.floor you will be off by one day too few. Just use Math.round because 1 hour either way is not going to skew the result.
function dateDiff(dateEarlier, dateLater) {
var one_day=1000*60*60*24
return ( Math.round((dateLater.getTime()-dateEarlier.getTime())/one_day) );
}
I would also suggest having a look at the incredible moment.js library. It has a versatile diff
function, which you can use to solve the above example as follows:
function is_same_date(startDate, endDate) {
var startMoment = moment(startDate).clone().startOf('day'),
endMoment = moment(endDate).clone().startOf('day');
return startMoment.diff(endMoment, 'days') == 0;
}
Here are some examples using moment.js
diff:
> d1 = new Date(2012,04,04,0,0)
Fri May 04 2012 00:00:00 GMT-0400 (EDT)
> d2 = new Date(2012,04,03,23,0)
Thu May 03 2012 23:00:00 GMT-0400 (EDT)
> d3 = new Date(2012,04,05,23,0)
Sat May 05 2012 23:00:00 GMT-0400 (EDT)
> moment(d2).diff(d1, 'days')
0
> moment(d1).diff(d2, 'days')
0
> moment(d1).diff(d3, 'days') // uh oh. this is why we use `startOf`
-2
> moment(d2).diff(d3, 'days')
-2
> moment(d3).startOf('day') // this modified d3, sets the time to 00:00:00.0000
> d3
Sat May 05 2012 00:00:00 GMT-0400 (EDT)
If timezones are a concern, you can also use moment.utc()
to convert to a normalized timezone.
Since the Julian day is effectively the number of days (and in some cases also the fraction of number of days) since a certain date, it is practically the same as a UNIX timestamp, presented differently. You can get the number of whole days since 1970 like so:
Date.prototype.getWholeDays = function () {
return Math.floor(new Date() / 1000*60*60*24);
};
function dateDiff(startDate, endDate) {
return endDate.getWholeDays() - startDate.getWholeDays();
}
If you only want the difference in days, be sure to use UTC (GMT) or the subtraction won't produce a whole number of days in seconds if Daylight Saving Time starts or end during the interval.
I used to check the result of datediff function which uses .getTime() with Excel for the 18th century. The result returns correct. I have another method to calculate different days:
function DaysOfYear(nYear) {
if ((nYear % 4) == 0) {
return 366;
}
else {
return 365;
}
}
function DiffDays(fDate, tDate) {
var fYear = fDate.getFullYear();
var tYear = tDate.getFullYear();
var fMonth = fDate.getMonth();
var tMonth = tDate.getMonth();
var fDay = fDate.getDate();
var tDay = tDate.getDate();
var nDays = 0;
if (tYear > fYear) { // different year
// remain days of from year
nDays = DaysOfYear(fYear) - YTD_Days(fDate);
// days of between fYear to tYear
for (y = (fYear + 1); y < tYear; y++) {
nDays = nDays + DaysOfYear(y);
}
// days from the beginning of tYear
nDays = nDays + YTD_Days(tDate);
}
else { // in the same year
nDays = YTD_Days(tDate) - YTD_Days(fDate);
};
return nDays;
}
function YTD_Days(dDate) {
var y = dDate.getFullYear();
var m = dDate.getMonth();
var nDays = 0
for (i = 0; i < m; i++) {
switch (i) {
case 0: // January
nDays = nDays + 31;
break;
case 1: // February
if ((y % 4) == 0) {
nDays = nDays + 29;
}
else {
nDays = nDays + 28;
};
break;
case 2: // March
nDays = nDays + 31;
break;
case 3: // April
nDays = nDays + 30;
break;
case 4: // May
nDays = nDays + 31;
break;
case 5: // June
nDays = nDays + 30;
break;
case 6: // July
nDays = nDays + 31;
break;
case 7: // August
nDays = nDays + 31;
break;
case 8: // September
nDays = nDays + 30;
break;
case 9: // October
nDays = nDays + 31;
break;
case 10: // November
nDays = nDays + 30;
break;
case 11: // December
nDays = nDays + 31;
break;
}
}
nDays = nDays + dDate.getDate();
return nDays;
}
You could adjust the start date to midnight of the same day, then calculate the number of 24-hour periods between the dates. Then, you would take the ceiling or floor of that number depending on whether you want to count any part of a day as a whole day or not.
function dateDiff(startDate, endDate) {
// set startDate to the beginning of the day
startDate = new Date(
startDate.getFullYear(),
startDate.getMonth(),
startDate.getDate());
return Math.floor((endDate - startDate) / 1000*60*60*24);
}
use setHours() method, assuming number of days can never be zero :)
function dateDiff1(startDate, endDate) {
endDate.setHours(0);
startDate.setHours(0);
//assuming days cannt be 0.
var x = ((endDate.getTime() - startDate.getTime()) / 1000*60*60*24);
if (x <1 && x>=0) {
return 1;
}
return x;
}
To get the full days the date interval over daylight saving time changes the floor(days) must be replaced by round. Otherwise it's a very useful function.
+up the example above that uses the UTC constructors. Without doing that, you'll be clobbered by Daylight Savings / Summer Hours.
If you take the differences in some of them, it could wind up an hour short when crossing the DST line for your time zone in one direction (spring-forward, meaning in Feb asking for April, for example). When you floor N+23/24, you'll end up with N.
The other direction (in October asking for December) should be fine, you'll end up an hour ahead which the floor() will deal with correctly.
Just out of curiosity:
If you can affirm that the outcome will ALWAYS be < 31 days, then the following is a solution too:
var deltaDays = new Date(endDate - startDate).getDate()-1
Why?
Well decomposing the previous line:
var msecs = endDate - startDate; // difference in milliseconds
var dt = new Date(msecs); // will give us a date object pointing to a time
// somewhere in Jan 1970 (given the precondition above)
var days = dt.getDate(); // Take the day part of it
var deltaDays = days - 1; // since the numbering starts from 1, we have to
// substract 1 (Ex. if the diff in msecs is 0. The
// Date will point to 1st of Jan 1970)
But obviously you should NOT use it if your results can be > 31.
Need date.js, http://code.google.com/p/datejs/
function CalculateDuration(startDate, endDate) {
var sdt = Date.parse(startDate);
var edt = Date.parse(endDate);
var sdtYear = sdt.getYear();
var edtYear = edt.getYear();
var sdtMonth = sdt.getMonth();
var edtMonth = edt.getMonth();
var sdtDay = sdt.getDate();
var edtDay = edt.getDate();
var StartDateMonthDays = Date.getDaysInMonth(sdtYear, sdtMonth);
var EndDateMonthDays = Date.getDaysInMonth(edtYear, edtMonth);
if (edtMonth < sdtMonth) { //Means the ending month is earlier, which invalidates the operation
alert("Ending month cannot be earlier than the starting month")
}
//Months are equal, if month is the next month of the start date month,
//the operation fails, thus we need to calculate month difference first
else if (edtMonth > sdtMonth) {
//Need to count how many days are left to finish the month
var daysToMonthFinish = StartDateMonthDays - sdtDay;
var calculatedDuration = daysToMonthFinish + edtDay;
$("#hdn_duration").val(calculatedDuration);
}
//If months are the same, it is safe to just calculate the end day minus the start day
else {
var calcDuration = edtDay - sdtDay;
$("#hdn_duration").val(calcDuration);
}
I know this is a partial solution but you may be able to get the days between dates (as long as the dates don't have time set). Then you can work from there.
I'm basing this solution with the problem you presented ((daily fee * number of days) = total charge); not the actual date difference question. This should help you out.
var Main = function() {
var startDate = new Date('08/20/2014');
var endDate = new Date('08/22/2014');
var totalCharge = monthlyFee * daysBetween(startDate, endDate);
}
var daysBetween = function(startDate, endDate) {
return Math.round(Math.abs((startDate.getTime() - endDate.getTime())/(24*60*60*1000)));
};
本文标签: Date difference in Javascript (ignoring time of day)Stack Overflow
版权声明:本文标题:Date difference in Javascript (ignoring time of day) - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1736856931a1955751.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
diff = Math.max(1, diff)
somewhere in your code if you're not offering free same-day rentals! :] – Noyo Commented Oct 8, 2014 at 14:24