Имя пользователя:
Пароль:  
Помощь | Регистрация | Забыли пароль?  | Правила  

Компьютерный форум OSzone.net » Программирование, базы данных и автоматизация действий » Программирование и базы данных » Delphi - Конвертирование времени

Ответить
Настройки темы
Delphi - Конвертирование времени

Пользователь


Сообщения: 108
Благодарности: 0


Конфигурация

Профиль | Отправить PM | Цитировать


Добрый день. Не так давно решил переписать участки с говнокодом в программе, до этого не было времени, а функции были не важные, сейчас переработал два куска кода, но после исправления второго нечаянно обнаружил проблему. Сама функция занимается переводом секунд в минуты, часы... казалось, что проще, оказалось и тут проблема есть. Привожу код:
Код: Выделить весь код
function ConvertTime(timeExt: Extended):string;
var m, w, d, h, min, sec: Int64;
begin
  m := Trunc(Convert(timeExt, tuSeconds, tuMonths));
  timeExt := timeExt - m * 2592000;
  w := Trunc(Convert(timeExt, tuSeconds, tuWeeks));
  timeExt := timeExt - w * 604800;
  d := Trunc(Convert(timeExt, tuSeconds, tuDays));
  timeExt := timeExt - d * 86400;
  h := Trunc(Convert(timeExt, tuSeconds, tuHours));
  timeExt := timeExt - h * 3600;
  min := Trunc(Convert(timeExt, tuSeconds, tuMinutes));
  sec := Trunc(timeExt - min * 60);
  if m <> 0 then Result := IntToStr(m) + ' мес ';
  if w <> 0 then Result := Result + IntToStr(w) + ' нед ';
  if d <> 0 then Result := Result + IntToStr(d) + ' д ';
  if h <> 0 then Result := Result + IntToStr(h) + ' ч ';
  if min <> 0 then Result := Result + IntToStr(min) + ' м ';
  if sec <> 0 then Result := Result + IntToStr(sec) + ' с ';
  if (m = 0) and (w = 0) and (d = 0) and (h = 0) and (min = 0) and (sec = 0)
  then Result := '0 c';
end;
Вроде как все нормально, но обнаружил проблему неправильного подсчета, если взять кол-во секунд примерно на 18 месяцев то при переводе данной функцией выйдет 17 месяцев 5 недель ... и при увеличении исходного числа недели,дни... будут расти превышая допустимые значения(7 дней, 24 часа...). Жду идеи

Отправлено: 14:35, 21-08-2012

 

Аватара для opel431

Ветеран


Contributor


Сообщения: 1803
Благодарности: 714

Профиль | Отправить PM | Цитировать


