【问题标题】:Change today's date, advancing one month and setting the systemtime更改今天的日期,提前一个月并设置系统时间
【发布时间】:2008-10-07 19:38:45
【问题描述】:

我想要一个函数的代码示例,该函数将 tDateTime 和一个整数作为输入,并在将该 tDateTime 提前 (int) 个月后使用 setlocaltime 设置系统时间。时间应该保持不变。

伪代码示例

SetNewTime(NOW,2);

我遇到的问题相当令人沮丧。我不能使用 incmonth 或类似的 tDateTime,只能使用 tDate 等。

【问题讨论】:

    标签: delphi datetime


    【解决方案1】:

    下面是一个适合我的完整命令行程序。在 Delphi 5 和 2007 中测试。为什么说 IncMonth 不适用于 TDateTime?

    program OneMonth;
    
    {$APPTYPE CONSOLE}
    
    uses
      SysUtils,
      Windows,
      Messages;
    
    procedure SetLocalSystemTime(settotime: TDateTime);
    var
      SystemTime : TSystemTime;
    begin
      DateTimeToSystemTime(settotime,SystemTime);
      SetLocalTime(SystemTime);
      //tell windows that the time changed
      PostMessage(HWND_BROADCAST,WM_TIMECHANGE,0,0);
    end;
    
    begin
      try
        SetLocalSystemTime(IncMonth(Now,1));
      except on E:Exception do
        Writeln(E.Classname, ': ', E.Message);
      end;
    end.
    

    【讨论】:

    • Bruce,您的代码非常干净,但 Kogus 的代码正确地保持了时间。谢谢你们!
    • 这很公平。我遗漏了一些重要的东西。
    【解决方案2】:

    IncMonth 应该使用 TDateTime:

    function IncMonth ( const StartDate  : TDateTime {; NumberOfMonths  : Integer = 1} ) : TDateTime;
    

    请记住,TDate 实际上只是一个 TDateTime,按照惯例您会忽略分数。

    【讨论】:

      【解决方案3】:

      根据您的伪代码:

      procedure SetNewTime(aDateTime: TDateTime; aMonths: Integer);
      var
        lSystemTime: TSystemTime;
      begin
        DateTimeToSystemTime(aDateTime, lSystemTime);
        Inc(lSystemTime.wMonth, aMonths);
        setSystemTime(lSystemTime);
      end;
      

      【讨论】:

      • 布鲁斯,我真的很喜欢这里的简单,但我没有时间。天数按预期增加和减少,但是当我这样做时,一天中的时间会变得混乱......想法?
      【解决方案4】:

      setSystemTime 使用 UTC 时间,因此您必须根据您的时区进行调整。偏差是您的机器时区与 UTC 不同的分钟数。这会在我的系统上正确调整日期:

      procedure SetNewTime(aDateTime: TDateTime; aMonths: Integer);
      var
        lSystemTime: TSystemTime;
        lTimeZone: TTimeZoneInformation;
       begin
        GetTimeZoneInformation(lTimeZone);
        aDateTime := aDateTime + (lTimeZone.Bias / 1440);
        DateTimeToSystemTime(aDateTime, lSystemTime);
        Inc(lSystemTime.wMonth, aMonths);
        setSystemTime(lSystemTime);
      end;
      

      【讨论】:

        【解决方案5】:

        没有足够的信息来为您的问题提供明确的答案。

        考虑一下,如果当前月份的某天在未来的月份中不存在,您希望发生什么。比如说,1 月 31 日 + 1 个月。 (一年中的 7 个月有 31 天,其余的则更少。)如果您增加年份并且开始日期是闰年的 2 月 29 日,您会遇到同样的问题。所以不可能有一个通用的 IncMonth 或 IncYear 函数在所有日期都一致地工作。

        对于任何感兴趣的人,我衷心推荐 Julian Bucknall's article 了解此类计算所固有的复杂性 关于如何计算两个日期之间的月数和天数。

        以下是唯一可能不会将异常引入通用日期数学的通用日期增量函数。但它只能通过将责任转回给可能具有他/她正在编程的特定应用程序的确切要求的程序员来实现这一点。

        IncDay - 加或减天数。
        IncWeek - 加或减周数。

        但是,如果您必须使用内置函数,那么至少要确保它们执行您希望它们执行的操作。查看 DateUtils 和 SysUtils 单位。拥有这些函数的源代码是 Delphi 最酷的方面之一。话虽如此,以下是内置函数的完整列表:

        IncDay - 加或减天数。
        IncWeek - 加或减周数。
        IncMonth - 加或减月数。
        IncYear - 加或减年数。

        至于您问题的第二部分,如何使用 TDatetime 设置系统日期和时间,一旦您拥有具有您想要的值的 TDatetime,以下从另一个帖子中无耻窃取的代码将完成这项工作:

        procedure SetSystemDateTime(aDateTime: TDateTime);
        var
          lSystemTime: TSystemTime;
          lTimeZone: TTimeZoneInformation;
         begin
          GetTimeZoneInformation(lTimeZone);
          aDateTime := aDateTime + (lTimeZone.Bias / 1440);
          DateTimeToSystemTime(aDateTime, lSystemTime);
          setSystemTime(lSystemTime);
        end;
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2023-04-08
          • 1970-01-01
          • 2016-02-28
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多