1

Тема: CMD/BAT: Вычисление пройденного времени

Помогите написать скрипт для вычисления времени которое прошло с момента А до момента Б.

момент А - %1 в формате hh.mm.ss - час.минута.секунда , например 22.15.45
момент Б - %1 в формате hh.mm.ss - час.минута.секунда , например 23.18.25

set start_time=%1
set begin_hour=%start_time:~0,2%
set begin_minute=%start_time:~3,2%
set begin_second=%start_time:~6,2%

set ending_time=%2
set ending_hour=%ending_time:~0,2%
set ending_minute=%ending_time:~3,2%
set ending_second=%ending_time:~6,2%

set /a duration_time_in_hour=%ending_hour%-%begin_hour%
set /a duration_time_in_minute=%ending_minute%-%begin_minute%
set /a duration_time_in_second=%ending_second%-%begin_second%

if /i %duration_time_in_minute% lss 0 (
    set /a %duration_time_in_hour_1%=%duration_time_in_hour%-1
    set /a %duration_time_in_minute_1%=60%duration_time_in_minute%
)

if /i %duration_time_in_minute% lss 0 (
    if /i %duration_time_in_second% lss 0 (
        set /a %duration_time_in_minute_2%=%duration_time_in_minute_1%-1
        set /a %duration_time_in_second_1%=60%duration_time_in_second%
    ) else (
    if /i %duration_time_in_second% lss 0 (
        set /a %duration_time_in_minute_1%=%duration_time_in_minute%-1
        set /a %duration_time_in_second_1%=60%duration_time_in_second%
    )
)

if /i %duration_time_in_minute_2% lss 0 (
    set /a %duration_time_in_hour_2%=%duration_time_in_hour_1%-1
    set /a %duration_time_in_minute_3%=60%duration_time_in_minute_2%
)

Не могу понять как реализовать подсчет времени нормально

2

Re: CMD/BAT: Вычисление пройденного времени

Математически.

...Писал я как-то скрипт для замера времени, затраченного на выполнение скрипта/команды. Там было всё по взрослому, с милисекундами...

По сути и риторические вопросы:
- много кода, но я особо не вникал;
- что будет если время старта будет [до полуночи], а время окончания [после полуночи]? (помучился я с этим в свое время, но решение в принцыпе простое)
- "поразрядное" вычитание (h2-h1, m2-m1, s2-s1) неизбежно приводит к запутыванию и усложнению кода, а в итоге к морю ошибок.

3

Re: CMD/BAT: Вычисление пройденного времени

Алгоритм такой:

1) Сериализация: Приводим все разряды метки времени к наименьшему общнму знаменателю (секунда) и всё это складываем. Как вы наверно догадались, преобразуем таким макаром обе временные метки.

time=(h*3600)+(m*60)+(s)

2) Из time2 вычитаем time1. Получаем time3 - затраченное время в секундах

3) Десериализация полученного значения: Выполняем обратное преобразование time3 в hh:mm:ss.

(c)

ps: код чуть позже - с мобильника писать не совсем удобно

4

Re: CMD/BAT: Вычисление пройденного времени

Вот, наваял кое что. В качестве разделителя разрядов временных меток можно использовать символы из набора [;:,.]


@================================================================
::	Name:		 spendtime.bat
::	Language:	 batch
::	CommandLine: spendtime.bat time1 time2
::	Description: Пример вычисления затраченного времени на основе двух временных меток. 
::				 В качестве разделителя разрядов временной метки - символы из набора [;:,.]
::	Author:		 Аскет
@================================================================

@echo off
IF "%*"=="" (EXIT /B)
SET T1=%1
SET T2=%2

	::--------------- РАЗБИЕНИЕ МЕТКИ ВРЕМЕНИ НА РАЗРЯДЫ [hh,mm,ss] -------------
for /f "tokens=1,2,3 delims=;:,." %%a in ("%T1%") do (set h1=%%a & set m1=%%b & set s1=%%c)
for /f "tokens=1,2,3 delims=;:,." %%a in ("%T2%") do (set h2=%%a & set m2=%%b & set s2=%%c)

	::--------------- СЕРИАЛИЗАЦИЯ -------------
set /a time1 = (h1*3600)+(m1*60)+(s1)
set /a time2 = (h2*3600)+(m2*60)+(s2)
	::--------------- ВЫЧИСЛЕНИЕ -------------
set /a time3=time2-time1
	::--------------- ДЕСЕРИАЛИЗАЦИЯ [muchSS -> hh,mm,ss] -------------
set /a H = time3/3600
set /a time3 = time3-(H*3600)