Можно попробовать не отсекать дробную часть (TRUNC), а округлять возвращаемое целое - ROUND(Int(...).
А, вообще, мне кажется, лучше измерять интервал используя TDateTime (1 сек = 1 / (24 * 60 * 60).

-------
Хвала тому, кто встав среди камней, уча другого, сам будет умней.


Последний раз редактировалось opel431, 21-08-2012 в 23:23.

Это сообщение посчитали полезным следующие участники:

Отправлено: 23:12, 21-08-2012 | #2



Для отключения данного рекламного блока вам необходимо зарегистрироваться или войти с учетной записью социальной сети.

Если же вы забыли свой пароль на форуме, то воспользуйтесь данной ссылкой для восстановления пароля.


Пользователь


Сообщения: 108
Благодарности: 0

Профиль | Отправить PM | Цитировать


Цитата:
округлять возвращаемое целое
не совсем понял, у меня возвращается вещественное число, если его округлить получится совсем не то, а целое из вещественного можно получить либо round либо trunc.
Цитата:
лучше измерять интервал используя TDateTime
нет, интервал лучше замерять TTimeStamp, но мне не интервал времени измерить надо, мне нужно перевести переменную с кол-вом секунд в удобочитаемое юзеру часы, дни....
Цитата:
ROUND(Int(...)
кстати такой структуры нет, единственный вариант - random(integer(...)), типа такого, тогда здесь ограничивается выбор чисел только целыми

Отправлено: 00:16, 22-08-2012 | #3


Аватара для opel431

Ветеран


Contributor


Сообщения: 1803
Благодарности: 714

Профиль | Отправить PM | Цитировать


Цитата novashdima:
кстати такой структуры нет »
Почему нет?
http://www.delphicode.org/math/Trunc_function.htm

читать дальше »
Одна секунда в формате TDateTime равна: 1 / (24 * 60 * 60). Поэтому, если задан некоторый временной интервал Dt в формате TDateTime, то количество секунд в нём равно:
CntSec = Dt / ( 1 / (24 * 60 * 60) ) = Dt * (24 * 60 * 60).
Соответственно, можно функцию написать:Код Delphi
function GetSec(const aPeriod : TDateTime) : Int64;
const
K = 24 * 60 * 60;
begin
Result := Round( Int(aPeriod * K) );
end;
Источник - http://www.cyberforum.ru/delphi-begi...ead325164.html

-------
Хвала тому, кто встав среди камней, уча другого, сам будет умней.


Отправлено: 02:24, 22-08-2012 | #4


Пользователь


Сообщения: 108
Благодарности: 0

Профиль | Отправить PM | Цитировать


Цитата opel431:
Почему нет? »
Извиняюсь, совсем забыл про такую функцию, да и не удивительно, я ею не пользуюсь, вообще ненужная функция, обычно отбрасывают часть или округляют чтобы получить целое число, а эта функция вернет целое число, но в формате вещественного, если нужно вещественное число, то IntToFloat никто не отменял... ну да ладно.
насчет главного вопроса, пока сделал простым делением, но хотелось бы все таки понять, почему не работает этот вариант перевода. Кстати пробовал также написать более грамотно, борясь с возможными лагами и т.д., но главный баг (а может это и не баг) так и остался, вот доработанный код:
Код: Выделить весь код
function ConvertTime(timeExt: Extended):string;
var m, w, d, h, min, sec: Int64;
begin
  m := Trunc(Convert(timeExt, tuSeconds, tuMonths));
  timeExt := timeExt - Trunc(Convert(m, tuMonths, tuSeconds));
  w := Trunc(Convert(timeExt, tuSeconds, tuWeeks));
  timeExt := timeExt - Trunc(Convert(w, tuWeeks, tuSeconds));
  d := Trunc(Convert(timeExt, tuSeconds, tuDays));
  timeExt := timeExt - Trunc(Convert(d, tuDays, tuSeconds));
  h := Trunc(Convert(timeExt, tuSeconds, tuHours));
  timeExt := timeExt - Trunc(Convert(h, tuHours, tuSeconds));
  min := Trunc(Convert(timeExt, tuSeconds, tuMinutes));
  sec := timeExt - Trunc(Convert(min, tuMinutes, tuSeconds));
  if m <> 0 then Result := IntToStr(m) + ' мес ';
  if w <> 0 then Result := Result + IntToStr(w) + ' нед ';
  if d <> 0 then Result := Result + IntToStr(d) + ' д ';
  if h <> 0 then Result := Result + IntToStr(h) + ' ч ';
  if min <> 0 then Result := Result + IntToStr(min) + ' м ';
  if sec <> 0 then Result := Result + IntToStr(sec) + ' с ';
  if (m = 0) and (w = 0) and (d = 0) and (h = 0) and (min = 0) and (sec = 0)
  then Result := '0 c';
end;

Отправлено: 04:04, 22-08-2012 | #5


Новый участник


Сообщения: 40
Благодарности: 19

Профиль | Отправить PM | Цитировать


Вот еще пример конвертации секунд. Я правда остановился на днях, но мне больше и не надо было
Код: Выделить весь код
function SecToTimeStr(Seconds : Integer) : String;
const
  SecPerDay = 86400;
  SecPerHour = 3600;
  SecPerMinute = 60;

var
   dd, ss, mm, hh: Cardinal;
   str : String;
begin
  str := '';
  dd := Seconds div SecPerDay;
  hh := (Seconds mod SecPerDay) div SecPerHour;
  mm := ((Seconds mod SecPerDay) mod SecPerHour) div SecPerMinute;
  ss := ((Seconds mod SecPerDay) mod SecPerHour) mod SecPerMinute;
  str := Format('%2.2d:%2.2d:%2.2d',[hh,mm,ss]);
  if dd>0 then
    str := Format('%d дн ',[dd])+str;
  result := str;
end;

Отправлено: 11:38, 22-08-2012 | #6


Пользователь


Сообщения: 108
Благодарности: 0

Профиль | Отправить PM | Цитировать


AlexVol, я тоже переделал код до обычного деления, у меня чуть попроще получилось, хотя кое какие упрощения мне подсказали)
Код: Выделить весь код
function DivAndMod(var Value : Int64; Divider : Byte):Int64;
begin
 Result := Value mod Divider;
 Value := Value div Divider;
end;

function ConvertTime(m: Int64):string;
var m, w, d, h, min, sec: Int64;
begin
  sec := DivAndMod(m, 60);
  min := DivAndMod(m, 60);
  h := DivAndMod(m, 24);
  w := DivAndMod(m, 30);
  d := DivAndMod(w, 7);
//остальные действия
end;

Отправлено: 14:30, 22-08-2012 | #7


Пользователь


Сообщения: 108
Благодарности: 0

Профиль | Отправить PM | Цитировать


Цитата AlexVol:
SecPerDay = 86400; »
кстати в делфи существует константа SecsPerDay, которая равна вашим 86400, поэтому вводить новую не обязательно)

Отправлено: 03:22, 24-08-2012 | #8


Новый участник


Сообщения: 40
Благодарности: 19

Профиль | Отправить PM | Цитировать


Но так как других нет, то для наглядности лучше забить свою. Много усилий это не займет.

Отправлено: 12:01, 24-08-2012 | #9


Пользователь


Сообщения: 108
Благодарности: 0

Профиль | Отправить PM | Цитировать


Цитата AlexVol:
Много усилий это не займет. »
И это верно.

Отправлено: 21:22, 25-08-2012 | #10



Компьютерный форум OSzone.net » Программирование, базы данных и автоматизация действий » Программирование и базы данных » Delphi - Конвертирование времени

Участник сейчас на форуме Участник сейчас на форуме Участник вне форума Участник вне форума Автор темы Автор темы Шапка темы Сообщение прикреплено

Похожие темы
Название темы Автор Информация о форуме Ответов Последнее сообщение
Конвертирование MKV Den47 Видео и аудио: обработка и кодирование 2 29-06-2008 22:54
Теория - Конвертирование xls в jpg Surround Программирование и базы данных 13 27-01-2008 17:50
Конвертирование вэб страниц Noel Вебмастеру 2 03-04-2007 01:37
Конвертирование FAT32 в NTFS Uber Microsoft Windows 2000/XP 2 27-03-2007 21:33
Конвертирование баз данных han Программирование и базы данных 2 08-12-2005 00:30




 
Переход