Подтвердить что ты не робот

Объявить TDateTime как Const в Delphi

Насколько я знаю, нет никакого способа сделать это, но я собираюсь спросить на всякий случай, если кто-то знает, как это сделать. Как объявить дату как константу в Delphi?

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

const
  Expire : TDateTime = 39895; // Is actually 3/23/2009

То, что я хотел бы сделать, это что-то вроде этого:

const
  Expire : TDateTime = TDateTime ('3/23/2009');

или

const
  Expire : TDateTime = StrToDate('3/23/2009');

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

4b9b3361

Ответ 1

Единственное? возможно, но, вероятно, не то, что вы ищете:

const
{$J+}
  Expire: TDateTime = 0;
{$J-}

initialization
  Expire := EncodeDate(2009, 3, 23);

Ответ 2

Хорошо, моя реакция немного запоздала, но вот решение для новых Delphi.

В нем используются неявные перегружатели классов, поэтому записи этого типа могут использоваться так, как если бы они были переменными TDateTime.

  TDateRec = record
    year,month,day,hour,minute,second,millisecond:word;
    class operator implicit(aDateRec:TDateRec):TDateTime;
    class operator implicit(aDateTime:TDateTime):TDateRec; // not needed
    class operator implicit(aDateRec:TDateRec):String; // not needed
    class operator implicit(aDateRec:String):TDateRec; // not needed
  end;

Реализация:

uses DateUtils;

class operator TDateRec.Implicit(aDateRec:TDateRec):TDateTime;
begin
  with aDateRec do // Yeah that right you wankers. I like "with" :)
    Result := encodeDateTime(Year,Month,Day,Hour,Minute,Second,Millisecond);
end;

class operator TDateRec.Implicit(aDateTime:TDateTime):TDateRec;
begin
  with Result do
    DecodeDateTime(aDateTime,Year,Month,Day,Hour,Minute,Second,Millisecond);
end;

class operator TDateRec.Implicit(aDateRec:TDateRec):String;
begin
  Result := DateTimeToStr(aDateRec)
end;

class operator TDateRec.Implicit(aDateRec:String):TDateRec;
begin
  Result := StrToDateTime(aDateRec)
end;

Теперь вы можете объявить свои даты следующим образом:

const
  Date1:TDateRec=(Year:2009;month:05;day:11);
  Date2:TDateRec=(Year:2009;month:05;day:11;hour:05);
  Date3:TDateRec=(Year:2009;month:05;day:11;hour:05;minute:00);

Чтобы узнать, работает ли это, выполните следующие действия:

ShowMessage(Date1); // it can act like a string
ShowMessage(DateToStr(Date1)); // it can act like a date

Если вы действительно хотите заменить все свои переменные TdateTime на это, вам, вероятно, также придется перегрузить некоторые другие операторы (добавление, вычитание, явное,...).

Ответ 3

Нет никакого способа сделать это, потому что интерпретация даты литтера сама по себе не является детерминированной, это зависит от соглашения/локали, которые вы следуете. '1/4/2009' не в январе для какого-либо французского человека, например, и с компилятором, переводящимся как 4 января, сделает его компилятором-дураком;-)
Если компилятор не реализует некоторую (хорошо документированную) "магическую" биективную функцию для сопоставления значения даты и представления отображения... И вообще, половине планеты это не понравится.
Единственный неопределенный способ, который я вижу сейчас, - это обеспечить ценность, даже если она похожа на боль... ... мой $0.02

Ответ 4

Я имею тенденцию симулировать даты const с помощью функции. Технически они немного более постоянны, чем "псевдопостоянный" присваиваемый тип const.

function Expire: TDateTime;
begin
  Result := EncodeDate(2009, 3, 23);
end;

ПРИМЕЧАНИЕ использование EncodeDate, а не StrToDate. StrToDate зависит от региональных настроек, поэтому нет гарантии, что строка будет интерпретироваться так, как ожидалось.

Например, знаете ли вы, что есть странная группа людей, которые думают, что имеет смысл "перетасовывать" детали даты в непоследовательный порядок значимости? Они используют среднюю, затем наименее значимую часть (например, "3/23/2009" ) < cheeky grin > . Единственный раз, когда логика имеет смысл, когда вам исполнилось 102 года - тогда вы можете утверждать, что ваш возраст равен 021.

Для преждевременных оптимизаторов там, если функция вызывается так часто, что nano секунды, необходимые для кодирования даты, становятся проблемой - у вас проблема с гораздо большей больше, чем эта незначительная неэффективность имени доступного для чтения кода.

Ответ 5

Нет, Delphi не поддерживает это.

Ваша первая идея была бы запросом для литературных дат, отличных от обычных литералов с плавающей запятой. Я нашел QC 72000, в котором отображаются значения TDateTime в качестве дат в отладчике, но ничего о вашем конкретном запросе. Однако это не так, как никто никогда не упоминал об этом раньше. Это постоянная тема в новостных группах; Я просто ничего не могу найти в КК.

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

Ответ 6

Ответ Роба Кеннеди показывает, что решение StrToDate по своей сути не может быть и речи, поскольку вы не хотите, чтобы ваш код сломался, если он скомпилирован в Европе!

Я согласен, что должен быть некоторый способ сделать EncodeDate, но нет.

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

Ответ 7

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

Const
  Leap_Day = 1;  // use for clarity for leap year dates beyond feb 29.
  Year_2009 = 39812;  // January 1, 2009
  Year_2010 = Year_2009 + 365; // January 1, 2010
  Year_2011 = Year_2010 + 365; // January 1, 2011
  Year_2012 = Year_2011 + 365; // January 1, 2012 (is leap year)
  Year_2013 = Year_2012 + Leap_Day + 365;  // January 1, 2013

Const
  Month_Jan = -1; // because adding the day will make the offset 0. 
  Month_Feb = Month_Jan + 31; // 31 days more for the first day of Feb.
  Month_Mar = Month_Feb + 28; // 28 days more for the first day of Mar.  
  Month_Apr = Month_Mar + 30; // 30 days more for the first day of Apr.

Const
  Expire_Jan1 : tDateTime = Year_2009 + Month_Jan + 1;
  Expire : tDateTime = Year_2009 + Month_Mar + 23;

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

Const
  Expire : tDateTime = Year_2008 + Month_Mar + 23 + Leap_Day;

ИЗМЕНИТЬ

Добавлено несколько лет для ясности и добавлена ​​константа Leap_Day.

Ответ 8

Датой Delphi является # of дней с 30 декабря 1899 года. Таким образом, вы могли бы придумать сложную математическую формулу, чтобы выразить дату как const. Тогда вы можете отформатировать его очень странно, чтобы подчеркнуть удобочитаемые части. Моя лучшая попытка ниже, но она очень неполна; во-первых, он предполагает, что у всех месяцев есть 30 дней.

Мой пример в основном для удовольствия. На практике это довольно смешно.

const
  MyDate = ((
           2009  //YEAR
                                          - 1900) * 365.25) + ((
           3     //MONTH
                                          - 1) * 30) +
           24    //DAY
           ;

Ответ 9

Я думаю, что лучшим решением для вас является объявление:

ArmisticeDay: TDateTime = 6888.0 + (11.0/24.0); //Nov 11, 1918 11 AM

и просто примите его.


Моя попытка Nº1

Expire = EncodeDate(2009, 3, 23);

[Ошибка] Ожидается постоянное выражение

Моя попытка Nº2

Expire: TDateTime = EncodeDate(2009, 3, 23);

[Ошибка] Ожидается постоянное выражение

Таким образом, хотя они являются постоянными и детерминированными (т.е. не зависят от какой-либо информации о локали), он все равно не работает.