set /a M = time3/60
set /a time3=time3-(M*60)

set /a S = time3

set spendTime=%H%:%M%:%S%

ECHO/Spend time = [%spendtime%]

5

Re: CMD/BAT: Вычисление пройденного времени

Аскет, надо бы добавить значащие нули в результат, по крайней мере в первый разряд к минутам и секундам.

6

Re: CMD/BAT: Вычисление пройденного времени

"По крайней мере" - это на один разряд, а тут по полной

Да и что вам мешает дополнить скрипт таким пустяком?

Эмм....Например, так (повторюсь: пишу с мобильника, поэтому могут быть синт. ашибки):


:CallMe (varIN,varOUT)
set /a temp = %1
if "%temp:~1,1%"=="" (SET %2=0%temp%)
EXIT /B

Поочерёдно прозваниваем функцию для каждого разряда (h,m,s).

7 (изменено: Аскет, 2011-05-28 09:27:15)

Re: CMD/BAT: Вычисление пройденного времени

Видимо, без моего Гения тут не обойтись ))

@================================================================
::	Name:		 spendtime.bat
::	Language:	 win-batch
::	CommandLine: spendtime.bat time1 time2
::	Description: Пример вычисления затраченного времени на основе двух временных меток. 
::				 В качестве разделителя разрядов временной метки - символы из набора [;:,.]
::	Author:		 Аскет
@================================================================

@echo off
IF "%*"=="" (EXIT /B)
SET T1=%1
SET T2=%2
	::--------------- РАЗБИЕНИЕ МЕТОК ВРЕМЕНИ НА РАЗРЯДЫ [hh,mm,ss] -------------
for /f "tokens=1,2,3 delims=;:,." %%a in ("%T1%") do (set h1=%%a & set m1=%%b & set s1=%%c)
for /f "tokens=1,2,3 delims=;:,." %%a in ("%T2%") do (set h2=%%a & set m2=%%b & set s2=%%c)
	::--------------- СЕРИАЛИЗАЦИЯ -------------
set /a time1 = (h1*3600)+(m1*60)+(s1)
set /a time2 = (h2*3600)+(m2*60)+(s2)
	::--------------- ВЫЧИСЛЕНИЕ -------------
set /a time3=time2-time1
	::--------------- ДЕСЕРИАЛИЗАЦИЯ [muchSS -> hh,mm,ss] -------------
::hour
set /a H = time3/3600
set /a time3 = time3-(H*3600)
::minute
set /a M = time3/60
set /a time3=time3-(M*60)
::second
set /a S = time3
	::--------------- CHECKING VALUES -------------
 CALL :CheckNum %H%,H
 CALL :CheckNum %M%,M
 CALL :CheckNum %S%,S

set spendTime=%H%:%M%:%S%
::show result
echo ______________________________
ECHO/Spend time = [%spendTime%]


EXIT /B
======================
:CheckNum (varIN,varOUT)
set /A temp = %1
if "%temp:~1,1%"=="" (SET %2=0%temp%)
EXIT /B
======================

8 (изменено: Александр_foxware, 2011-09-28 00:12:50)

Re: CMD/BAT: Вычисление пройденного времени

Спасибо за помощь. Просто отличное решение. Есть глюк с подсчетом если время начала находится на день раньше, но там всего одна строчка:


@================================================================
::    Name:         spendtime.bat
::    Language:     win-batch
::    CommandLine: spendtime.bat time1 time2
::    Description: Пример вычисления затраченного времени на основе двух временных меток. 
::                 В качестве разделителя разрядов временной метки - символы из набора [;:,.]
::    Author:         Аскет
@================================================================
 
@echo off
IF "%*"=="" (EXIT /B)
SET T1=%1
SET T2=%2
    ::--------------- РАЗБИЕНИЕ МЕТОК ВРЕМЕНИ НА РАЗРЯДЫ [hh,mm,ss] -------------
for /f "tokens=1,2,3 delims=;:,." %%a in ("%T1%") do (set h1=%%a & set m1=%%b & set s1=%%c)
for /f "tokens=1,2,3 delims=;:,." %%a in ("%T2%") do (set h2=%%a & set m2=%%b & set s2=%%c)
    ::--------------- СЕРИАЛИЗАЦИЯ -------------
set /a time1 = (h1*3600)+(m1*60)+(s1)
set /a time2 = (h2*3600)+(m2*60)+(s2)
    ::--------------- ВЫЧИСЛЕНИЕ -------------
set /a time3=time2-time1
if /i %time3% lss 0 set /a time3=time2+(86400-time1)
    ::--------------- ДЕСЕРИАЛИЗАЦИЯ [muchSS -> hh,mm,ss] -------------
