Показать полную графическую версию : [решено] Посчитать количество дней между двумя датами
wlad1164
24-05-2018, 16:55
Имеется 2 переменных
Set /a Date1=180312
Set /a Date2=180523
Date2 всегда больше Date1
Формат всегда ГГММДД
Нужно посчитать кол-во дней между ними ( = 72 )
Запнулся на такой задаче, предположение как решить:
посчитать разность лет,месяцев,дней
затем перемножить и сложить и играться с этими данными добавив условия
но думаю есть решение проще... Буду благодарен за подсказку если таковое есть.
Все это нужно сделать именно в bat
Все это нужно сделать именно в bat »
Причина?
wlad1164, мсье знает толк в извращениях. Тут час убить только на то чтобы прописать условия для всех месяцев, учесть високосный год, имхо, если так уж нужно получать эти данные в bat - проще выполнять вычисления, например, в powershell, в нужном формате возвращать результат и разбив его извращаться дальше.
Elven, ну, коллеги тут делать-то делали подобное, при большом желании напишут. А так — да, хотелось бы понять причины требования «только пакетный файл».
megaloman
24-05-2018, 20:01
@set @E=1; /*
@Echo Off
cls
Set /A Date1=180312
Set /A Date2=180523
Set /A Vek=20
FOR /F "usebackq delims=" %%d IN (`Cscript //NoLogo /E:jscript "%~dpnx0" %Vek%%Date2% %Vek%%Date1%`) DO Set /A Days=%%d
Echo %Date2%-%Date1%=%Days%
Pause
GoTo :Eof
*/
var oArg = WScript.Arguments;
if (oArg.Count()<2) WScript.Quit(1);
var msek1=Date.UTC(oArg(0).substr(0,4),oArg(0).substr(4,2)-1,oArg(0).substr(6,2));
var msek2=Date.UTC(oArg(1).substr(0,4),oArg(1).substr(4,2)-1,oArg(1).substr(6,2));
WScript.Echo((msek1-msek2)/86400000);
WScript.Quit(0);
wlad1164
24-05-2018, 22:31
Iska, ну главный вопрос был в том а нет ли какой-либо функции для этого, насколько понял нет...
megaloman, спасибо что не поленились затратить время, но хотелось бы без JS....
Попыхтев пару часов получилось что то вроде этого:
echo off
Chcp 1251
cls
:: Установка дат
Set /a Date1=180312
Set /a Date2=180523
echo %time%
:: Разбивка первой даты
Set /a God1= %Date1:~0,2%+2000
Set /a Mes1= %Date1:~2,2%
Set /a Day1= %Date1:~4,2%
:: Разбивка второй даты
Set /a God2= %Date2:~0,2%+2000
Set /a Mes2= %Date2:~2,2%
Set /a Day2= %Date2:~4,2%
:: Считаем кол-во дней в за годы первой даты
Set /a GodVis1=%God1%/4
Set /a GodNeVis1=%God1%/4-1
Set /a VisGod1=%God1%%%4
If "%VisGod1%"=="0" (Set /a KolNeVisGod1=%God1%-%GodNeVis1%)
If "%VisGod1%"=="1" (Set /a KolNeVisGod1=%God1%-%GodNeVis1%)
If "%VisGod1%"=="2" (Set /a KolNeVisGod1=%God1%-%GodVis1%)
If "%VisGod1%"=="3" (Set /a KolNeVisGod1=%God1%-%GodVis1%)
Set /a KolVisGod1=%God1%-%KolNeVisGod1%
Set /a DaysGod1=%KolVisGod1%*366+%KolNeVisGod1%*365
:: Считаем кол-во дней за годы второй даты
Set /a GodVis2=%God2%/4
Set /a GodNeVis2=%God2%/4-1
Set /a VisGod2=%God2%%%4
If "%VisGod2%"=="0" (Set /a KolNeVisGod2=%God2%-%GodNeVis2%)
If "%VisGod2%"=="1" (Set /a KolNeVisGod2=%God2%-%GodNeVis2%)
If "%VisGod2%"=="2" (Set /a KolNeVisGod2=%God2%-%GodVis2%)
If "%VisGod2%"=="3" (Set /a KolNeVisGod2=%God2%-%GodVis2%)
Set /a KolVisGod2=%God2%-%KolNeVisGod2%
Set /a DaysGod2=%KolVisGod2%*366+%KolNeVisGod2%*365
:: Разность жней меду годами
Set /a RaznostGod=%DaysGod2%-%DaysGod1%
:: Считаем кол-во дней за месяца первой даты
:: Февраль первой даты
If "%VisGod1%"=="0" (Set /a FebDate1=29) else (Set /a FebDate1=28)
:: Дни
If "%Mes1%"=="1" (Set /a DayMes1=%Day1%)
If "%Mes1%"=="2" (Set /a DayMes1=31+%Day1%)
If "%Mes1%"=="3" (Set /a DayMes1=31+%FebDate1%+%Day1%)
If "%Mes1%"=="4" (Set /a DayMes1=31*2+%FebDate1%+%Day1%)
If "%Mes1%"=="5" (Set /a DayMes1=31*2+%FebDate1%+30+%Day1%)
If "%Mes1%"=="6" (Set /a DayMes1=31*3+%FebDate1%+30+%Day1%)
If "%Mes1%"=="7" (Set /a DayMes1=31*3+%FebDate1%+30*2+%Day1%)
If "%Mes1%"=="8" (Set /a DayMes1=31*4+%FebDate1%+30*2+%Day1%)
If "%Mes1%"=="9" (Set /a DayMes1=31*5+%FebDate1%+30*2+%Day1%)
If "%Mes1%"=="10" (Set /a DayMes1=31*5+%FebDate1%+30*3+%Day1%)
If "%Mes1%"=="11" (Set /a DayMes1=31*6+%FebDate1%+30*3+%Day1%)
If "%Mes1%"=="12" (Set /a DayMes1=31*6+%FebDate1%+30*4+%Day1%)
:: Считаем кол-во дней за месяца второй даты
:: Февраль второй даты
If "%VisGod2%"=="0" (Set /a FebDate2=29) else (Set /a FebDate2=28)
:: Дни
If "%Mes2%"=="1" (Set /a DayMes2=%Day2%)
If "%Mes2%"=="2" (Set /a DayMes2=31+%Day2%)
If "%Mes2%"=="3" (Set /a DayMes2=31+%FebDate2%+%Day2%)
If "%Mes2%"=="4" (Set /a DayMes2=31*2+%FebDate2%+%Day2%)
If "%Mes2%"=="5" (Set /a DayMes2=31*2+%FebDate2%+30+%Day2%)
If "%Mes2%"=="6" (Set /a DayMes2=31*3+%FebDate2%+30+%Day2%)
If "%Mes2%"=="7" (Set /a DayMes2=31*3+%FebDate2%+30*2+%Day2%)
If "%Mes2%"=="8" (Set /a DayMes2=31*4+%FebDate2%+30*2+%Day2%)
If "%Mes2%"=="9" (Set /a DayMes2=31*5+%FebDate2%+30*2+%Day2%)
If "%Mes2%"=="10" (Set /a DayMes2=31*5+%FebDate2%+30*3+%Day2%)
If "%Mes2%"=="11" (Set /a DayMes2=31*6+%FebDate2%+30*3+%Day2%)
If "%Mes2%"=="12" (Set /a DayMes2=31*6+%FebDate2%+30*4+%Day2%)
:: Разность жней меду днями года
Set /a RaznostDayMes=%DayMes2%-%DayMes1%
:: Разность между
Set /a Day=%RaznostGod%+%RaznostDayMes%
echo %Date2%-%Date1%=%Day% дн.
echo %time%
pause
Високосный год вроде бы тоже работает... по крайней мере мне так показалось)))
Код корявый, можно и упростить, но сначала надо убедиться что работает правильно....
UPD
echo off
Chcp 1251
cls
call :СчитатьРазностьДат Day 20180312 20180523
echo Разность %Day% дн.
pause
:СчитатьРазностьДат
:: Получение дат
Set /a Date1=%~2 & Set /a Date2=%~3
:: Разбивка даты
Set /a God1= %Date1:~0,4% & Set /a God2= %Date2:~0,4%
Set /a Mes1= %Date1:~4,2% & Set /a Mes2= %Date2:~4,2%
Set /a Day1= %Date1:~6,2% & Set /a Day2= %Date2:~6,2%
:: Определяем вискокосные ли даты
Set /a VisGod1=%God1%%%4 & Set /a VisGod2=%God2%%%4
:: Считаем дни
call :СчитатьДниПрошедшихЛет DaysGod1 %VisGod1% %God1%
call :СчитатьДниПрошедшихЛет DaysGod2 %VisGod2% %God2%
call :СчитатьДниГода DayMes1 %VisGod1% %Mes1% %Day1%
call :СчитатьДниГода DayMes2 %VisGod2% %Mes2% %Day2%
Set /a %~1=(%DaysGod2%-%DaysGod1%)+(%DayMes2%-%DayMes1%)
exit /b
:СчитатьДниГода
If "%~2"=="0" (Set /a FebDay=29) else (Set /a FebDay=28)
If "%~3"=="1" (Set /a %~1=%~4)
If "%~3"=="2" (Set /a %~1=31+%~4)
If "%~3"=="3" (Set /a %~1=31+%FebDay%+%~4)
If "%~3"=="4" (Set /a %~1=31*2+%FebDay%+%~4)
If "%~3"=="5" (Set /a %~1=31*2+%FebDay%+30+%~4)
If "%~3"=="6" (Set /a %~1=31*3+%FebDay%+30+%~4)
If "%~3"=="7" (Set /a %~1=31*3+%FebDay%+30*2+%~4)
If "%~3"=="8" (Set /a %~1=31*4+%FebDay%+30*2+%~4)
If "%~3"=="9" (Set /a %~1=31*5+%FebDay%+30*2+%~4)
If "%~3"=="10" (Set /a %~1=31*5+%FebDay%+30*3+%~4)
If "%~3"=="11" (Set /a %~1=31*6+%FebDay%+30*3+%~4)
If "%~3"=="12" (Set /a %~1=31*6+%FebDay%+30*4+%~4)
exit /b
:СчитатьДниПрошедшихЛет
Set /a GodVis=%~3/4
Set /a GodNeVis=%~3/4-1
If "%~2"=="0" (Set /a NeVis=%~3-%GodNeVis%)
If "%~2"=="1" (Set /a NeVis=%~3-%GodNeVis%)
If "%~2"=="2" (Set /a NeVis=%~3-%GodVis%)
If "%~2"=="3" (Set /a NeVis=%~3-%GodVis%)
Set /a VisGod=%~3-%NeVis%
Set /a %~1=%VisGod%*366+%NeVis%*365
exit /b
megaloman
25-05-2018, 09:34
wlad1164, Меня количество Ваших если ужасает. Идея как и в JS: сделал функцию, которая вычислит порядковый номер заданного дня в дате начиная от 1 января 2000 (точнее -00) года . Затем разность посчитать - нет труда.@Echo Off
cls
Set "Date1=180312"
Set "Date2=180523"
Call :Days %Date1:~0,2% %Date1:~2,2% %Date1:~4,2% "ND1"
Call :Days %Date2:~0,2% %Date2:~2,2% %Date2:~4,2% "ND2"
Set /A ND=%ND2%-%ND1%
Echo %Date2%-%Date1%=%ND2%-%ND1%=%ND%
Pause
GoTo :Eof
:Days
SetLocal
Set /A N01=0, N02=31, N03=59, N04=90, N05=120, N06=151, N07=181, N08=212, N09=243, N10=273, N11=304, N12=334
Set /A V01=0, V02=31, V03=60, V04=91, V05=121, V06=152, V07=182, V08=213, V09=244, V10=274, V11=305, V12=335
Set /A NN=%1-%1/4*4
Set /A Dy=%1/4*1461+%NN%*365
If %NN%==0 (Call Set MM=%%V%2%%) Else (Set /A Dy+=1 &Call Set MM=%%N%2%%)
EndLocal &Set /A %~4=%Dy%+%MM%+%3
GoTo :Eof
Замечание: Если год начинается с 0, то надо его определять не как численный
Set /a Date1=080312
а как строковый
Set "Date1=080312"
Вариант использования функции..................................
Set "Date1=18 03 12"
Set "Date2=18 05 23"
Call :Days %Date1% "ND1"
Call :Days %Date2% "ND2"
..................................
В принципе, не сложно переделать и под четырёхзначный год, например, дни отсчитывать начиная с 1900 года, но задача Вами так не ставиласьВерю: это же можно сделать элегантнее, но я пока не знаю как
greg zakharov
26-05-2018, 14:13
Есть такая штука, julian day называется, значительно облегчает расчет разницы между датами.
@echo off
setlocal
2>nul set /a "d1=180312, d2=180523" % rem : даты, между которыми будет считаться разница
call:expandDate %d1% d1
call:expandDate %d2% d2
set /a "delta=d2-d1"
echo %delta%
endlocal
exit /b
:expandDate
set "d=%~1"
call:toJulianDay %d:~4,2% %d:~2,2% 20%d:~0,2%
set "%~2=%jdn%"
exit /b
:toJulianDay
set /a "jdn=(1461*(%3+4800+(%2-14)/12))/4+(367*(%2-2-12*((%2-14)/12)))/12-(3*((%3+4900+(%2-14)/12)/100))/4+%1-32075"
exit /b
wlad1164
08-06-2018, 11:28
greg zakharov, наконец тор снова добрался до батника, предложенный Вами вариант работает, но не всегда, к примеру
2>nul set /a "d1=180312, d2=180508"
Уже не сработает
greg zakharov
08-06-2018, 12:15
wlad1164, ошибка возникает из-за того, что командная строка считает числа начинающиеся с нуля в восьмеричной системе счисления, отсюда 08, например, будет недопустимым значением для данной СЧ. Чтобы избежать подобной ошибки нужно значения вроде того же 08 приводить к тому, что в понимании командного интерпретатора будет десятичным числом. Иначе говоря:
set /a "n=10%var%%%100"
Исправленный вариант с julianday будет выглядеть так:
@echo off
setlocal
2>nul set /a "d1=180312, d2=180508" % rem : даты, между которыми будет считаться разница
call:expandDate %d1% d1
call:expandDate %d2% d2
set /a "delta=d2-d1"
echo %delta%
endlocal
exit /b
:expandDate
set "d=%~1"
set /a "a=10%d:~4,2%%%100, b=10%d:~2,2%%%100"
call:toJulianDay %a% %b% 20%d:~0,2%
set "%~2=%jdn%"
exit /b
:toJulianDay
set /a "jdn=(1461*(%3+4800+(%2-14)/12))/4+(367*(%2-2-12*((%2-14)/12)))/12-(3*((%3+4900+(%2-14)/12)/100))/4+%1-32075"
exit /b
© OSzone.net 2001-2012
vBulletin v3.6.4, Copyright ©2000-2025, Jelsoft Enterprises Ltd.