Accessing the Day, Month, and Year

From RAD Studio
Jump to: navigation, search

Go Up to Tracking the Date


An encoded numeric date is fine for applications, but humans prefer to work with days, months, and years. You can provide alternate access to those elements of the stored, encoded date by creating properties.

Because each element of the date (day, month, and year) is an integer, and because setting each requires encoding the date when set, you can avoid duplicating the code each time by sharing the implementation methods for all three properties. That is, you can write two methods, one to read an element and one to write one, and use those methods to get and set all three properties.

To provide design-time access to the day, month, and year, you do the following:

  1. Declare the three properties, assigning each a unique index number:

    Delphi:

    type
      TSampleCalendar = class(TCustomGrid)
      public
        property Day: Integer index 3 read GetDateElement write SetDateElement;
        property Month: Integer index 2 read GetDateElement write SetDateElement;
        property Year: Integer index 1 read GetDateElement write SetDateElement;
        // …
    

    C++:

    class PACKAGE TSampleCalendar : public TCustomGrid
    {
        // …
    public:
        __property int Day = {read=GetDateElement, write=SetDateElement, index=3,
          nodefault};
        __property int Month = {read=GetDateElement, write=SetDateElement, index=2,       nodefault};
        __property int Year = {read=GetDateElement, write=SetDateElement, index=1,       nodefault};
    };
    
  2. Declare and write the implementation methods, setting different elements for each index value:

    Delphi:

    type
      TSampleCalendar = class(TCustomGrid)
      private
        function GetDateElement(Index: Integer): Integer;         { note the Index parameter }
        procedure SetDateElement(Index: Integer; Value: Integer);
        // …
    function TSampleCalendar.GetDateElement(Index: Integer): Integer;
    var
      AYear, AMonth, ADay: Word;
    begin
      DecodeDate(FDate, AYear, AMonth, ADay);             { break encoded date into elements }
      case Index of
        1: Result := AYear;
        2: Result := AMonth;
        3: Result := ADay;
        else Result := -1;
      end;
    end;
    procedure TSampleCalendar.SetDateElement(Index: Integer; Value: Integer);
    var
      AYear, AMonth, ADay: Word;
    begin
      if Value > 0 then                                      { all elements must be positive }
      begin
        DecodeDate(FDate, AYear, AMonth, ADay);                  { get current date elements }
        case Index of                                   { set new element depending on Index }
          1: AYear := Value;
          2: AMonth := Value;
          3: ADay := Value;
          else Exit;
        end;
        FDate := EncodeDate(AYear, AMonth, ADay);                 { encode the modified date }
        Refresh;                                               { update the visible calendar }
      end;
    end;
    

    C++:

    // header file
    class PACKAGE TSampleCalendar : public TCustomGrid
    {
    private:
        int __fastcall GetDateElement(int Index);           // note the Index parameter
        void __fastcall SetDateElement(int Index, int Value);
        // …
     };
    
    // implementation file
    int __fastcall TSampleCalendar::GetDateElement(int Index)
    {
      unsigned short AYear, AMonth, ADay;
      int result;
      FDate.DecodeDate(&AYear, &AMonth, &ADay);            // break encoded date into elements
      switch (Index)
      {
        case 1: result = AYear;  break;
        case 2: result = AMonth; break;
        case 3: result = ADay;   break;
        default: result = -1;
      }
      return result;
    }
    void __fastcall TSampleCalendar::SetDateElement(int Index, int Value)
    {
      unsigned short AYear, AMonth, ADay;
      if (Value > 0)                                   // all elements must be positive
      {
        FDate.DecodeDate(&AYear, &AMonth, &ADay);     // get current date elements
        switch (Index)
        {
          case 1: AYear = Value;     break;
          case 2: AMonth = Value;    break;
          case 3: ADay = Value;      break;
          default: return;
        }
      }
      FDate = TDateTime(AYear, AMonth, ADay);         // encode the modified date
      Refresh();                                      // update the visible calendar
    }
    

Now you can set the calendar's day, month, and year at design time using the Object Inspector or at run time using code. Of course, you have not yet added the code to paint the dates into the cells, but now you have the needed data.

See Also