在delphi中某一年的同一周



我将Delphi 11与新的DateUtils库一起使用,但在给定的年份内,我无法获得过去同一天的日期。对于n年前的某个特定日期,我必须在同一周的同一天重新命名。所以如果今天是星期天,我必须回到n年前的那个星期天。我添加了一个用delphi编写的真实测试应用程序的完整源代码,并修复了错误

unit Unit1;
interface
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, Vcl.ComCtrls, system.DateUtils, system.Types;
type
TForm1 = class(TForm)
dtDataOggi: TDateTimePicker;
Label1: TLabel;
edYears: TEdit;
bnCalcola: TButton;
procedure bnCalcolaClick(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
function annobisestile(value : tDate) : integer;
end;

var
Form1: TForm1;
implementation
{$R *.dfm}

procedure TForm1.bnCalcolaClick(Sender: TObject);
var
DataAppoggio : tDate;
NumberOfYearToSubtract : integer;
annobis : integer; // is leap year?
annoappoggio : integer;
giorno : boolean;
febb28 :tDate;
i : integer;
begin
DataAppoggio := dtDataOggi.date;
NumberOfYearToSubtract := strToInt(edYears.Text);
annobis := 0;
annoappoggio := yearOf(DataAppoggio);
febb28 := encodedate(annoappoggio ,2,28);
if CompareDate(febb28,DataAppoggio) = GreaterThanValue then
Giorno := true
else
Giorno := false;
DataAppoggio := IncYear(DataAppoggio, -NumberOfYearToSubtract);
// check if adataappoggio is before feb 28  so i must add a day
if giorno then  begin
for I := 0 to NumberOfYearToSubtract  do begin
//annobiststile is a custom functions that returns 1 if the given year is a leap year
annobis := annobis + annobisestile(encodeDate(annoappoggio,01,01));
annoappoggio := annoappoggio -1;
end;
end
else begin
for I := 0 to NumberOfYearToSubtract -1  do begin
annobis := annobis + annobisestile(encodeDate(annoappoggio,01,01));
annoappoggio := annoappoggio -1;
end;
end;
label1.Caption  :=  incDay(DataAppoggio, NumberOfYearToSubtract+annobis).ToString;
end;
function TForm1.annobisestile(value: tDate): integer;
begin
if IsInLeapYear(value) then
result := 1
else
result := 0;
end;

此函数返回给定年份的确切日期,但如果该年份为3或更多,则不会包含同一周。知道吗?非常感谢。

如果您需要n年前(或更晚(同一周号一周中的同一天的日期,则解决方案是直接的。System.DateUtils单元具有所有必要的功能。

首先使用函数YearOf()WeekOf()DayOfTheWeek()InputDate得到InputYearInputWeekInputDOW(星期几(。

然后使用EncodeDateWeek()函数将InputYear+YearsToAddInputWeekInputDOW转换为TDateTime

完整的示例代码如下:

procedure TForm2.Button3Click(Sender: TObject);
var
InputDate: TDate;
InputYear: word;
InputWeek: word;
InputDOW:  word;
YearsToAdd: integer;
NewDate: TDate;
begin
InputDate := dtDataOggi.date;
InputYear := YearOf(InputDate);
InputWeek := WeekOf(InputDate);
InputDOW  := DayOfTheWeek(InputDate); // ISO 8601 Monday is first dow,
// use DayOfWeek() for Sunday as first dow
YearsToAdd := strToInt(edYears.Text); // use '-' in input for subtraction
NewDate := EncodeDateWeek(InputYear + YearsToAdd, InputWeek, InputDOW);
Memo1.Lines.Add(DateToStr(InputDate));
Memo1.Lines.Add(DateToStr(NewDate));
end;

编辑:

您可以通过删除中间变量InputYearInputWeekInputDOW来缩短代码,并将对YearOf(InputDate)WeekOf(InputDate)DayOfTheWeek(InputDate)的调用作为对EncodeDateWeek()的参数。

procedure TForm2.Button3Click(Sender: TObject);
var
InputDate: TDate;
YearsToAdd: integer;
NewDate: TDate;
begin
InputDate := dtDataOggi.date;
YearsToAdd := strToInt(edYears.Text); // use '-' in input for subtraction
NewDate := EncodeDateWeek(
YearOf(InputDate) + YearsToAdd, 
WeekOf(InputDate), 
DayOfTheWeek(InputDate));           // ISO 8601, monday is first dow
// use DayOfWeek() for sunday as first dow
Label1.Caption := DateToStr(NewDate);
end;

你把事情搞得太复杂了。您不需要function annobisestile,可以使用以下方法替换TForm1.bnCalcolaClick。简而言之,这会减去指定的年数,然后根据一周中原始日期的天数来调整日期。

(这是用10.4完成的,它没有新的TDateTime助手,所以我用了DateToStr()而不是.toString。(

procedure TForm1.bnCalcolaClick(Sender: TObject);
var
DataAppoggio : tDate;
NumberOfYearToSubtract : integer;
DOW : Integer;
begin
DataAppoggio := dtDataOggi.date;
NumberOfYearToSubtract := strToInt(edYears.Text);
DOW := DayOfWeek(DataAppoggio);
DataAppoggio := IncYear(DataAppoggio,-NumberOfYearToSubtract);
DataAppoggio := IncDay(DataAppoggio,DOW-DayOfWeek(DataAppoggio));
label1.Caption  :=  DateToStr(DataAppoggio);
end;

最新更新