Delphi: как определить и очистить значение TDatetime

Кажется, нет способа присвоить NULL (либо "неприсвоенное значение" TDateTime переменным.

Единственный способ, который я себе представлял, - это использовать что-то вроде этого:

function isNull(aDate : TDateTime) : boolean;
const NullDate = 0.0;
var aNullDate : TDatetime;
    ms : Int64;
begin
  aNullDate := NullDate;
  ms := MilliSecondsBetween(aDate,aNullDate);
  result := (ms = Int64(0));
end;

Есть ли кто-нибудь, кто знает лучшее решение, которое не перекрывает значение даты 0?

Опасны ли отрицательные значения TDateTime? (Как способный ресурс для предыдущей цели)


person xsubira    schedule 20.02.2013    source источник
comment
Если вы собираетесь использовать эту функцию, я думаю, что NullDate должна быть глобальной константой?   -  person Andreas Rejbrand    schedule 20.02.2013
comment
У меня возникли проблемы при сравнении переменной TDateTime с нулевым присвоенным значением и константным значением 0. Простой if, поскольку этот не проверял условие ` var v_datetime: TDatetime ;` ` v_datetime := 0;` ` если (v_datetime = 0), то actionToTake`   -  person xsubira    schedule 20.02.2013
comment
Это из-за пуха с плавающей запятой. Используйте 1_.   -  person Andreas Rejbrand    schedule 20.02.2013
comment
0 — это вполне допустимая дата, и отрицательные даты также прекрасно подходят. 0 — это полночь 30 декабря 1899 года. Отрицательные числа — это даты до нее.   -  person Nick Hodges    schedule 21.02.2013


Ответы (5)


Как уже писал Андреас, тип TDateTime на самом деле double и, следовательно, не " обнуляемый". я использую

const
  c_UnassignedDate = -693594;

для пустого значения даты, поскольку это представляет собой невозможную дату 00/00/0000. Но, например, DevExpress использует

NullDate = -700000;
InvalidDate = NullDate + 1;

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

person ain    schedule 20.02.2013
comment
Нет даты, где день и месяц равны 0 (ноль). В базе данных, если дата не назначена, следует использовать NULL, а не какую-то магическую дату. - person ain; 20.02.2013
comment
Да извини. Возвращаясь назад, я смотрел только на часть года этой даты... Что ж, если значение определенного столбца даты и времени будет NULL, и мне придется хранить это значение строго в поле TDateTime, я бы, вероятно, использовал ваш c_UnassignedDate постоянное значение. [+1] - person TLama; 20.02.2013
comment
Как вы понимаете, что -693594 представляет дату 0/0/0000? - person Rob Kennedy; 20.02.2013
comment
@Rob: Я думаю, потому что -693591 представляет 0000-01-03, -693592 представляет 0000-01-02, а -693593 представляет 0000-01-01, по крайней мере, согласно DateTimeToStr. - person Andreas Rejbrand; 20.02.2013
comment
@RobKennedy просто выполните ShowMessage(FormatDateTime('dd.mm.yyyy',-693594));, и появится dlg с 00.00.0000. - person ain; 20.02.2013
comment
@ain: Как и каждое меньшее значение. Мой анализ показывает, что -693594 является наибольшим отрицательным целым числом с этим свойством. - person Andreas Rejbrand; 20.02.2013

Сначала вам нужно определить, что вы подразумеваете под «пустым значением TDateTime».

Значение TDateTime представляет собой двойное число с датой, закодированной в целой части, и временем, закодированным в дробной части. Итак, самое близкое к «нулевой дате», которое вы можете получить, это, вероятно, 0.

Следовательно, просто проверьте ADate <> 0, чтобы проверить, является ли дата «нулевой».

Но будьте осторожны: если вы объявите локальную переменную TDateTime, то она не обязательно будет =0 до того, как вы присвоите ей значение. Это может быть что угодно. Разумеется, то же самое относится и к переменным типа integer, double, boolean,...

Кроме того, я считаю, что TDateTime со значением 0 кодирует дату 1899-12-30.

Наконец, отрицательные значения TDateTime совершенно нормальны. Например, -5000 соответствует 1886-04-22.

Я не совсем понимаю смысл вашего кода. Если вы хотите использовать 0 в качестве «неназначенного» значения (что плохо, если вас интересуют даты, близкие к 1899-12-30), почему бы просто не сделать

function IsUnassigned(ADate: TDateTime): boolean;
begin
  result := ADate = 0;
end;

или, возможно (но не эквивалентно!),

function IsUnassigned(ADate: TDateTime): boolean;
begin
  result := IsZero(Date);
end;

В своем ответе ain дал несколько более разумных вариантов значения «неназначенная дата».

person Andreas Rejbrand    schedule 20.02.2013
comment
Даты с отрицательным временем становятся бессмысленными в конце концов, когда календарь ломается. - person David Heffernan; 20.02.2013
comment
@ Дэвид: Хороший вопрос. Таким образом, на самом деле есть много правдоподобных вариантов для «неназначенного» значения. - person Andreas Rejbrand; 20.02.2013
comment
Не было бы полезно использовать здесь NaN как явное значение? Затем вы можете использовать IsNaN для проверки условия. - person Brian Frost; 21.02.2013

В модуле Spring.Persistence.Core.Session.pas библиотеки Spring Framework для Delphi (http://www.spring4d.org) в методе TSession.ExecuteScalar<T> в случае NULL для результата использовалось значение Default(T);

Я думаю, ваша функция может выглядеть так

function IsNull(ADate: TDateTime): Boolean;
begin
  Result := ADate = Default(TDateTime);
end;
person Nashev    schedule 23.01.2020

tDateTime не определен для значений от 0 до -1, что означает, что tDateTime, равное -0,5, является неопределенным значением и полезно для нулевой даты в качестве альтернативы NaN. DateTimeToString будет отображать -0,5 так же, как +0,5;

person John Hillier    schedule 03.02.2016

Используйте PDateTime вместо TDateTime и отправьте как нулевое значение. Если нет указателя на значение, результат не имеет значения.

Чтобы проверить значение, используйте Assigned ptr :

MyDatePointer := nil;
if ( Assigned(MyDatePointer)) then ...
person Eugene.LatDev    schedule 24.07.2015