周数计算

问题描述 投票:2回答:1

我有代码的问题其用于计算从最新的周数。该应用程序是报表生成器。语言是:报告应用程序编程(RAP)的RAP语言是相同的Object Pascal中。

我写的代码工作的年2017年至2018年,但它不`吨工作,为2019年和2020年。

是否有人有一个想法是什么I'm做错了什么?

if (AVX['P_DELDATE'] >= 42737) and (AVX['P_DELDATE'] <= 43100) {= Jahr        2017} then begin
Value:= (AVX['P_DELDATE'] - 1 - (42737-1) + 7-((AVX['P_DELDATE'] -1 - (42737-1) ) mod 7))/7;
end else begin

if (AVX['P_DELDATE'] >= 43101) and (AVX['P_DELDATE'] <= 43465) {= Jahr 2018} then begin
Value:= (AVX['P_DELDATE'] - 1 - (43101-1) + 7-((AVX['P_DELDATE'] -1 -  (43101-1) ) mod 7))/7;
end;
end else begin

if (AVX['P_DELDATE'] >= 43466) and (AVX['P_DELDATE'] <= 43830) {= Jahr  2019} then begin
Value:= (AVX['P_DELDATE'] - 1 - (43466-1) + 7-((AVX['P_DELDATE'] -1 - (43466-1) ) mod 7))/7;
end;
end else begin

if (AVX['P_DELDATE'] >= 43831) and (AVX['P_DELDATE'] <= 44196) {= Jahr 2020} then begin
Value:= (AVX['P_DELDATE'] - 1 - (43831-1) + 7-((AVX['P_DELDATE'] -1 - (43831-1) ) mod 7))/7;
end;
end;
end;
pascal week-number
1个回答
1
投票

你不说你为什么问在RAP代码做周数计算。除了事实,我找不到任何的RAP文档中AVX函数的定义,试图计算RAP使用AVX周数显然是容易出错,而不是自我记录,并且是所有,但undebuggable办法做到这一点。

显然,你的函数(?或者也许是一个报表字段)AVX返回一个数字值,其整数部分对应于TDateTime类型值的整数部分。在下面的例子项目 - 我已经包括显示处理问题的更容易且不易出错的方式,我包括这(我希望)相匹配的RAP功能的功能,如下所示:

 function WeekNumber(Day : Integer) : Double;
begin
  if (Day >= 42737) and (Day <= 43100) {= Jahr        2017} then begin
      result:= (Day - 1 - (42737-1) + 7-((Day -1 - (42737-1) ) mod 7))/7;
  end
  else begin
    if (Day >= 43101) and (Day <= 43465) {= Jahr 2018} then begin
      result:= (Day - 1 - (43101-1) + 7-((Day -1 -  (43101-1) ) mod 7))/7;
    end
    else begin
      if (Day >= 43466) and (Day <= 43830) {= Jahr  2019} then begin
        result:= (Day - 1 - (43466-1) + 7-((Day -1 - (43466-1) ) mod 7))/7;
      end
      else begin
        if (Day >= 43831) and (Day <= 44196) {= Jahr 2020} then begin
          result:= (Day - 1 - (43831-1) + 7-((Day -1 - (43831-1) ) mod 7))/7;
        end;
      end;
    end;
  end;
end;

(顺便说一句,在做这个转换,我不得不修复了一些在你的RAP代码语法错误的哪个,如果你自己尝试转换你很快就会发现。)

然后,我添加了一个程序来测试这个功能:

procedure TForm1.TestWeekNumber;
var
  Date : TDateTime;
  i : integer;

  procedure TestInner(Date : TDateTime);
  var
    WN1,
    WN2 : Double;
    S,
    SError : String;
  begin
    WN1 := WeekOf(Date);
    WN2 := WeekNumber(Trunc(Date));
    if WN1 = WN2 then
      SError := ''
    else
      SError := '***';
    S := Format('Date: %s WeekOf: %g WeekNumber: %g %s',[ DateTimeToStr(Date), WN1, WN2, SError]);
    if SError <> '' then
      Memo1.Lines.Add(S);
  end;
begin
  Date := StrToDateTime('01/01/2017');
  Memo1.Lines.BeginUpdate;
  try
    for i := 0 to 1999 do
      TestInner(Date + i);
   finally
     Memo1.Lines.EndUpdate;
   end;
end;

这是你WeekNumber与DateUtils.Pas标准WeekOf函数,该函数将返回周数由ISO 8601标准定义的,TDateTime类型的输入值,并且当它们产生不同的结果的值写入到一个TMemo进行比较。以下是从输出的提取物:

Date: 01/01/2017 WeekOf: 52 WeekNumber: 1.13989900694441E-307 ***
Date: 31/12/2018 WeekOf: 1 WeekNumber: 53 ***
Date: 07/01/2019 WeekOf: 2 WeekNumber: 1 ***
Date: 14/01/2019 WeekOf: 3 WeekNumber: 2 ***
Date: 21/01/2019 WeekOf: 4 WeekNumber: 3 ***
Date: 28/01/2019 WeekOf: 5 WeekNumber: 4 ***
Date: 04/02/2019 WeekOf: 6 WeekNumber: 5 ***
Date: 11/02/2019 WeekOf: 7 WeekNumber: 6 ***
[...]
Date: 06/01/2020 WeekOf: 2 WeekNumber: 1 ***
Date: 07/01/2020 WeekOf: 2 WeekNumber: 1 ***
Date: 13/01/2020 WeekOf: 3 WeekNumber: 2 ***
Date: 14/01/2020 WeekOf: 3 WeekNumber: 2 ***
Date: 20/01/2020 WeekOf: 4 WeekNumber: 3 ***
Date: 21/01/2020 WeekOf: 4 WeekNumber: 3 ***
Date: 27/01/2020 WeekOf: 5 WeekNumber: 4 ***
Date: 28/01/2020 WeekOf: 5 WeekNumber: 4 ***
Date: 03/02/2020 WeekOf: 6 WeekNumber: 5 ***
Date: 04/02/2020 WeekOf: 6 WeekNumber: 5 ***
Date: 10/02/2020 WeekOf: 7 WeekNumber: 6 ***

正如你所看到的,事情开始于2018年底脚麻,在此之后,错误的价值观似乎“由一休”之类的错误的建议的。我离开你自己调查并解决这个问题。

我之所以还没有研究它的任何进一步的我是在我看来,你正在做的方式是凌乱的,本可避免复杂。这几乎是微不足道的通过添加计算字段与weeknumber值作供给报告中的数据集,以周数支持添加到您的RBuilder报告。代码做如下所示。

另外,您也可以使用报表制作的工厂到WeekNumber功能添加到可以采取任何时间值(例如,从任何数据集的日期时间字段值)的RAP运行时的语言。例如见Extending RAP - RAP Pass-Through Functions在现有的报表制作工具开发人员指南这里的P213:Report Builder Developer's Guide。什么是描述有可能是堆焊在一份报告中一个Delphi函数的最灵活的方法,虽然ISTR还有其他的。

代码(为简单起见不包括RBuilder部件)

  type
    TForm1 = class(TForm)
      CDS1: TClientDataSet;
      DataSource1: TDataSource;
      DBGrid1: TDBGrid;
      DBNavigator1: TDBNavigator;
      procedure FormCreate(Sender: TObject);
      procedure CDS1CalcFields(DataSet: TDataSet);
    private
      procedure CreateDataSetFields;
    protected
    public
    end;
  [...]
  implementation
  uses
    DateUtils;

  procedure TForm1.FormCreate(Sender: TObject);
  var
    i : Integer;
  begin
    CreateDataSetFields;  // see below
    CDS1.CreateDataSet;

    //  Insert one row per day for current year
    for i := 1 to 365 do begin
      CDS1.InsertRecord([i, i + Now - DayOfTheYear(Now)]);
    end;
    CDS1.First;
  end;

  procedure TForm1.CDS1CalcFields(DataSet: TDataSet);
  begin
    //  This sets the WeekNo calculated field to the value returned by the DateUtils.WeekOf function
    DataSet.FieldByName('WeekNo').AsInteger := WeekOf(DataSet.FieldByName('Date').AsDateTime);
  end;

  procedure TForm1.CreateDataSetFields;
  var
    Field : TField;
  begin
    Field := TIntegerField.Create(Self);
    Field.FieldKind := fkData;
    Field.FieldName := 'ID';
    Field.Name := 'ID';
    Field.DataSet := CDS1;

    Field := TDateTimeField.Create(Self);
    Field.FieldKind := fkData;
    Field.FieldName := 'Date';
    Field.Name := 'Date';
    Field.DataSet := CDS1;

    Field := TIntegerField.Create(Self);
    Field.FieldKind := fkInternalCalc;
    Field.FieldName := 'WeekNo';
    Field.Name := 'WeekNo';
    Field.DataSet := CDS1;
  end;
© www.soinside.com 2019 - 2024. All rights reserved.