Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Прочее";
Текущий архив: 2010.09.05;
Скачать: [xml.tar.bz2];

Вниз

Работа TDateTime в отрицательном диапазоне   Найти похожие ветки 

 
bss   (2010-06-10 13:52) [0]

Не понимаю, почему реализовали именно такое поведение функций преобразования даты в строку. Для тех кто не в курсе - краткий ликбез:

Начало отсчета - значение ноль, интерпретируется как:
FormatDateTime("dd.mm.yyyy hh:nn:ss.zzz" , 0) = 30.12.1899  00:00:00.00

А вот дальше интереснее. Пример 1:

FormatDateTime("dd.mm.yyyy hh:nn:ss.zzz" , +0.5) = 30.12.1899  12:00:00.00

Что логично. Но вот:

FormatDateTime("dd.mm.yyyy hh:nn:ss.zzz" , -0.5) = 30.12.1899  12:00:00.00

Одна и та же дата, что уже не так логично...

Пример 2:

FormatDateTime("dd.mm.yyyy hh:nn:ss.zzz" , -1.25) = 29.12.1899  06:00:00.00

Хотя в теории логичнее, чтобы получилось: 28.12.1899  18:00:00.00

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

То есть, значение "-1.5" интерпретируется как полдня в прошлое относительно нуля. Сначала вычитается "1" день, а потом прибавляется еще полдня, получается полдня в прошлое.

Мне крайне непонятно, зачем нарушать с виду очень естественную линию времени. "1.5" - это полтора дня в будущее относительно нулевой даты, "-1.5" - это полтора дня в прошлое относительно нулевой даты.
Никаких проблем при работе с датой, нужно прибавить один день к дате - прибавляй, нужно отнять - отнимай, независимо в каком диапазоне ты работаешь. Разница между двумя датами всегда находится вычитанием... Это же логично.

Почему же реализовано именно так, как реализовано? Я бы мог назвать это ошибкой, но это не исправляется годами. Задокументировано в хелпе, написано что между "0" и "-1" дат типа вообще нету, а если хотите работать с отрицательными датами - то, мол, вручную складывайте отдельно целую и дробную часть.

Зачем такое, если бы просто можно было немного переписать функции конвертации времени? Вполне возможно, что это чем-то обосновано, но я абсолютно не понимаю чем. Любопытство, может кто знает историю вопроса...


 
Dimka Maslov ©   (2010-06-10 13:55) [1]

99.999999999999% пользователей никогда не будут работать с датами, относящимися к 19 веку.


 
Медвежонок Пятачок ©   (2010-06-10 13:59) [2]

Гораздо дальновиднее иметь возможность "Дат вообще нету"  (даже если это сейчас не используется)

Чем иметь ситуацию "любой дабл - это валидная дата"


 
Медвежонок Пятачок ©   (2010-06-10 14:05) [3]

кроме того, с арифметикой там тоже все в порядке

ShowMessage(IntToStr(Trunc(Double(EncodeDate(1899,12,30))) - Trunc(Double(EncodeDate(1899,12,29)))));

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


 
bss   (2010-06-10 14:15) [4]

Dimka Maslov, согласен. Но почему бы не исправить? Тем более глюк базовый, в работе базового так сказать типа TDateTime, пусть и в очень редко используемых диапазонах.

Более того, описывать этот глюк в хелпе мне кажется дольше по времени, чем его исправить. А то хелп жжот напалмом - говорит о том, что между "0" и "-1" нету дат. А на самом деле просто между "0" и "-1" все даты соответствуют положительным датам от "0" до "+1".


 
Медвежонок Пятачок ©   (2010-06-10 14:16) [5]

если для реализации типа "дата" (время пока не учитываем) взята шкала натуральных чисел, то на ней есть ноль.
а нулевой даты нету.

если "первая" дата это 30.12.1899, то предыдущая дата не "нулевая".
она "вчерашняя"

то есть интервал от -1 до 0 это и есть олицетворение несуществующей "нулевой" даты

при сотворении мира сразу была "первая" дата. а "днем ранее" была не "нулевая "дата, а "вчерашняя" (один день до нашей эры)


 
Anatoly Podgoretsky ©   (2010-06-10 14:19) [6]

> bss  (10.06.2010 13:52:00)  [0]

