Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / Delphi Новый топик    Ответить
Топик располагается на нескольких страницах: 1 2      [все]
 Проблема округления даты (Double)  [new]
Lisichkin
Member

Откуда:
Сообщений: 474
Помогите! На Delphi 7 следующий код возвращает 0

uses DateUtils;

procedure TForm1.Button1Click(Sender: TObject);
var
  i: Integer;
  D1, D2: TDateTime;
begin
  D1 := StrToDateTime('25.11.20 00:00');
  D2 := StrToDateTime('24.11.20 23:00');
  i := HoursBetween(D1, D2);
  ShowMessage(IntToStr(i));
end;
17 ноя 20, 20:27    [22234152]     Ответить | Цитировать Сообщить модератору
 Re: Проблема округления даты (Double)  [new]
wadman
Member

Откуда: Санкт-Петербург
Сообщений: 26836
D1 и D2 - точно даты со временем после преобразования?
17 ноя 20, 20:29    [22234154]     Ответить | Цитировать Сообщить модератору
 Re: Проблема округления даты (Double)  [new]
defecator
Member

Откуда:
Сообщений: 39394
wadman
D1 и D2 - точно даты со временем после преобразования?

я уже не помню точно, но не должна ли быть D1 меньше (либо равна) D2 ?
17 ноя 20, 20:34    [22234156]     Ответить | Цитировать Сообщить модератору
 Re: Проблема округления даты (Double)  [new]
Lisichkin
Member

Откуда:
Сообщений: 474
Все хуже:
HoursBetween = Round((D2-D1)*24)
(ABS я пропустил)
Так вот (D2-D1)*24 = 0.99999
17 ноя 20, 20:39    [22234157]     Ответить | Цитировать Сообщить модератору
 Re: Проблема округления даты (Double)  [new]
_Vasilisk_
Member

Откуда: Украина, Харьков
Сообщений: 12319
А если так?
  D1 := StrToDateTime('25.11.2020 00:00');
  D2 := StrToDateTime('24.11.2020 23:00');
17 ноя 20, 20:48    [22234160]     Ответить | Цитировать Сообщить модератору
 Re: Проблема округления даты (Double)  [new]
_Vasilisk_
Member

Откуда: Украина, Харьков
Сообщений: 12319
Lisichkin,

Посмотрите в DateUtils код HoursBetween. В XE3 такое
function HoursBetween(const ANow, AThen: TDateTime): Int64;
begin
  Result := Abs(DateTimeToMilliseconds(ANow) - DateTimeToMilliseconds(AThen))
    div (MSecsPerSec * SecsPerMin * MinsPerHour);
end;
17 ноя 20, 20:54    [22234165]     Ответить | Цитировать Сообщить модератору
 Re: Проблема округления даты (Double)  [new]
defecator
Member

Откуда:
Сообщений: 39394
в древнем xe7/8 всё чОтко

К сообщению приложен файл. Размер - 13Kb
17 ноя 20, 21:46    [22234202]     Ответить | Цитировать Сообщить модератору
 Re: Проблема округления даты (Double)  [new]
ъъъъъ
Member

Откуда:
Сообщений: 1350
Может, в системе у ТС нестандартный формат времени?
17 ноя 20, 21:50    [22234204]     Ответить | Цитировать Сообщить модератору
 Re: Проблема округления даты (Double)  [new]
DimaBr
Member

Откуда:
Сообщений: 11910
старо
тынц

Сообщение было отредактировано: 17 ноя 20, 22:04
17 ноя 20, 22:01    [22234211]     Ответить | Цитировать Сообщить модератору
 Re: Проблема округления даты (Double)  [new]
DimaBr
Member

Откуда:
Сообщений: 11910


К сообщению приложен файл. Размер - 18Kb
17 ноя 20, 22:11    [22234217]     Ответить | Цитировать Сообщить модератору
 Re: Проблема округления даты (Double)  [new]
_Vasilisk_
Member

Откуда: Украина, Харьков
Сообщений: 12319
DimaBr,

Там Trunc вместо Round стоит?
18 ноя 20, 12:53    [22234524]     Ответить | Цитировать Сообщить модератору
 Re: Проблема округления даты (Double)  [new]
alekcvp
Member

Откуда:
Сообщений: 2494
_Vasilisk_,
Ну вообще это логично: 59 минут - это не час. Но вот погрешность они не учли...
18 ноя 20, 12:57    [22234527]     Ответить | Цитировать Сообщить модератору
 Re: Проблема округления даты (Double)  [new]
