JavaScriptで2つのDate()オブジェクトの違いを計算し、違いの月数のみを返すにはどうすればよいですか?
どんな助けでも素晴らしいでしょう:)
JavaScriptで2つのDate()オブジェクトの違いを計算し、違いの月数のみを返すにはどうすればよいですか?
どんな助けでも素晴らしいでしょう:)
「差の月数」の定義は、多くの解釈の対象となります。:-)
JavaScriptの日付オブジェクトから年、月、日を取得できます。探している情報に応じて、それらを使用して、2つの時点の間の月数を把握できます。
たとえば、すぐに使用できます。
function monthDiff(d1, d2) {
var months;
months = (d2.getFullYear() - d1.getFullYear()) * 12;
months -= d1.getMonth();
months += d2.getMonth();
return months <= 0 ? 0 : months;
}
function monthDiff(d1, d2) {
var months;
months = (d2.getFullYear() - d1.getFullYear()) * 12;
months -= d1.getMonth();
months += d2.getMonth();
return months <= 0 ? 0 : months;
}
function test(d1, d2) {
var diff = monthDiff(d1, d2);
console.log(
d1.toISOString().substring(0, 10),
"to",
d2.toISOString().substring(0, 10),
":",
diff
);
}
test(
new Date(2008, 10, 4), // November 4th, 2008
new Date(2010, 2, 12) // March 12th, 2010
);
// Result: 16
test(
new Date(2010, 0, 1), // January 1st, 2010
new Date(2010, 2, 12) // March 12th, 2010
);
// Result: 2
test(
new Date(2010, 1, 1), // February 1st, 2010
new Date(2010, 2, 12) // March 12th, 2010
);
// Result: 1
(JavaScriptの月の値は0 = 1月で始まることに注意してください。)
通常の2月の3日は、8月の3日(〜9.677%)よりもその月の割合が大きい(〜10.714%)ため、上記に小数の月を含めることははるかに複雑です。もちろん、2月でさえも動く目標です。うるう年かどうかによって異なります。
JavaScriptで利用できる日付と時刻のライブラリもいくつかあり、おそらくこの種のことを簡単にします。
注:+ 1
上記には、ここにがありました:
months = (d2.getFullYear() - d1.getFullYear()) * 12;
months -= d1.getMonth() + 1;
// −−−−−−−−−−−−−−−−−−−−^^^^
months += d2.getMonth();
それはもともと私が言ったからです:
...これは、部分的な月を数えずに、2つの日付の間にある完全な月の数を調べます(たとえば、各日付が含まれる月を除く)。
私は2つの理由でそれを削除しました:
部分的な月を数えないことは、答えに来る多くの(ほとんどの?)人々が望んでいないことが判明したので、私はそれらを分離するべきだと思いました。
その定義でも常に機能するとは限りませんでした。:-D(ごめんなさい)
月の日を考慮しない場合、これははるかに簡単な解決策です
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
月のインデックスは0ベースであることに注意してください。これは、January = 0
とを意味しDecember = 11
ます。
これは、2つの日付の間の月数を正確に提供する関数です。
デフォルトの動作では、1か月のみがカウントされます。たとえば、3か月と1日では、3か月の差が生じます。roundUpFractionalMonths
paramをに設定することでこれを防ぐことができるためtrue
、3か月と1日の差は4か月として返されます。
上記の受け入れられた答え(TJ Crowderの答え)は正確ではなく、間違った値を返すことがあります。
たとえば、明らかに間違っているをmonthDiff(new Date('Jul 01, 2015'), new Date('Aug 05, 2015'))
返します。0
正しい違いは、丸1か月または切り上げ2か月のいずれかです。
これが私が書いた関数です:
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);
};
日の部分を完全に無視して、2つの日付の間の月の量だけを取得したい場合があります。たとえば、2013/06/21と2013/10 / 18の2つの日付があり、2013/06と2013/10の部分だけを気にした場合、シナリオと考えられる解決策は次のとおりです。
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.month1とmonth2の両方を除く2つの日付の間の月数だけが必要な場合
numberOfMonths = (year2 - year1) * 12 + (month2 - month1) - 1;
2.いずれかの月を含める場合
numberOfMonths = (year2 - year1) * 12 + (month2 - month1);
3.両方の月を含める場合
numberOfMonths = (year2 - year1) * 12 + (month2 - month1) + 1;
月が28日、29日、30日、または31日であるかどうかに関係なく、完全な月を数える必要がある場合。以下が機能するはずです。
var months = to.getMonth() - from.getMonth()
+ (12 * (to.getFullYear() - from.getFullYear()));
if(to.getDate() < from.getDate()){
months--;
}
return months;
これは回答https://stackoverflow.com/a/4312956/1987208の拡張バージョンですが、 1月31日から2月1日(1日)までのケースで1か月を計算する場合を修正します。
これは以下をカバーします。
JavaScriptの2つの日付の月の違い:
start_date = new Date(year, month, day); //Create start date object by passing appropiate argument
end_date = new Date(new Date(year, month, day)
start_dateとend_dateの間の合計月数:
total_months = (end_date.getFullYear() - start_date.getFullYear())*12 + (end_date.getMonth() - start_date.getMonth())
これは本当に遅いことは知っていますが、他の人に役立つ場合に備えて、とにかく投稿してください。これが私が思いついた関数で、2つの日付の間の月の差を数えるのに良い仕事をしているようです。確かに、Crowder氏よりもかなり不潔ですが、日付オブジェクトをステップスルーすることで、より正確な結果が得られます。AS3にありますが、強い型付けをやめることができるはずで、JSがあります。気軽に誰かを見て見栄えを良くしてください!
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;
}
@TJの回答を拡張するために、完全な暦月ではなく単純な月を探している場合は、d2の日付がd1の日付以上であるかどうかを確認できます。つまり、d2がその月よりも遅い場合、d1はその月よりも1か月多くなります。したがって、これを実行できるはずです。
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
これは時間の問題(たとえば、3月3日午後4時と4月3日午後3時)を完全に説明しているわけではありませんが、より正確で、わずか数行のコードです。
各日付を月単位で検討し、減算して差を求めます。
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());
これにより、日を無視して、2つの日付の月の差がわかります。
このソリューションを検討することもできます。これfunction
により、月の差が整数または数値で返されます。
開始日を最初または最後として渡すことparam
は、フォールトトレラントです。つまり、関数は同じ値を返します。
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);
2つのアプローチがあります。数学的で迅速ですが、カレンダーの変動の影響を受けます。または反復的で低速ですが、すべての奇妙なことを処理します(または、少なくともそれらを十分にテストされたライブラリに処理します)。
カレンダーを繰り返し処理する場合は、開始日を1か月ずつ増やし、終了日を過ぎているかどうかを確認します。これにより、異常処理が組み込みのDate()クラスに委任されますが、これを多数の日付で実行すると、処理が遅くなる可能性があります。ジェームズの答えはこのアプローチを取ります。私はこのアイデアが嫌いですが、これが「最も安全な」アプローチだと思います。計算を1つだけ行う場合、パフォーマンスの違いは実際にはごくわずかです。私たちは、一度だけ実行されるタスクを過度に最適化しようとする傾向があります。
ここで、データセットでこの関数を計算している場合は、おそらく各行でその関数を実行したくないでしょう(または、レコードごとに複数回、神は禁じられています)。その場合、受け入れられた答えを除いnew Date()
て、ここで他のほとんどすべての答えを使用できますが、それはちょうど間違っています(との差new Date()
は-1です)?
これが、月の長さとうるう年の違いを説明する、数学的かつ迅速なアプローチへの私の突き刺しです。これをデータセットに適用する場合(この計算を何度も繰り返す場合)にのみ、このような関数を使用する必要があります。一度だけ実行する必要がある場合は、上記のJamesの反復アプローチを使用してください。これは、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;
}
ここでは、ループの少ない他のアプローチを使用します。
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;
}
月(日)の端数を含む2つの日付の差を計算します。
var difference = (date2.getDate() - date1.getDate()) / 30 +
date2.getMonth() - date1.getMonth() +
(12 * (date2.getFullYear() - date1.getFullYear()));
例:date1:2015年9月24日(2015年9月24日)date2:2015年
9月11日(2015年11月9日) 差:2.5(月)
これは正常に機能するはずです。
function monthDiff(d1, d2) {
var months;
months = (d2.getFullYear() - d1.getFullYear()) * 12;
months += d2.getMonth() - d1.getMonth();
return months;
}
この場合、私は完全な月、部分的な月、月の長さなどには関係ありません。月数を知る必要があるだけです。関連する現実のケースは、レポートが毎月支払われる場合であり、レポートがいくつあるべきかを知る必要があります。
例:
これは、数字がどこに向かっているのかを示すための複雑なコード例です。
4か月になるはずの2つのタイムスタンプを取りましょう
タイムゾーン/プルされた時間によってわずかに異なる場合があります。日、分、秒は関係なく、タイムスタンプに含めることができますが、実際の計算では無視します。
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();
これは私たちに与えます
(12 * (endYear - startYear)) + 1
ステップ3:終了月に追加します。2 + (12 * (2020 - 2019)) + 1 = 15
15 - 11 = 4
; 4か月の結果が得られます。
2019年11月から2022年3月までは29か月です。これらをExcelスプレッドシートに入れると、29行が表示されます。
3 + (12 * (2022-2019)) + 1
40-11 = 29
これは私が見つけることができる最も簡単な解決策です。これにより、月数が直接返されます。ただし、常に絶対値を示します。
new Date(new Date(d2) - new Date(d1)).getMonth();
非絶対値の場合、次のソリューションを使用できます。
function diff_months(startDate, endDate) {
let diff = new Date( new Date(endDate) - new Date(startDate) ).getMonth();
return endDate >= startDate ? diff : -diff;
}
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);
}
次のコードは、部分的な月の日数も考慮に入れて、2つの日付の間の完全な月を返します。
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;
}
以下のロジックは、月単位で差を取得します
(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;
}
私が使用しているものを参照してください:
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;
}
また、日数をカウントし、月単位で変換します。
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
getMonthDiff(d1, d2) {
var year1 = dt1.getFullYear();
var year2 = dt2.getFullYear();
var month1 = dt1.getMonth();
var month2 = dt2.getMonth();
var day1 = dt1.getDate();
var day2 = dt2.getDate();
var months = month2 - month1;
var years = year2 -year1
days = day2 - day1;
if (days < 0) {
months -= 1;
}
if (months < 0) {
months += 12;
}
return months + years*!2;
}
任意の値がその絶対値とともに返されます。
function differenceInMonths(firstDate, secondDate) {
if (firstDate > secondDate) [firstDate, secondDate] = [secondDate, firstDate];
let diffMonths = (secondDate.getFullYear() - firstDate.getFullYear()) * 12;
diffMonths -= firstDate.getMonth();
diffMonths += secondDate.getMonth();
return diffMonths;
}
anyVar = (((DisplayTo.getFullYear() * 12) + DisplayTo.getMonth()) - ((DisplayFrom.getFullYear() * 12) + DisplayFrom.getMonth()));
私は車輪の再発明をしたくないので、単純に保ち(月の日数やうるう年などを気にしないことを意味します)、date-fns
libを使用します。
npm install -s date-fns
と
const differenceInMonths = require('date-fns/differenceInMonths')
;(() => {
console.log(differenceInMonths(new Date(`2015-12-01`), new Date(`2013-12-01`)))
console.log(differenceInMonths(new Date(1582261140000), new Date(`2014-12-01`)))
console.log(differenceInMonths(new Date(1582261140000), new Date(1573621200000)))
})()
1つのアプローチは、JODAライブラリを使用する単純なJava Webサービス(REST / JSON)を作成することです。
http://joda-time.sourceforge.net/faq.html#datediff
2つの日付の差を計算し、javascriptからそのサービスを呼び出します。
これは、バックエンドがJavaであると想定しています。