А у тебя случайно не 12 часовая шкала в системе?


 
bss   (2010-06-10 14:22) [7]


> кроме того, с арифметикой там тоже все в порядке
> ShowMessage(IntToStr(Trunc(Double(EncodeDate(1899,12,30)))
> - Trunc(Double(EncodeDate(1899,12,29)))));
> интервал в один день. несмотря на то, что оперируем чистым
> даблом.


ну понятно. Медвежонок не читатель, Медвежонок писатель? ))

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


 
bss   (2010-06-10 14:24) [8]


> А у тебя случайно не 12 часовая шкала в системе?


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


 
Медвежонок Пятачок ©   (2010-06-10 14:26) [9]

Ты сам-то читаешь?

Голая арифметика с приведенными к даблу датами дает правильный результат.
Где ты там у бордланда увидел  нелогичность с точки зрения интервала?


 
Dimka Maslov ©   (2010-06-10 14:29) [10]


> Но почему бы не исправить?


Однажды к нам в контору приехал разработчик одной используемой нами программы. Мы ему показали сделанную нами вспомогательную программку, которая существенно облегчает процесс выполнения работы. Также мы предложили ему бесплатно передать исходники, дабы они вставили нашу разработку к себе. Он ответил, что всё это хорошо, но подавляющее большинство пользователей, в силу различных причин, никогда не будут применять это у себя, ибо их уровень гораздо ниже нашего. А следовательно, вставлять эту процедуру невыгодно. Это бизнес.

Мораль: если нужны "отрицательные" даты — делай их самостоятельно.


 
Медвежонок Пятачок ©   (2010-06-10 14:31) [11]

берем шкалу дабла и точку 0 на ней.

Это 0 часов о минут 30 января 1899 года.

Идем влево от нуля на 0.5

Где мы оказываемся с точки зрения времени?
Мы оказываемся во вчера.

итого: если бы борланд принял -0.5 за полдень 29 декабря 1899 года, то

Trunc(0 - 0.5) = 0

И привет семье. Сегодня как бы и 30 декабря, но еще и как бы 29 декабря.
Одновременно.


 
Медвежонок Пятачок ©   (2010-06-10 14:32) [12]

Это 0 часов о минут 30 января 1899 года.

декабря конечно, пардон


 
Anatoly Podgoretsky ©   (2010-06-10 14:40) [13]

> bss  (10.06.2010 13:52:00)  [0]

1.00 нашей эры
0.75 нашей эры
0.50 нашей эры
0.25 нашей эры
0
-0.25 до нашей эры
-0.50 до нашей эры
-0.05 до нашей эры
-1.00 до нашей эры

Так было задумано, но в 1996 году произошел крах


 
bss   (2010-06-10 14:46) [14]


> Trunc(0 - 0.5) = 0


считаю пример некорректным. Ибо Trunc округляет в МЕНЬШУЮ сторону. В случае же отрицательных чисел Trunc округляет в БОЛЬШУЮ сторону. Отсюда и разница поведений. Если бы для положительных чисел Trunc тоже округлял в большую сторону - ты получил бы тот же самый "свой" глюк.

Я бы в своей версии интерпретировал это так то, что Trunc не предназначен для корректного узнавания начала дня по переменной DT: TDateTime. Собственно, для этого и есть функция: StartOfADay

Но я согласен, что, возможно, история вопроса как раз в том, что в свое время сделали именно так, чтобы "низкоуровневый" Trunc работал точно также, как спец. функция StartOfADay. А потом уже поздно было менять.

Но изменять естественную линию времени таким извратом для того, чтобы Trunc корректно давал начала дня... Имхо, перебор.

А может быть еще какие объяснения есть


 
Anatoly Podgoretsky ©   (2010-06-10 14:46) [15]

> Медвежонок Пятачок  (10.06.2010 14:26:09)  [9]

У борланда все документировано -1.25 это 6 1часов минус 1 день и минус 0,25,
а не плюс 0,25


 
Anatoly Podgoretsky ©   (2010-06-10 14:49) [16]

> bss  (10.06.2010 14:46:14)  [14]

Trunc ничего не округляет, а обрезает


 
Медвежонок Пятачок ©   (2010-06-10 14:49) [17]

Ты можешь считать все что угодно.

В том числе что точка ноль на шкале дабл это одновременно начало ДВУХ РАЗНЫХ суток.