::hour
set /a H = time3/3600
set /a time3 = time3-(H*3600)
::minute
set /a M = time3/60
set /a time3=time3-(M*60)
::second
set /a S = time3
    ::--------------- CHECKING VALUES -------------
 CALL :CheckNum %H%,H
 CALL :CheckNum %M%,M
 CALL :CheckNum %S%,S
 
set spendTime=%H%:%M%:%S%
::show result
echo ______________________________
ECHO/Spend time = [%spendTime%]
 
EXIT /B
======================
:CheckNum (varIN,varOUT)
set /A temp = %1
if "%temp:~1,1%"=="" (SET %2=0%temp%)
EXIT /B

Также если вдруг подсчет выполняется для отрезка времени больше одного дня, то просчет неверный. Если начальное время например 5 января 20.40, а конечное 6 января 22.35 - подсчет будет тоже неверным.

Но для меня такой скрипт вполне подходит, ибо у меня не больше 5 часов подсчет

9

Re: CMD/BAT: Вычисление пройденного времени

Оставлю тут, возможно кому-то пригодится. Проблема с переполнением из-за начала отдельного дня частично решена.

::===Функции работы со временем в .bat====================================
:: libTime.cmd, Anonymous, 2010
:ParseTimestamp
:: Разбирает на составляющие временную метку формата ЧЧ:ММ:СС
:: Формат:   Call :ParseTimestamp (время)
:: К примеру - Call :ParseTimestamp %time:~-0,8%
:: Вывод - в переменные HH MM и SS
For /F "tokens=1,2,3 delims=:" %%A In ("%1") Do (
Set HH=%%A
Set MM=%%B
Set SS=%%C
)

:SerializeTime
:: Сериализует время из переменных HH MM и SS
:: Вывод - в ErrorLevel
Set /A STime=(HH*60*60)+(MM*60)+SS
Exit /B %STime%

:DeserializeTime
:: Десериализует время, приводит его к стандартному формату
:: Формат:   Call :DeserializeTime (сериализованное время)
:: Вывод - в переменные DHH DMM и DSS
Set /A DHH=%1/60/60
Set /A DMM=(%1/60)-(DHH*60)
Set /A DSS=%1-(DHH*60*60)-(DMM*60)
If %DHH%==24 Set DHH=00
If %DHH% LSS 10 Set DHH=0%DHH%
If %DMM% LSS 10 Set DMM=0%DMM%
If %DSS% LSS 10 Set DSS=0%DSS%
Exit /B

:TMinus
:: Функция вычитания для сериализованного времени
:: Формат:   Call :TMinus (сериализованное время) (сколько секунд отнять)
:: Вывод - в ErrorLevel
Set /A Result=%1-%2
If %2 GTR %1 (
Set /A Result=86400+%1-%2
)
Exit /B %Result%

:TPlus
:: Функция прибавления для сериализованного времени
:: Формат:   Call :TPlus (сериализованное время) (сколько секунд прибавить)
:: Вывод - в ErrorLevel
Set /A Result=%1+%2
If %Result% GTR 86400 (
Set /A Result=%1+%2-86400
)
Exit /B %Result%

:Timer
:: Отсчитывает прошедшее с заданного момента время
:: Формат:   Call :Timer (запомненное сериализованное время)
:: Вывод - в ErrorLevel
:: Если счетчик переходит границу суток, число дней возрастает на 1
:: Дни выводятся в переменную ED (и накапливаются) // да, знаю, что костыль и быдлокод
Set OTime=%1
If "%ED%"=="" Set ED=0
Call :ParseTimestamp %time:~-0,8%
Call :SerializeTime
Set CTime=%ErrorLevel%
If %OTime% GTR %CTime% (
Set /A Timer=86400-%OTime%+%CTime%
Set /A ED+=1
) Else (
Set /A Timer=CTime-OTime
)
Exit /B %Timer%

:Timer2
:: Проверяет, прошел ли заданный промежуток времени
:: Формат:   Call :Timer2 (запомненное сериализованное время) (промежуток в секундах)
:: Вывод - в ErrorLevel (только 0=промежуток истёк или 1=промежуток ещё не истёк)
Call :ParseTimestamp %time:~-0,8%
Call :SerializeTime
Call :TMinus %ErrorLevel% %1
If %2 GTR %ErrorLevel% Exit /B 1
Exit /B 0
::========================================================================

10

Re: CMD/BAT: Вычисление пройденного времени

оно конечно так оно, а как быть если позже меньше чем раньше ?

Я конечно далек от мысли... (с)