在 Delphi 中将 TDateTime 声明为 Const

发布于 2024-07-15 02:32:54 字数 485 浏览 8 评论 0原文

据我所知,没有办法做到这一点,但我会问以防万一其他人知道如何做到这一点。 在 Delphi 中如何将日期声明为常量?

我找到的唯一解决方案是使用数字等价物,维护起来有点痛苦,因为它不是人类可读的。

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

我希望能够做的是这样的事情:

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

或者

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

所以让我知道这是否是一个功能请求或者我是否只是错过了如何做到这一点(是的,我知道这似乎是一件奇怪的事情...... .)

As far as I know there is no way to do this, but I am going to ask just in case someone else knows how to do this. How can I declare a date as a const in Delphi?

The only solution I have found is to use the numeric equivalent, which is kind of a pain to maintain because it is not human readable.

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

What I would like to be able to do is something like this:

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

or

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

So let me know if this is a feature request or if I just missed how to do this (yeah, I know it seems like an odd thing to want . . . .)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(11

素染倾城色 2024-07-22 02:32:54

好吧,我的反应有点晚了,但这里有一个针对较新的德尔福的解决方案。

它使用隐式类重载器,以便可以像使用 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 变量,你可能还需要重载一些其他运算符(加、减、显式、 ...)。

Ok, my reaction is a bit late, but here's a solution for the newer Delphi's.

It uses implicit class overloaders so that records of this type can be used as if they are TDateTime variables.

  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;

Implementation:

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;

Now you can declare your dates like this:

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);

To see if it works, execute the following:

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

If you really want to replace all your TdateTime variables with this, you probably need to overload some other operators too (Add, subtract, explicit, ...).

唯一的? 可能的方式,但可能不是您正在寻找的:

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

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

The only? possible way, but probably not what you are looking for:

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

initialization
  Expire := EncodeDate(2009, 3, 23);
青朷 2024-07-22 02:32:54

我倾向于用函数模拟 const 日期。 从技术上讲,它们比“伪常量”可分配类型const常量

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

注意使用EncodeDate而不是StrToDateStrToDate 受区域设置的影响,这意味着不能保证字符串会按预期进行解释。

例如,您是否知道有一群奇怪的人认为将日期部分“洗牌”成不一致的重要性顺序是有意义的? 他们使用中间部分,然后是最不重要的部分,然后是最重要的部分(例如“3/23/2009”)<厚脸皮的笑容>。 逻辑唯一有意义的时候是当你年满 102 岁时 - 那么你就可以声称你的年龄是 021 岁。

对于那些不成熟的优化者来说,如果该函数被如此频繁地调用,以至于编码日期所需的纳秒成为一个问题 - 那么你就会遇到一个更大的问题这比可读、可维护代码的效率低下更重要。

I tend to simulate const dates with a function. Technically they're a little more constant than the "pseudo-constant" assignable typed const's.

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

NOTE the use of EncodeDate rather than StrToDate. StrToDate is affected by regional settings meaning there's no guarantee a string will be interpreted as would be expected.

For example, did you know that there's a strange a group of people who think it makes sense to "shuffle" date parts into an inconsistent order of significance? They use middle, then least, then most significant part (e.g. '3/23/2009') <cheeky grin>. The only time that logic makes sense is when you turn 102 years old - then you can claim your age is 021.

For the premature optimisers out there, if the function is called so frequently that the nano seconds required to encode a date becomes an issue - you have a far bigger problem than this minor inefficiency in the name of readable, maintainable code.

2024-07-22 02:32:54

没有办法做到这一点,因为解释日期文字本身并不是确定性的,它取决于您遵循的约定/区域设置。
例如,对于任何法国人来说,“1/4/2009”都不是一月份,并且将编译器翻译为 1 月 4 日将使其成为傻瓜编译器;-)
除非编译器实现一些(有据可查的)“神奇”双射函数来配对日期值和显示表示......无论如何,地球的一半人不会喜欢它。
我现在看到的唯一明确的方式是提供价值,即使它看起来很痛苦......
...我的 0.02 美元

There is no way to do this because interpreting a date litteral in itself is not deterministic, it depends on the convention/locale you follow.
'1/4/2009' is not in January for any French person for instance, and having the compiler translating as January 4th would make it a fool's compiler ;-)
Unless the compiler implements some (well documented) "magic" bijective function for pairing a date value and a display representation... And anyway, half of the planet would not like it.
The only non ambiguous way I see now is to provide the value even if it looks like a pain...
... my $0.02

鼻尖触碰 2024-07-22 02:32:54

不,Delphi 不支持这一点。

您的第一个想法是请求与普通浮点文字不同的日期时间文字。 我找到了 QC 72000,它是关于显示TDateTime< /code> 值作为调试器中的日期,但与您的特定请求无关。 不过,以前也没有人提过这个问题。 这是新闻组中常年出现的话题。 我只是在 QC 中找不到任何相关内容。