Это по твоему 00:00:00 30 декабря, но еще и 00:00:00 29 декабря того же года

в то время как все остальные натуральные точки на шкале - это конец одних суток и начало следующих


 
sniknik ©   (2010-06-10 15:00) [18]

не доверяете борланду?....
смотрим в мелкософте (акцесс)
SELECT CDate(0.5), CDate(-0.5)
получаем
30.12.1899 12:00:00 | 30.12.1899 12:00:00
т.е. то же самое

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


 
bss   (2010-06-10 15:05) [19]


> Trunc ничего не округляет, а обрезает

обрезание - это округление до целого в меньшую сторону. Эквивалентные понятия.


> не доверяете борланду?....
> смотрим в мелкософте (акцесс)

но ПОЧЕМУ именно так сделано?


 
sniknik ©   (2010-06-10 15:07) [20]

> Ты
можешь считать все что угодно.
> ...
может вот так будет понятнее
procedure Form1.Button1Click(Sender: TObject);
var
 orDt, tmDt: TDateTime;
begin
 orDt:= 0;
 tmDt:= -0.5;
 ReplaceTime(orDt, tmDt);
 ShowMessage(FloatToStr(orDt));
end;

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


 
sniknik ©   (2010-06-10 15:12) [21]

> но ПОЧЕМУ именно так сделано?
а КАК по другому? время задается от 0 до 24 часов. -пол дня не бывает. бывает только день (точка отсчета) + какое то время. день в твоем примере не меняется.


 
Медвежонок Пятачок ©   (2010-06-10 15:14) [22]

А может быть еще какие объяснения есть

Объяснение одно. Чисто геометрическое.

на положительной шкале дабл:  начало суток левее конца тех же суток
на отрицательной шкале дабл:  начало суток правее конца тех же суток

защитный диапазон от -1 до нуля существует для того, чтобы одна и та же точка на шкале не была началом двух разный суток. (само по себе это ничего страшного, если не оперировать разностью даблов как разницей в днях)

вот и все.


 
RWolf ©   (2010-06-10 15:23) [23]


> bss   (10.06.10 15:05) [19]
> > Trunc ничего не округляет, а обрезает
> обрезание - это округление
> до целого в меньшую сторону. Эквивалентные понятия.

trunc(1.1) = 1
trunc(-1.1) = -1


 
Anatoly Podgoretsky ©   (2010-06-10 15:29) [24]

> sniknik  (10.06.2010 15:00:18)  [18]

Та это крах 1996 года, но крах произошел в мозах, они свихнулись, то же
самое при смешение 01,01.0001 ни каких вопросов не вызывало.


 
Anatoly Podgoretsky ©   (2010-06-10 15:32) [25]

> bss  (10.06.2010 15:05:19)  [19]

Что как -1.25 это минус (1 день и 6 часов)
TRUNC это не округление до меньшего, этим даже и не пахнет.
Но это из той же оперы, когда мозги кипят


 
Anatoly Podgoretsky ©   (2010-06-10 15:32) [26]

> sniknik  (10.06.2010 15:07:20)  [20]

В IBM так и есть, два нуля


 
Anatoly Podgoretsky ©   (2010-06-10 15:33) [27]

> sniknik  (10.06.2010 15:12:21)  [21]

минус четверть дня -0.25, что равно 6 часам


 
Anatoly Podgoretsky ©   (2010-06-10 15:35) [28]

> Медвежонок Пятачок  (10.06.2010 15:14:22)  [22]

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


 
Anatoly Podgoretsky ©   (2010-06-10 15:36) [29]

> RWolf  (10.06.2010 15:23:23)  [23]

Справка это тоже подтверждает и поведение тоже. Только у некоторых -1 это
почему то в мельшую сторону.

Нет ничего проще времени и сколько людей не могут его понять.


 
Медвежонок Пятачок ©   (2010-06-10 15:36) [30]

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

молниеносный скачек на два шага вперед, потом меееееедленно на один шаг назад.
и так каждый божий день.

:)


 
bss   (2010-06-10 15:56) [31]


> время задается от 0 до 24 часов. -пол дня не бывает. бывает
> только день (точка отсчета) + какое то время. день в твоем
> примере не меняется.