s62
Member

Откуда: Жуковский
Сообщений: 1199
Ещё один повод перейти с Delphi 7 на что-то более новое.
18 ноя 20, 13:25    [22234554]     Ответить | Цитировать Сообщить модератору
 Re: Проблема округления даты (Double)  [new]
Lisichkin
Member

Откуда:
Сообщений: 474
К сожалению, в рамках моего проекта перейти на другую версию не возможно.

Лечится так (взял кусок из Delphi XE):
function DateTimeToMilliseconds(const ADateTime: TDateTime): Int64;
var
  LTimeStamp: TTimeStamp;
begin
  LTimeStamp := DateTimeToTimeStamp(ADateTime);
  Result := LTimeStamp.Date;
  Result := (Result * MSecsPerDay) + LTimeStamp.Time;
end;

function HoursBetween(const ANow, AThen: TDateTime): Int64;
begin
  Result := Abs(DateTimeToMilliseconds(ANow) - DateTimeToMilliseconds(AThen))
    div (MSecsPerSec * SecsPerMin * MinsPerHour);
end;

procedure TForm1.Button1Click(Sender: TObject);
var
  i: Integer;
  D1, D2: TDateTime;
begin
  D1 := StrToDateTime('25.11.20 00:00');
  D2 := StrToDateTime('24.11.20 23:00');
  i := HoursBetween(D1, D2);
  ShowMessage(IntToStr(i));
end;


P.S.
Даты произвольны и никогда не приходят в систему из StrToDateTime - а взяты из базы.

Сообщение было отредактировано: 18 ноя 20, 17:39
18 ноя 20, 17:42    [22234792]     Ответить | Цитировать Сообщить модератору
 Re: Проблема округления даты (Double)  [new]
rgreat
Member

Откуда:
Сообщений: 6312
Извращенец.

(D1-D2) * 24 = кол-во часов.
18 ноя 20, 17:44    [22234800]     Ответить | Цитировать Сообщить модератору
 Re: Проблема округления даты (Double)  [new]
DimaBr
Member

Откуда:
Сообщений: 11910
rgreat
Извращенец.
(D1-D2) * 24 = кол-во часов.

Не работает

К сообщению приложен файл. Размер - 12Kb
18 ноя 20, 18:42    [22234846]     Ответить | Цитировать Сообщить модератору
 Re: Проблема округления даты (Double)  [new]
_Vasilisk_
Member

Откуда: Украина, Харьков
Сообщений: 12319
DimaBr
Не работает
А как должно работать? Ну сделай так
Trunc((D1 - D2) * 24 + 1 / 36000001)
18 ноя 20, 19:02    [22234863]     Ответить | Цитировать Сообщить модератору
 Re: Проблема округления даты (Double)  [new]
defecator
Member

Откуда:
Сообщений: 39394
_Vasilisk_
DimaBr
Не работает
А как должно работать? Ну сделай так
Trunc((D1 - D2) * 24 + 1 / 36000001)


формула отработает правильно, если D1 > D2
Если D1 < D2, то будет отрицательное значение +1 лишний час
18 ноя 20, 20:58    [22234925]     Ответить | Цитировать Сообщить модератору
 Re: Проблема округления даты (Double)  [new]
rgreat
Member

Откуда:
Сообщений: 6312
DimaBr
rgreat
Извращенец.
(D1-D2) * 24 = кол-во часов.

Не работает
Чего у тебя не работает?
Работа функции Round не соответствует твоим ожиданиям? ;)

Что ты написал - то и получил.
Чего хотел-то?

Сообщение было отредактировано: 18 ноя 20, 21:16
18 ноя 20, 21:19    [22234935]     Ответить | Цитировать Сообщить модератору
 Re: Проблема округления даты (Double)  [new]
_Vasilisk_
Member

Откуда: Украина, Харьков
Сообщений: 12319
defecator
формула отработает правильно, если D1 > D2
Abs подразумевался
defecator
Если D1 < D2, то будет отрицательное значение +1 лишний час
Заменить Trunc ()на Int()
18 ноя 20, 21:46    [22234943]     Ответить | Цитировать Сообщить модератору
 Re: Проблема округления даты (Double)  [new]
defecator
Member

Откуда:
Сообщений: 39394
_Vasilisk_
defecator
формула отработает правильно, если D1 > D2
Abs подразумевался
defecator
Если D1 < D2, то будет отрицательное значение +1 лишний час
Заменить Trunc ()на Int()


не поможет
25.11.20 00:00 - 24.11.20 23:00 по формуле получится 23
24.11.20 00:00 - 25.11.20 23:00 по формуле получится -24

Сообщение было отредактировано: 18 ноя 20, 21:50
18 ноя 20, 21:54    [22234949]     Ответить | Цитировать Сообщить модератору
 Re: Проблема округления даты (Double)  [new]
DimaBr
Member

Откуда:
Сообщений: 11910
rgreat

>Работа функции Round не соответствует твоим ожиданиям?
Моим соответствует.

>Что ты написал - то и получил.
Что ты предложил, то я и написал, демонстрируя, что твоё предложение не работает
18 ноя 20, 21:56    [22234951]     Ответить | Цитировать Сообщить модератору
 Re: Проблема округления даты (Double)  [new]
rgreat
Member

Откуда:
Сообщений: 6312
DimaBr
Моим соответствует.

Зачем ты тогда такую дичь с подобными округлениями написал?
Что бы запутать топик стартера?

Что ты предложил, то я и написал, демонстрируя, что твоё предложение не работает

Т.е. ты не согласен с моим утверждением что "(D1-D2) * 24 = кол-во часов."?
Картинка с другого сайта.

А уж как правильно double в integer перевести - это как бы должно быть известно каждому.
Да и не ясно, надо ли вообще в int переводить.

Сообщение было отредактировано: 18 ноя 20, 22:00
18 ноя 20, 22:03    [22234955]     Ответить | Цитировать Сообщить модератору
 Re: Проблема округления даты (Double)  [new]
DimaBr
Member

Откуда:
Сообщений: 11910
rgreat

>Зачем ты тогда такую дичь с подобными округлениями написал?
Предложи свой вариант округления, согласно своей же формуле

>Что бы запутать топик стартера?
Топикстартер уже нашёл верное решение, считать НЕ РАЗНИЦУ В ДАТАХ, а разницу в МИЛЛИСЕКУНДАХ

>Т.е. ты не согласен с моим утверждением что "(D1-D2) * 24 = кол-во часов."?
Как видишь, твоя идея с разницей в датах натыкается на погрешность
18 ноя 20, 22:28    [22234970]     Ответить | Цитировать Сообщить модератору
 Re: Проблема округления даты (Double)  [new]
rgreat
Member

Откуда:
Сообщений: 6312
DimaBr
Предложи свой вариант округления, согласно своей же формуле

Цель этого "округления"-то хоть какая?
18 ноя 20, 22:31    [22234971]     Ответить | Цитировать Сообщить модератору
 Re: Проблема округления даты (Double)  [new]
DimaBr
Member

Откуда:
Сообщений: 11910
Цель любого округления получить цельночисленное значение. Топикстартеру не нужно 0,9999999999 часов
18 ноя 20, 22:51    [22234986]     Ответить | Цитировать Сообщить модератору
 Re: Проблема округления даты (Double)  [new]
rgreat
Member

Откуда:
Сообщений: 6312
Вместо ответа на вопрос демагогия пошла.
18 ноя 20, 23:38    [22235009]     Ответить | Цитировать Сообщить модератору
 Re: Проблема округления даты (Double)  [new]
rgreat
Member

Откуда:
Сообщений: 6312
Если надо "кол-во полных часов между двумя датами":

Res:=Trunc(Abs(d1-d2)*24+0.0000000001);

P.S. При решении через DateTimeToMilliseconds стоит уменьшить зазор в часу менее чем 1 мсек получается прикол.
function HoursBetween(const ANow, AThen: TDateTime): Int64;
begin
  Result := Abs(DateTimeToMilliseconds(ANow) - DateTimeToMilliseconds(AThen))
    div (MSecsPerSec * SecsPerMin * MinsPerHour);
end;

begin
  var D1 := StrToDateTime('25.11.20 00:00');
  var D2 := StrToDateTime('24.11.20 23:00')+1/24/3600/10000;
  writeln(Trunc(Abs(D1-D2)*24+0.0000000001));
  writeln(HoursBetween(D1,D2));
end.

0
1

Мой подход и точнее и быстрей. Как-то так.

Сообщение было отредактировано: 19 ноя 20, 00:17
19 ноя 20, 00:13    [22235014]     Ответить | Цитировать Сообщить модератору
 Re: Проблема округления даты (Double)  [new]
alekcvp
Member

Откуда:
Сообщений: 2494
rgreat
Мой подход и точнее и быстрей. Как-то так.

С чего он точнее, если выдаёт час при интервале меньше часа?..

Тогда уж правильнее сделать функцию
function HoursBetween(...; AccuracyMSec: Double): Integer;
, где AccuracyMSec - точность определения интервала в миллисекундах.
19 ноя 20, 10:23    [22235122]     Ответить | Цитировать Сообщить модератору
 Re: Проблема округления даты (Double)  [new]
defecator
Member

Откуда:
Сообщений: 39394
alekcvp
rgreat
Мой подход и точнее и быстрей. Как-то так.

С чего он точнее, если выдаёт час при интервале меньше часа?..

Тогда уж правильнее сделать функцию
function HoursBetween(...; AccuracyMSec: Double): Integer;

, где AccuracyMSec - точность определения интервала в миллисекундах.


тогда уж выдавать разницу в секундах, а не в часах.
а дальше пусть кому как надо округляют
19 ноя 20, 11:01    [22235150]     Ответить | Цитировать Сообщить модератору
 Re: Проблема округления даты (Double)  [new]
alekcvp
Member

Откуда:
Сообщений: 2494
defecator
тогда уж выдавать разницу в секундах, а не в часах.
а дальше пусть кому как надо округляют

999 мсек - это одна секунда или ноль?.. А 999.99?

Сообщение было отредактировано: 19 ноя 20, 11:32
19 ноя 20, 11:36    [22235185]     Ответить | Цитировать Сообщить модератору
 Re: Проблема округления даты (Double)  [new]
defecator
Member

Откуда:
Сообщений: 39394
alekcvp
defecator
тогда уж выдавать разницу в секундах, а не в часах.
а дальше пусть кому как надо округляют

999 мсек - это одна секунда или ноль?.. А 999.99?


я написал - в секундах

defecator

тогда уж выдавать разницу в секундах, а не в часах.
а дальше пусть кому как надо округляют


Сообщение было отредактировано: 19 ноя 20, 11:53
19 ноя 20, 11:58    [22235205]     Ответить | Цитировать Сообщить модератору
 Re: Проблема округления даты (Double)  [new]
rgreat
Member

Откуда:
Сообщений: 6312
alekcvp
rgreat
Мой подход и точнее и быстрей. Как-то так.

С чего он точнее, если выдаёт час при интервале меньше часа?.
Где?!
19 ноя 20, 12:27    [22235227]     Ответить | Цитировать Сообщить модератору
 Re: Проблема округления даты (Double)  [new]
alekcvp
Member

Откуда:
Сообщений: 2494
rgreat
alekcvp
пропущено...
С чего он точнее, если выдаёт час при интервале меньше часа?.
Где?!

Вот здесь:
  var D2 := StrToDateTime('24.11.20 23:00')+1/24/3600/10000;
19 ноя 20, 12:34    [22235235]     Ответить | Цитировать Сообщить модератору
 Re: Проблема округления даты (Double)  [new]
alekcvp
Member

Откуда:
Сообщений: 2494
defecator
alekcvp
пропущено...

999 мсек - это одна секунда или ноль?.. А 999.99?

я написал - в секундах
defecator

тогда уж выдавать разницу в секундах, а не в часах.
а дальше пусть кому как надо округляют

И? Разница в 999 мсек - это разница в одну секунду или в ноль секунд?
А почему именно в секундах, а не в миллисекундах?
А почему именно в одну, а не в 0.1?

Вообще весь вопрос в том - насколько точно может время определять компьютер и к этой точности привязаться при определении интервалов, с учётом погрешности округления Double.

Сообщение было отредактировано: 19 ноя 20, 12:31
19 ноя 20, 12:35    [22235236]     Ответить | Цитировать Сообщить модератору
 Re: Проблема округления даты (Double)  [new]
rgreat
Member

Откуда:
Сообщений: 6312
alekcvp,

Где мой код выдает 1?
То что ты зацитировал это задание входных параметров.
При них мой код выдает 0.

Сообщение было отредактировано: 19 ноя 20, 12:46
19 ноя 20, 12:50    [22235248]     Ответить | Цитировать Сообщить модератору
 Re: Проблема округления даты (Double)  [new]
alekcvp
Member

Откуда:
Сообщений: 2494
rgreat
alekcvp,

Где мой код выдает 1?
То что ты зацитировал это задание входных параметров.
При них мой код выдает 0.

Да, перепутал, извини :)
19 ноя 20, 13:01    [22235260]     Ответить | Цитировать Сообщить модератору
Топик располагается на нескольких страницах: 1 2      [все]
Все форумы / Delphi Ответить