您的第二个想法需要 StrToDate 在编译时可评估。 我在 QC 中也没有看到任何有关它的条目,但就其价值而言,C++ 正在为具有必要品质的函数提供这样的功能。 但是,StrToDate 无法满足这些要求,因为它对当前区域设置的日期设置很敏感。

No, Delphi doesn't support that.

Your first idea would be a request for date-time literals distinct from ordinary floating-point literals. I found QC 72000, which is about displayingTDateTime values as dates in the debugger, but nothing about your particular request. It's not like nobody's ever mentioned it before, though. It's a perennial topic on the newsgroups; I just can't find anything in QC about it.

Your second idea would require StrToDate to be evaluable at compile time. I don't see any entries in QC about it either, but for what it's worth, C++ is getting such a feature for functions that are shown to have the necessary qualities. StrToDate wouldn't meet those requirements, though, because it's sensitive to the current locale's date settings.

东京女 2024-07-22 02:32:54

Rob Kennedy 的回答表明,StrToDate 解决方案本质上是不可能的,因为如果代码是在欧洲编译的,您不希望代码被破坏!

我确实同意应该有某种方法来执行 EncodeDate 但没有。

就我而言,编译器应该简单地编译并运行它在常量赋值中找到的任何代码,并将结果存储到常量中。 我将其留给程序员来确保代码对其环境不敏感。

Rob Kennedy's answer shows that the StrToDate solution is inherently out of the question as you don't want your code to break if it's compiled in Europe!

I do agree there should be some way to do EncodeDate but there isn't.

As far as I'm concerned the compiler should simply compile and run any code it finds in a constant assignment and store the result into the constant. I'd leave it up to the programmer to ensure the code isn't sensitive to it's environment.

静赏你的温柔 2024-07-22 02:32:54

一种解决方案是创建一个多年来的常量列表,另一个用于月份偏移量的列表,然后动态构建它。 您必须自己处理闰年,将每个结果常量加 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 常量。

One solution would be to create a list of constants for years, another for month offsets and then build it on the fly. You would have to take care of leap years yourself by adding 1 to each resulting constant. Just a few below to get you started... :)

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;

If you have a leap year then you have to add 1 to anything beyond february of that year.

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

EDIT

Added a few more years for clarity, and added a Leap_Day constant.

屋檐 2024-07-22 02:32:54

Delphi 日期是自 1899 年 12 月 30 日以来的天数。 因此,您可能会想出一个复杂的数学公式来将日期表示为常量。 然后你可以非常奇怪地格式化它,以强调人类可读的部分。 我最好的尝试如下,但它非常不完整; 一方面,它假设所有月份都有 30 天。

不过,我的例子主要是为了好玩。 实际上,这是相当荒谬的。

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

A Delphi date is the # of days since Dec 30, 1899. So you could probably come up with an elaborate mathematical formula to express a date as a const. Then you could format it very oddly, to emphasize the human-readable parts. My best attempt is below, but it is very much incomplete; for one thing, it assumes that all months have 30 days.

My example is mostly for fun though. In practice, this is pretty ridiculous.

const
  MyDate = ((
           2009  //YEAR
                                          - 1900) * 365.25) + ((
           3     //MONTH
                                          - 1) * 30) +
           24    //DAY
           ;
相思碎 2024-07-22 02:32:54

我认为您可用的最佳解决方案是声明:

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

并接受它。


我的尝试No.1

Expire = EncodeDate(2009, 3, 23);

[错误]需要常量表达式

我的尝试 N°2

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

[错误]需要常量表达式

因此,即使它们是常量且确定的(即不依赖于任何区域设置信息),它仍然不起作用。

i think the best solution available to you is to declare:

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

and just accept it.


My attempt Nº1

Expire = EncodeDate(2009, 3, 23);

[Error] Constant expression expected

My attempt Nº2

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

[Error] Constant expression expected

So even though they're constant, and deterministic (i.e. do not depend on any locale information), it still doesn't work.

倒数 2024-07-22 02:32:54

类型“TDateTime”=类型“Double”。

算法:

  1. 使用StrToDateTime('01.01.1900 01:01:01')(或其他方式)计算需要的double_value。 ('01.01.1900 01:01:01' => 2.04237268518519)

2.const
DTZiro: TDateTime = 2.04237268518519;

The type "TDateTime" = type "Double".

Algorithm:

  1. Use StrToDateTime('01.01.1900 01:01:01') (or other way) to calculate need double_value. ('01.01.1900 01:01:01' => 2.04237268518519)

2.const
DTZiro: TDateTime = 2.04237268518519;

囍孤女 2024-07-22 02:32:54

System.DateUtils 对于每个时间部分都有常量。

const cDT : TDateTime = (12 * OneHour)   + ( 15 * OneMinute) 
                      + (33 * OneSecond) + (123 * OneMillisecond);

System.DateUtils has constants for each part of time.

const cDT : TDateTime = (12 * OneHour)   + ( 15 * OneMinute) 
                      + (33 * OneSecond) + (123 * OneMillisecond);
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文