Ну да, я понял... Просто нельзя сделать красиво отрицательное время. Если принять одну интерпретацию - вылезут одни косяки, если принять другую интерпретацию - полезут другие косяки...

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


 
Rouse_ ©   (2010-06-10 15:59) [32]


> bss   (10.06.10 15:05) [19]
> обрезание - это округление до целого в меньшую сторону.

Ты только евреям такое не говори :)


 
sniknik ©   (2010-06-10 16:00) [33]

> молниеносный скачек на два шага вперед, потом меееееедленно на один шаг назад.
> и так каждый божий день.
жизнь контрамота по Стругацким (понедельник начинается в субботу), только у них там скачек на 2 дня назад, а после медленно (нормально) проживает один день вперед. и так далее.


 
Медвежонок Пятачок ©   (2010-06-10 16:02) [34]

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

начало суток 29 дек 1899 года должно быть удалено от начала суток 30 дек 1899 года ровно на единицу. То есть это -1

но до 29 декабря были еще даты и их единственное место - слева по шкале.

это значит, что сутки в отрицательной части бегут влево, а даты по прежнему вправо.

Никаких иных зол и вариантов просто нет.


 
RWolf ©   (2010-06-10 16:16) [35]


> Никаких иных зол и вариантов просто нет.

вполне себе логичный вариант:
29 дек 1899 00:00 = -1
29 дек 1899 06:00 = -0.75
29 дек 1899 18:00 = -0.25
30 дек 1899 00:00 = 0
и никаких скачков.


 
bss   (2010-06-10 16:20) [36]


> Никаких иных зол и вариантов просто нет.

как это нету вариантов. Мой вариант с линейным течением времени.

То есть:

TDateTime(0) = 30.12.1899  00:00:00.00
TDateTime(-0.5) = 29.12.1899  12:00:00.00
TDateTime(-1.25) = 28.12.1899  18:00:00.00

Почему это не вариант? Есть косяки, конечно, как и в текущем варианте. Что из глюков мы уже определили:

- неверно будет работать Trunc(TDateTime) в смысле определения начала дня. Да, но для этого есть функция StartOfTheDay.

Что еще не так будет?

А вот в текущей интерпретации TDateTime да, Trunc отработает верно на любых датах, в том числе отрицательных. Зато возникает провальный диапазон от "0" до "-1", и плюс этот эффект:

>молниеносный скачек на два шага вперед,
>потом меееееедленно на один шаг назад.
>и так каждый божий день.

что сложно для восприятия для неподготовленного. Имхо.


 
bss   (2010-06-10 16:23) [37]

фактически корректность работы Trunc"а мы променяли на то, что время идет нелинейно относительно линии дробных чисел. Что очень жестко путает, гораздо проще осознать, что вместо Trunc надо пользовать StartOfTheDay


 
Медвежонок Пятачок ©   (2010-06-10 16:26) [38]

и никаких скачков.

а ничего, что при этом 18 часов для 29 дек и 30 дек это будут разные величины?

0.75
-0.25


 
Медвежонок Пятачок ©   (2010-06-10 16:30) [39]

как это нету вариантов. Мой вариант с линейным течением времени.

тогда смотри [38]

фактически это означает, что никакой арифметики с TDateTime, построенном на дабле иметь нельзя.

Нужно создавать класс TDateTime и писать в нем методы.

Оно надо?


 
bss   (2010-06-10 16:34) [40]


> а ничего, что при этом 18 часов для 29 дек и 30 дек это
> будут разные величины?

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


> никакой арифметики с TDateTime, построенном на дабле иметь
> нельзя.

какой арифметике? Да, обрезать с помощью Trunc"а нельзя. Но вычитать, складывать даты вполне можно, разве нет?

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



Страницы: 1 2 3 вся ветка

Форум: "Прочее";
Текущий архив: 2010.09.05;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.57 MB
Время: 0.004 c
2-1276157798
novichek
2010-06-10 12:16
2010.09.05
работа с БД


2-1275991560
Cannon
2010-06-08 14:06
2010.09.05
Авторизация


15-1271944492
JohnKorsh
2010-04-22 17:54
2010.09.05
Все ли IP адреса равноправны ?


15-1276195781
AKE
2010-06-10 22:49
2010.09.05
Где можно найти какой-нибудь исходный код


4-1239652712
Unlocker
2009-04-13 23:58
2010.09.05
Запуск под админом





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский