29

私の知る限り、これを行う方法はありませんが、他の誰かがこれを行う方法を知っている場合に備えて質問します. Delphiで日付をconstとして宣言するにはどうすればよいですか?

私が見つけた唯一の解決策は、同等の数値を使用することです。これは、人間が判読できないため、維持するのが面倒です。

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

私ができるようにしたいのは、次のようなものです。

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

また

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

それで、これが機能のリクエストなのか、それとも単にこれを行う方法を忘れたのかを教えてください (ええ、それが欲しいのは奇妙なことのように思えます. . . .)

4

11 に答える 11

22

わかりました、私の反応は少し遅れていますが、これが新しい 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's 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 変数をこれに置き換えたい場合は、おそらく他の演算子 (加算、減算、明示的など) もオーバーロードする必要があります。

于 2009-05-15T17:03:01.630 に答える
12

唯一の?可能な方法ですが、おそらくあなたが探しているものではありません:

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

initialization
  Expire := EncodeDate(2009, 3, 23);
于 2009-03-23T23:26:16.110 に答える
11

関数でconst日付をシミュレートする傾向があります。技術的には、「疑似定数」の割り当て可能な型付きconstよりも少し定数です。

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

EncodeDateではなく を使用することに注意StrToDateしてください。StrToDateつまり、文字列が期待どおりに解釈されるという保証はありません。

たとえば、日付の部分を一貫性のない重要な順序に「シャッフル」することが理にかなっていると考える奇妙なグループがあることをご存知ですか? 彼らは、中間、次に重要でない部分、次に重要な部分を使用します (例: '3/23/2009') <cheeky grin>。論理が通用するのは、あなたが 102 歳になったときだけです。その後、あなたの年齢は 021 歳であると主張できます。

時期尚早のオプティマイザーにとって、関数が頻繁に呼び出されて日付をエンコードするのに必要なナノ秒が問題になる場合、読み取り可能で保守可能なコードの名の下に、この小さな非効率性よりもはるかに大きな問題があります。

于 2012-06-30T12:31:17.767 に答える
8

日付リテラル自体の解釈は決定論的ではないため、これを行う方法はありません。それは、従う慣習/ロケールに依存します。
たとえば、「1/4/2009」はフランス人にとっては 1 月ではなく、コンパイラが 1 月 4 日として翻訳するのはばかげ
たコンパイラになります ;-) コンパイラが何らかの (十分に文書化された) 「魔法の」全単射関数を日付値と表示表現を組み合わせる...とにかく、地球の半分はそれを好まないでしょう.
私が今見ている唯一のあいまいでない方法は、たとえそれが苦痛のように見えても値を提供することです... ...私の$ 0.02

于 2009-03-24T01:30:08.387 に答える
6

いいえ、Delphi はそれをサポートしていません。

最初のアイデアは、通常の浮動小数点リテラルとは異なる日時リテラルを要求することです。デバッガーで値を日付として表示することに関するQC 72000を見つけましTDateTimeたが、特定の要求については何もありません。ただし、これまで誰も言及していなかったわけではありません。これは、ニュースグループの永遠のトピックです。私はそれについてQCで何も見つけることができません。

2 番目のアイデアはStrToDate、コンパイル時に評価可能である必要があります。QC にもそれに関するエントリはありませんが、価値のあることとして、C++ は、必要な品質を備えていることが示されている関数に対してそのような機能を取得しています。StrToDateただし、現在のロケールの日付設定に敏感であるため、これらの要件を満たしていません。

于 2009-03-24T01:10:41.053 に答える
4

1 つの解決策は、年の定数のリストを作成し、別の月のオフセットを作成して、その場で作成することです。結果の各定数に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;

閏年がある場合は、その年の 2 月以降に 1 を追加する必要があります。

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

編集

わかりやすくするためにさらに数年を追加し、Leap_Day 定数を追加しました。

于 2009-03-25T16:49:38.887 に答える
4

ロブ・ケネディの答えは、コードがヨーロッパでコンパイルされた場合にコードが壊れたくないため、StrToDate ソリューションは本質的に問題外であることを示しています!

EncodeDate を実行する方法があるはずですが、そうではありません。

私が懸念している限り、コンパイラは、定数割り当てで見つかったコードをコンパイルして実行し、結果を定数に格納するだけです。コードが環境の影響を受けないようにすることは、プログラマーに任せます。

于 2009-03-24T01:27:15.413 に答える
1

あなたが利用できる最善の解決策は、宣言することだと思います:

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

そしてそれを受け入れるだけです。


私の試み No1

Expire = EncodeDate(2009, 3, 23);

[エラー] 定数式が必要です

私の試み Nº2

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

[エラー] 定数式が必要です

そのため、それらが一定で決定論的 (つまり、ロケール情報に依存しない) であっても、それでも機能しません。

于 2009-05-14T17:09:30.890 に答える