Javascript-форум (https://javascript.ru/forum/)
-   Общие вопросы Javascript (https://javascript.ru/forum/misc/)
-   -   Промежуток времени между датами (https://javascript.ru/forum/misc/37338-promezhutok-vremeni-mezhdu-datami.html)

Octane 16.04.2013 13:21

Промежуток времени между датами
 
Обычно используют «финансовый год» (12 месяцев по 30 дней = 360 дней), тут все просто, количество дней между датами:
количество миллисекунд между датами / 1000 миллисекунд / 60 секунд / 60 минут / 24 часа
потом количество дней делим нацело на 360… и т.д…

Но как быть, если необходимо узнать точный календарный период времени между двумя датами?
В JavaScript объект Date умеет перескакивать на следующий месяц, если значение переданное в метод setDate, превышает количество дней в месяце. Выполняя date.setDate(date.getDate() + 1) можно в цикле пройтись по всем дням в указанном промежутке и посчитать количество календарных месяцев:

Например, с 10.04.2013 до 20.10.2013 пройдет 5 месяцев 39 дней.
Теперь главный вопрос: 39 дней надо как-то перевести в месяцы, какое количество дней брать? 30 дней, как в начальном месяце или 31, как в конечном месяце? есть ли какое-то правило или соглашение?

рони 16.04.2013 13:48

Цитата:

Сообщение от Octane
есть ли какое-то правило или соглашение?

насчёт соглашения незнаю ... но была тема тут
Цитата:

Сообщение от Octane
Например, с 10.04.2013 до 20.10.2013 пройдет 5 месяцев 39 дней.

по моему алгоритму получается 6 месяцев 10 дней
function passed(d, m, g, dd, mm, gg) {
    //устанавливаем начальное время  и  будушее
    var a = new Date(g, m - 1, d, 0, 0, 0, 0),b = new Date(gg, mm-1, dd, 0, 0, 0, 0);
    //увеличивая начальное время на 1 месяц вперёд
    //подсчитываем количество полных месяцев до сегодня
    //если дата превышает число дней следующего месяца
    //то месяцем считаем весь следующий  месяц
    //5 января + 1 месяц = 5 февраля, но 31 января + 1 месяц = 28/29 февраля
    for (m = 0;; m++) {
        g = new Date(a.getFullYear(), a.getMonth() + 2, 0);
        g.getDate() > d && g.setDate(d);
        if (g > b) break;
        a = g
    }
    d = b - a;//оставшееся время за последний неполный месяц, если будет
    d = Math.round(d/864E5);//количество полных дней в этом времени
    g = Math.floor(m/12);//сколько полных лет в подсчитанных месяцах
    m = m % 12;//оставшиеся месяцы от полных лет
    return [g, m, d]
};
alert(passed('10','4','2013','20','10','2013'));

nerv_ 17.04.2013 15:25

Цитата:

Сообщение от рони
по моему алгоритму получается 6 месяцев 10 дней

ради интереса посмотрел функцию php date_diff. Результат как у рони.

$datetime1 = date_create('2013-04-10');
$datetime2 = date_create('2013-10-20');
$interval = date_diff($datetime1, $datetime2);
echo print_r( $interval );

выхлоп
DateInterval Object
(
    [y] => 0
    [m] => 6
    [d] => 10
    [h] => 0
    [i] => 0
    [s] => 0
    [invert] => 0
    [days] => 193
)

nerv_ 17.04.2013 16:37

особо не проверял, вроде работает
function dateDiff( date1, date2 ) {
	var years = date2.getFullYear() - date1.getFullYear();
	var months = years * 12 + date2.getMonth() - date1.getMonth();
	var days = date2.getDate() - date1.getDate();  
	
	years -= date2.getMonth() < date1.getMonth();
	months -= date2.getDate() < date1.getDate();
	days += days < 0 ? new Date( date2.getFullYear(), date2.getMonth() - 1, 0 ).getDate() + 1 : 0;
	
	return [ years, months, days ];
}

alert( dateDiff( new Date( '2013-11-10' ), new Date( '2014-01-09' ) ) );
alert( dateDiff( new Date( '2013-04-10' ), new Date( '2013-10-20' ) ) );

nerv_ 17.04.2013 19:24

вариант #2

function dateDiff( date1, date2 ) {
	date1 = new Date( date1 );
	date2 = new Date( date2 );
	
	var milliseconds = date2.getMilliseconds() - date1.getMilliseconds();
	
	if ( milliseconds < 0 ) {
		milliseconds += 1000;
		date2.setSeconds( date2.getSeconds() - 1 );
	}
	
	var seconds = date2.getSeconds() - date1.getSeconds();
	
	if ( seconds < 0 ) {
		seconds += 60;
		date2.setMinutes( date2.getMinutes() - 1 );
	}
		
	var minutes = date2.getMinutes() - date1.getMinutes();
	
	if ( minutes < 0 ) {
		minutes += 60;
		date2.setHours( date2.getHours() - 1 );
	}
	
	var hours = date2.getHours() - date1.getHours();
	
	if ( hours < 0 ) {
		hours += 24;
		date2.setDate( date2.getDate() - 1 );
	}
	
	var days = date2.getDate() - date1.getDate();
	
	if ( days < 0 ) {
		days += new Date( date2.getFullYear(), date2.getMonth() - 1, 0 ).getDate() + 1;
		date2.setMonth( date2.getMonth() - 1 );
	}
	
	var months = date2.getMonth() - date1.getMonth();
	
	if ( months < 0 ) {
		months += 12;
		date2.setFullYear( date2.getFullYear() - 1 );
	}
	
	var years = date2.getFullYear() - date1.getFullYear();
	
	return [ years, months, days, hours, minutes, seconds, milliseconds ];
}

alert( dateDiff( '2013-01-10 00:10', '2013-01-11 00:09' ) );
alert( dateDiff( '2013-04-10', '2013-10-20' ) );

with-love-from-siberia 17.04.2013 21:00

Особого смысла считать разницу в интервалах больших чем сутки нет по причине непостоянства количества дней в этих интервалах (в месяцах и годах). Хотя для удобства же представления можно сделать, например, так:
var S = 60 * 60 * 24 * 1000;

var diff2 = function(date1, date2)
{
	var delta = date1.getDate() - 1;

	var date3 = new Date(date1.getFullYear(), date1.getMonth(), 1);
	var date4 = new Date(date2.getFullYear(), date2.getMonth(), date2.getDate() - delta);

	var m = date4.getMonth() - date3.getMonth();
	var d = date4.getDate() - 1;

	alert([
		date1, date2, (date4 - date3) / S, 
		date3, date4, (date2 - date1) / S, 
		'months: ' + m, 'days: ' + d
	].join('\n'));
};

var x = new Date(2013, 3, 10);
var y = new Date(2013, 9, 20);

diff2(x, y);

tsigel 22.04.2013 10:52

У меня есть вопрос, по похожей проблеме. Есть 2 даты (строки в формате день.месяц.год часы:минуты:секунды), нужно посчитать количество часов и минут между этими датами

tsigel 22.04.2013 12:08

var date1 = new Date('10.05.12 16:30'); 
var date2 = new Date('10.05.13 15:20'); 
var delta = date2-date1; 
var hours = Math.round(delta / (60*60*1000)); 
var minutes = (delta-hours*60*60*1000) / (60*1000); 
alert(hours + ' ' + minutes);

Так?

rgl 22.04.2013 12:29

Используя round рискуете получить отрицательное количество минут, напр: 4 часа -25 минут вместо 3 часа 35 минут
var minutes = Math.round(delta / (60*1000));
var hours = Math.floor( minutes / 60 );
minutes -= hours * 60;

tsigel 22.04.2013 12:41

var date1 = new Date('10.05.12 14:30');
    var date2 = new Date('10.05.12 15:20');
    var delta = date2-date1;
    var minutes = Math.round(delta / (60*1000));
    var hours = Math.floor(minutes / 60);
    minutes -= (hours * 60);
    alert(hours + ' ' + minutes);


Часовой пояс GMT +3, время: 21:42.