Làm cách nào để tôi tìm ra sự khác biệt cho hai đối tượng Date () trong JavaScript, trong khi chỉ trả về số tháng chênh lệch?
Bất kỳ sự trợ giúp nào đều sẽ là tuyệt vời :)
Làm cách nào để tôi tìm ra sự khác biệt cho hai đối tượng Date () trong JavaScript, trong khi chỉ trả về số tháng chênh lệch?
Bất kỳ sự trợ giúp nào đều sẽ là tuyệt vời :)
Câu trả lời:
Định nghĩa về "số tháng chênh lệch" có thể được giải thích rất nhiều. :-)
Bạn có thể lấy năm, tháng và ngày trong tháng từ một đối tượng ngày JavaScript. Tùy thuộc vào thông tin bạn đang tìm kiếm, bạn có thể sử dụng những thông tin đó để tính xem có bao nhiêu tháng giữa hai thời điểm.
Ví dụ: off-the-cuff:
function monthDiff(d1, d2) {
var months;
months = (d2.getFullYear() - d1.getFullYear()) * 12;
months -= d1.getMonth();
months += d2.getMonth();
return months <= 0 ? 0 : months;
}
(Lưu ý rằng giá trị tháng trong JavaScript bắt đầu bằng 0 = tháng một.)
Bao gồm các tháng phân đoạn ở trên phức tạp hơn nhiều, bởi vì ba ngày trong tháng Hai điển hình là một phần lớn hơn của tháng đó (~ 10,714%) so với ba ngày trong tháng 8 (~ 9.677%), và tất nhiên ngay cả tháng Hai là mục tiêu di chuyển tùy thuộc vào việc đó có phải là một năm nhuận hay không.
Ngoài ra còn có một số thư viện ngày và thời gian có sẵn cho JavaScript có thể làm cho loại điều này dễ dàng hơn.
Lưu ý : Đã từng có một + 1
ở trên, ở đây:
months = (d2.getFullYear() - d1.getFullYear()) * 12;
months -= d1.getMonth() + 1;
// −−−−−−−−−−−−−−−−−−−−^^^^
months += d2.getMonth();
Đó là bởi vì ban đầu tôi đã nói:
... điều này phát hiện ra có bao nhiêu tháng đầy đủ nằm giữa hai ngày, không tính một phần tháng (ví dụ: không bao gồm tháng mỗi ngày).
Tôi đã xóa nó vì hai lý do:
Không tính một phần tháng hóa ra không phải là điều mà nhiều người (hầu hết?) Đến với câu trả lời muốn, vì vậy tôi nghĩ tôi nên tách chúng ra.
Nó không luôn luôn hoạt động ngay cả theo định nghĩa đó. :-D (Xin lỗi.)
Nếu bạn không xem xét ngày trong tháng, thì đây là giải pháp đơn giản hơn
function monthDiff(dateFrom, dateTo) {
return dateTo.getMonth() - dateFrom.getMonth() +
(12 * (dateTo.getFullYear() - dateFrom.getFullYear()))
}
//examples
console.log(monthDiff(new Date(2000, 01), new Date(2000, 02))) // 1
console.log(monthDiff(new Date(1999, 02), new Date(2000, 02))) // 12 full year
console.log(monthDiff(new Date(2009, 11), new Date(2010, 0))) // 1
Hãy lưu ý rằng chỉ số tháng là dựa trên 0. Điều này có nghĩa là January = 0
và December = 11
.
Đôi khi bạn có thể chỉ muốn lấy số lượng tháng giữa hai ngày hoàn toàn bỏ qua phần ngày. Vì vậy, ví dụ, nếu bạn có hai ngày- 2013/06/21 và 2013/10 / 18- và bạn chỉ quan tâm đến các phần 2013/06 và 2013/10, đây là các tình huống và giải pháp khả thi:
var date1=new Date(2013,5,21);//Remember, months are 0 based in JS
var date2=new Date(2013,9,18);
var year1=date1.getFullYear();
var year2=date2.getFullYear();
var month1=date1.getMonth();
var month2=date2.getMonth();
if(month1===0){ //Have to take into account
month1++;
month2++;
}
var numberOfMonths;
1.Nếu bạn chỉ muốn số tháng giữa hai ngày không bao gồm cả tháng 1 và tháng 2
numberOfMonths = (year2 - year1) * 12 + (month2 - month1) - 1;
2.Nếu bạn muốn bao gồm một trong hai tháng
numberOfMonths = (year2 - year1) * 12 + (month2 - month1);
3.Nếu bạn muốn bao gồm cả hai tháng
numberOfMonths = (year2 - year1) * 12 + (month2 - month1) + 1;
numberOfMonths=(year2-year1)*12+(month2-month1)+1;
điều này cũng tương tự nhưng đúng hơn về mặt ngữ nghĩa đối với tôi
Đây là một chức năng cung cấp chính xác số tháng giữa 2 ngày.
Hành vi mặc định chỉ tính cả tháng, ví dụ 3 tháng và 1 ngày sẽ dẫn đến chênh lệch 3 tháng. Bạn có thể ngăn chặn điều này bằng cách đặt roundUpFractionalMonths
tham số là true
, vì vậy chênh lệch 3 tháng và 1 ngày sẽ được trả lại là 4 tháng.
Câu trả lời được chấp nhận ở trên (câu trả lời của TJ Crowder) không chính xác, đôi khi nó trả về giá trị sai.
Ví dụ, monthDiff(new Date('Jul 01, 2015'), new Date('Aug 05, 2015'))
trả về 0
đó rõ ràng là sai. Sự khác biệt chính xác là 1 tháng hoặc 2 tháng làm tròn.
Đây là chức năng tôi đã viết:
function getMonthsBetween(date1,date2,roundUpFractionalMonths)
{
//Months will be calculated between start and end dates.
//Make sure start date is less than end date.
//But remember if the difference should be negative.
var startDate=date1;
var endDate=date2;
var inverse=false;
if(date1>date2)
{
startDate=date2;
endDate=date1;
inverse=true;
}
//Calculate the differences between the start and end dates
var yearsDifference=endDate.getFullYear()-startDate.getFullYear();
var monthsDifference=endDate.getMonth()-startDate.getMonth();
var daysDifference=endDate.getDate()-startDate.getDate();
var monthCorrection=0;
//If roundUpFractionalMonths is true, check if an extra month needs to be added from rounding up.
//The difference is done by ceiling (round up), e.g. 3 months and 1 day will be 4 months.
if(roundUpFractionalMonths===true && daysDifference>0)
{
monthCorrection=1;
}
//If the day difference between the 2 months is negative, the last month is not a whole month.
else if(roundUpFractionalMonths!==true && daysDifference<0)
{
monthCorrection=-1;
}
return (inverse?-1:1)*(yearsDifference*12+monthsDifference+monthCorrection);
};
Nếu bạn cần tính cả tháng, bất kể tháng là 28, 29, 30 hay 31 ngày. Dưới đây nên làm việc.
var months = to.getMonth() - from.getMonth()
+ (12 * (to.getFullYear() - from.getFullYear()));
if(to.getDate() < from.getDate()){
months--;
}
return months;
Đây là phiên bản mở rộng của câu trả lời https://stackoverflow.com/a/4312956/1987208 nhưng khắc phục trường hợp tính toán 1 tháng cho trường hợp từ ngày 31 tháng 1 đến ngày 1 tháng 2 (1 ngày).
Điều này sẽ bao gồm những điều sau đây;
Sự khác biệt về tháng giữa hai ngày trong JavaScript:
start_date = new Date(year, month, day); //Create start date object by passing appropiate argument
end_date = new Date(new Date(year, month, day)
tổng số tháng giữa start_date và end_date:
total_months = (end_date.getFullYear() - start_date.getFullYear())*12 + (end_date.getMonth() - start_date.getMonth())
Tôi biết điều này thực sự muộn, nhưng dù sao thì việc đăng nó cũng chỉ trong trường hợp nó giúp được người khác. Đây là một chức năng mà tôi đã nghĩ ra dường như làm rất tốt việc đếm sự khác biệt trong các tháng giữa hai ngày. Nó được thừa nhận là rất tuyệt vời so với Mr.Crowder, nhưng cung cấp kết quả chính xác hơn bằng cách bước qua đối tượng ngày. Đó là trong AS3 nhưng bạn chỉ cần có thể bỏ kiểu gõ mạnh và bạn sẽ có JS. Hãy thoải mái để làm cho nó đẹp hơn bất cứ ai ngoài đó!
function countMonths ( startDate:Date, endDate:Date ):int
{
var stepDate:Date = new Date;
stepDate.time = startDate.time;
var monthCount:int;
while( stepDate.time <= endDate.time ) {
stepDate.month += 1;
monthCount += 1;
}
if ( stepDate != endDate ) {
monthCount -= 1;
}
return monthCount;
}
Xem xét mỗi ngày tính theo tháng, sau đó trừ đi để tìm sự khác biệt.
var past_date = new Date('11/1/2014');
var current_date = new Date();
var difference = (current_date.getFullYear()*12 + current_date.getMonth()) - (past_date.getFullYear()*12 + past_date.getMonth());
Điều này sẽ giúp bạn có sự khác biệt của tháng giữa hai ngày, bỏ qua các ngày.
Để mở rộng câu trả lời của @ TJ, nếu bạn đang tìm kiếm các tháng đơn giản, thay vì các tháng theo lịch đầy đủ, bạn chỉ cần kiểm tra xem ngày của d2 có lớn hơn hoặc bằng so với d1 không. Đó là, nếu d2 muộn hơn trong tháng của nó so với d1 trong tháng của nó, thì có thêm 1 tháng nữa. Vì vậy, bạn sẽ có thể chỉ cần làm điều này:
function monthDiff(d1, d2) {
var months;
months = (d2.getFullYear() - d1.getFullYear()) * 12;
months -= d1.getMonth() + 1;
months += d2.getMonth();
// edit: increment months if d2 comes later in its month than d1 in its month
if (d2.getDate() >= d1.getDate())
months++
// end edit
return months <= 0 ? 0 : months;
}
monthDiff(
new Date(2008, 10, 4), // November 4th, 2008
new Date(2010, 2, 12) // March 12th, 2010
);
// Result: 16; 4 Nov – 4 Dec '08, 4 Dec '08 – 4 Dec '09, 4 Dec '09 – 4 March '10
Điều này không hoàn toàn giải thích cho vấn đề thời gian (ví dụ: 3 tháng 3 lúc 4:00 chiều và 3 tháng 4 lúc 3:00 chiều), nhưng nó chính xác hơn và chỉ với một vài dòng mã.
Có hai cách tiếp cận, toán học & nhanh chóng, nhưng tùy thuộc vào sự mơ hồ trong lịch, hoặc lặp lại & chậm, nhưng xử lý tất cả các điều kỳ lạ (hoặc ít nhất là các đại biểu xử lý chúng đến một thư viện được kiểm tra tốt).
Nếu bạn lặp qua lịch, hãy tăng ngày bắt đầu thêm một tháng và xem liệu chúng ta có vượt qua ngày kết thúc hay không. Điều này ủy quyền xử lý bất thường cho các lớp Date () tích hợp, nhưng có thể chậm NẾU bạn đang làm điều này trong một số lượng lớn ngày. Câu trả lời của James có cách tiếp cận này. Nhiều như tôi không thích ý tưởng này, tôi nghĩ rằng đây là cách tiếp cận "an toàn nhất" và nếu bạn chỉ thực hiện một phép tính, sự khác biệt hiệu suất thực sự là không đáng kể. Chúng tôi có xu hướng cố gắng tối ưu hóa quá mức các nhiệm vụ sẽ chỉ được thực hiện một lần.
Bây giờ, nếu bạn đang tính toán chức năng này trên một tập dữ liệu, có lẽ bạn không muốn chạy chức năng đó trên mỗi hàng (hoặc thần cấm, nhiều lần trên mỗi bản ghi). Trong trường hợp đó, bạn có thể sử dụng hầu hết các câu trả lời khác ở đây ngoại trừ câu trả lời được chấp nhận, điều này chỉ sai (sự khác biệt giữa new Date()
và new Date()
là -1)?
Đây là cú đâm của tôi theo cách tiếp cận toán học và nhanh chóng, chiếm các độ dài tháng khác nhau và năm nhuận. Bạn thực sự chỉ nên sử dụng một hàm như thế này nếu bạn sẽ áp dụng điều này cho bộ dữ liệu (thực hiện phép tính này hơn & hơn). Nếu bạn chỉ cần thực hiện một lần, hãy sử dụng phương pháp lặp của James ở trên, vì bạn đang ủy thác xử lý tất cả (nhiều) ngoại lệ cho đối tượng Date ().
function diffInMonths(from, to){
var months = to.getMonth() - from.getMonth() + (12 * (to.getFullYear() - from.getFullYear()));
if(to.getDate() < from.getDate()){
var newFrom = new Date(to.getFullYear(),to.getMonth(),from.getDate());
if (to < newFrom && to.getMonth() == newFrom.getMonth() && to.getYear() %4 != 0){
months--;
}
}
return months;
}
Ở đây bạn đi cách tiếp cận khác với ít vòng lặp hơn:
calculateTotalMonthsDifference = function(firstDate, secondDate) {
var fm = firstDate.getMonth();
var fy = firstDate.getFullYear();
var sm = secondDate.getMonth();
var sy = secondDate.getFullYear();
var months = Math.abs(((fy - sy) * 12) + fm - sm);
var firstBefore = firstDate > secondDate;
firstDate.setFullYear(sy);
firstDate.setMonth(sm);
firstBefore ? firstDate < secondDate ? months-- : "" : secondDate < firstDate ? months-- : "";
return months;
}
Bạn cũng có thể xem xét giải pháp này, điều này function
trả về chênh lệch tháng theo số nguyên hoặc số
Vượt qua ngày bắt đầu là ngày đầu tiên hoặc cuối cùng param
, là khả năng chịu lỗi. Có nghĩa là, hàm vẫn sẽ trả về cùng một giá trị.
const diffInMonths = (end, start) => {
var timeDiff = Math.abs(end.getTime() - start.getTime());
return Math.round(timeDiff / (2e3 * 3600 * 365.25));
}
const result = diffInMonths(new Date(2015, 3, 28), new Date(2010, 1, 25));
// shows month difference as integer/number
console.log(result);
Tính toán sự khác biệt giữa hai ngày bao gồm phân số của tháng (ngày).
var difference = (date2.getDate() - date1.getDate()) / 30 +
date2.getMonth() - date1.getMonth() +
(12 * (date2.getFullYear() - date1.getFullYear()));
Ví dụ:
date1 : 24/09/2015 (
24/9/2015 ) date2 : 09/11/2015 (9/11/2015)
chênh lệch: 2.5 (tháng)
Điều này sẽ hoạt động tốt:
function monthDiff(d1, d2) {
var months;
months = (d2.getFullYear() - d1.getFullYear()) * 12;
months += d2.getMonth() - d1.getMonth();
return months;
}
function calcualteMonthYr(){
var fromDate =new Date($('#txtDurationFrom2').val()); //date picker (text fields)
var toDate = new Date($('#txtDurationTo2').val());
var months=0;
months = (toDate.getFullYear() - fromDate.getFullYear()) * 12;
months -= fromDate.getMonth();
months += toDate.getMonth();
if (toDate.getDate() < fromDate.getDate()){
months--;
}
$('#txtTimePeriod2').val(months);
}
Mã sau trả về đầy đủ các tháng giữa hai ngày bằng cách lấy nr ngày của một phần tháng.
var monthDiff = function(d1, d2) {
if( d2 < d1 ) {
var dTmp = d2;
d2 = d1;
d1 = dTmp;
}
var months = (d2.getFullYear() - d1.getFullYear()) * 12;
months -= d1.getMonth() + 1;
months += d2.getMonth();
if( d1.getDate() <= d2.getDate() ) months += 1;
return months;
}
monthDiff(new Date(2015, 01, 20), new Date(2015, 02, 20))
> 1
monthDiff(new Date(2015, 01, 20), new Date(2015, 02, 19))
> 0
monthDiff(new Date(2015, 01, 20), new Date(2015, 01, 22))
> 0
function monthDiff(d1, d2) {
var months, d1day, d2day, d1new, d2new, diffdate,d2month,d2year,d1maxday,d2maxday;
months = (d2.getFullYear() - d1.getFullYear()) * 12;
months -= d1.getMonth() + 1;
months += d2.getMonth();
months = (months <= 0 ? 0 : months);
d1day = d1.getDate();
d2day = d2.getDate();
if(d1day > d2day)
{
d2month = d2.getMonth();
d2year = d2.getFullYear();
d1new = new Date(d2year, d2month-1, d1day,0,0,0,0);
var timeDiff = Math.abs(d2.getTime() - d1new.getTime());
diffdate = Math.abs(Math.ceil(timeDiff / (1000 * 3600 * 24)));
d1new = new Date(d2year, d2month, 1,0,0,0,0);
d1new.setDate(d1new.getDate()-1);
d1maxday = d1new.getDate();
months += diffdate / d1maxday;
}
else
{
if(!(d1.getMonth() == d2.getMonth() && d1.getFullYear() == d2.getFullYear()))
{
months += 1;
}
diffdate = d2day - d1day + 1;
d2month = d2.getMonth();
d2year = d2.getFullYear();
d2new = new Date(d2year, d2month + 1, 1, 0, 0, 0, 0);
d2new.setDate(d2new.getDate()-1);
d2maxday = d2new.getDate();
months += diffdate / d2maxday;
}
return months;
}
logic dưới đây sẽ lấy sự khác biệt trong tháng
(endDate.getFullYear()*12+endDate.getMonth())-(startDate.getFullYear()*12+startDate.getMonth())
function monthDiff(date1, date2, countDays) {
countDays = (typeof countDays !== 'undefined') ? countDays : false;
if (!date1 || !date2) {
return 0;
}
let bigDate = date1;
let smallDate = date2;
if (date1 < date2) {
bigDate = date2;
smallDate = date1;
}
let monthsCount = (bigDate.getFullYear() - smallDate.getFullYear()) * 12 + (bigDate.getMonth() - smallDate.getMonth());
if (countDays && bigDate.getDate() < smallDate.getDate()) {
--monthsCount;
}
return monthsCount;
}
Xem những gì tôi sử dụng:
function monthDiff() {
var startdate = Date.parseExact($("#startingDate").val(), "dd/MM/yyyy");
var enddate = Date.parseExact($("#endingDate").val(), "dd/MM/yyyy");
var months = 0;
while (startdate < enddate) {
if (startdate.getMonth() === 1 && startdate.getDate() === 28) {
months++;
startdate.addMonths(1);
startdate.addDays(2);
} else {
months++;
startdate.addMonths(1);
}
}
return months;
}
Nó cũng đếm số ngày và chuyển đổi chúng trong tháng.
function monthDiff(d1, d2) {
var months;
months = (d2.getFullYear() - d1.getFullYear()) * 12; //calculates months between two years
months -= d1.getMonth() + 1;
months += d2.getMonth(); //calculates number of complete months between two months
day1 = 30-d1.getDate();
day2 = day1 + d2.getDate();
months += parseInt(day2/30); //calculates no of complete months lie between two dates
return months <= 0 ? 0 : months;
}
monthDiff(
new Date(2017, 8, 8), // Aug 8th, 2017 (d1)
new Date(2017, 12, 12) // Dec 12th, 2017 (d2)
);
//return value will be 4 months
Trong trường hợp này, tôi không quan tâm đến các tháng đầy đủ, một phần tháng, một tháng là bao lâu, v.v. Tôi chỉ cần biết số tháng. Một trường hợp thực tế có liên quan sẽ là nơi báo cáo đến hạn hàng tháng và tôi cần biết có bao nhiêu báo cáo nên có.
Thí dụ:
Đây là một ví dụ mã được xây dựng để chỉ ra nơi các con số đang đi.
Hãy lấy 2 dấu thời gian sẽ có kết quả sau 4 tháng
Có thể hơi khác với thời gian / thời gian kéo của bạn. Ngày, phút và giây không quan trọng và có thể được bao gồm trong dấu thời gian, nhưng chúng tôi sẽ bỏ qua nó với tính toán thực tế của chúng tôi.
let dateRangeStartConverted = new Date(1573621200000);
let dateRangeEndConverted = new Date(1582261140000);
let startingMonth = dateRangeStartConverted.getMonth();
let startingYear = dateRangeStartConverted.getFullYear();
let endingMonth = dateRangeEndConverted.getMonth();
let endingYear = dateRangeEndConverted.getFullYear();
Điều này cho chúng ta
(12 * (endYear - startYear)) + 1
tháng kết thúc.2 + (12 * (2020 - 2019)) + 1 = 15
15 - 11 = 4
; chúng tôi nhận được kết quả 4 tháng của chúng tôi.
Tháng 11 năm 2019 đến tháng 3 năm 2022 là 29 tháng. Nếu bạn đặt chúng vào bảng tính excel, bạn sẽ thấy 29 hàng.
3 + (12 * (2022-2019)) + 1
40 - 11 = 29
anyVar = (((DisplayTo.getFullYear() * 12) + DisplayTo.getMonth()) - ((DisplayFrom.getFullYear() * 12) + DisplayFrom.getMonth()));
Một cách tiếp cận là viết một Dịch vụ web Java đơn giản (REST / JSON) sử dụng thư viện JODA
http://joda-time.sourceforge.net/faq.html#datediff
để tính toán sự khác biệt giữa hai ngày và gọi dịch vụ đó từ javascript.
Điều này giả sử back end của bạn là trong Java.