LoginSignup
0
1

More than 3 years have passed since last update.

C++ Builder > TTimer > 指定時刻(hh, mm)に処理をする (毎日処理) > TTimer(1秒)+期限更新 | Dependency Injectionを使ったテスト

Last updated at Posted at 2017-10-18
動作環境
C++ Builder XE4

前回: https://qiita.com/7of9/items/b473ad1d0e1a24f40d27

処理概要

  • 指定時刻(hh, mm)に処理を行う
  • 毎日処理をする

  • v0.1

    • 実装したが、1日一回の処理を待つわけにはいかない
  • v0.2

    • Dependency Injectionを使って「現在日時」の(時、分、秒)を変更するボタン3つを追加
      • => ボタンをN回押して調整するのが面倒
  • v0.3

    • TDateTimePickerを使った
    • 「現在日時」をTDateTimePickerのDate,Timeで置き換え

コンポーネント概要

  • Timer1sec : 1秒ごとのタイマー
    • 「現在日時」の表示更新
    • 「次の処理日時」に達したか確認する
  • m_nextDateTime: 次の処理日時
  • m_nowDateTime: 現在日時
    • getNow()で使われる
  • TimerAddSecond: 1秒ごとのタイマー
    • m_nowDateTimeを毎秒更新する

code v0.1..v0.3

Unit1.h
//---------------------------------------------------------------------------

#ifndef Unit1H
#define Unit1H
//---------------------------------------------------------------------------
#include <System.Classes.hpp>
#include <Vcl.Controls.hpp>
#include <Vcl.StdCtrls.hpp>
#include <Vcl.Forms.hpp>
#include <Vcl.ExtCtrls.hpp>
#include <Vcl.ComCtrls.hpp>
//---------------------------------------------------------------------------
class TForm1 : public TForm
{
__published:    // IDE で管理されるコンポーネント
    TTimer *Timer1sec;
    TEdit *E_hh;
    TEdit *E_mm;
    TLabel *Label1;
    TButton *B_start;
    TMemo *Memo1;
    TTimer *TimerAddSecond;
    TButton *dbgB_add5Sec;
    TLabel *L_nowDateTime;
    TButton *dbgB_addHour;
    TButton *dbgB_add5Min;
    TDateTimePicker *DTP_time;
    TDateTimePicker *DTP_date;
    TButton *dbgB_setDateTime;
    void __fastcall Timer1secTimer(TObject *Sender);
    void __fastcall B_startClick(TObject *Sender);
    void __fastcall TimerAddSecondTimer(TObject *Sender);
    void __fastcall dbgB_add5SecClick(TObject *Sender);
    void __fastcall dbgB_addHourClick(TObject *Sender);
    void __fastcall dbgB_add5MinClick(TObject *Sender);
    void __fastcall dbgB_setDateTimeClick(TObject *Sender);
private:    // ユーザー宣言
    TDateTime m_nowDateTime; // 現在時刻 (Dependency Injection用)
    TDateTime m_nextDateTime; // 次の処理時間
    TDateTime __fastcall getNextAlarmDateTime(TDateTime now, int hh, int mm);
    TDateTime __fastcall getNow(void);
public:     // ユーザー宣言
    __fastcall TForm1(TComponent* Owner);
};
//---------------------------------------------------------------------------
extern PACKAGE TForm1 *Form1;
//---------------------------------------------------------------------------
#endif
Unit1.dfm
object Form1: TForm1
  Left = 0
  Top = 0
  Caption = 'Form1'
  ClientHeight = 300
  ClientWidth = 635
  Color = clBtnFace
  Font.Charset = DEFAULT_CHARSET
  Font.Color = clWindowText
  Font.Height = -11
  Font.Name = 'Tahoma'
  Font.Style = []
  OldCreateOrder = False
  PixelsPerInch = 96
  TextHeight = 13
  object Label1: TLabel
    Left = 8
    Top = 35
    Width = 179
    Height = 13
    Caption = '                               h                        m'
  end
  object L_nowDateTime: TLabel
    Left = 8
    Top = 8
    Width = 92
    Height = 16
    Caption = 'L_nowDateTime'
    Font.Charset = DEFAULT_CHARSET
    Font.Color = clWindowText
    Font.Height = -13
    Font.Name = 'Tahoma'
    Font.Style = []
    ParentFont = False
  end
  object E_hh: TEdit
    Left = 40
    Top = 32
    Width = 57
    Height = 21
    TabOrder = 0
    Text = '10'
  end
  object E_mm: TEdit
    Left = 120
    Top = 32
    Width = 57
    Height = 21
    TabOrder = 1
    Text = '30'
  end
  object B_start: TButton
    Left = 216
    Top = 30
    Width = 75
    Height = 25
    Caption = 'B_start'
    TabOrder = 2
    OnClick = B_startClick
  end
  object Memo1: TMemo
    Left = 8
    Top = 104
    Width = 617
    Height = 185
    Lines.Strings = (
      'Memo1')
    ScrollBars = ssVertical
    TabOrder = 3
  end
  object dbgB_add5Sec: TButton
    Left = 320
    Top = 8
    Width = 75
    Height = 25
    Caption = 'dbgB_add5Sec'
    TabOrder = 4
    OnClick = dbgB_add5SecClick
  end
  object dbgB_addHour: TButton
    Left = 320
    Top = 73
    Width = 75
    Height = 25
    Caption = 'dbgB_addHour'
    TabOrder = 5
    OnClick = dbgB_addHourClick
  end
  object dbgB_add5Min: TButton
    Left = 320
    Top = 42
    Width = 75
    Height = 25
    Caption = 'dbgB_add5Min'
    TabOrder = 6
    OnClick = dbgB_add5MinClick
  end
  object DTP_time: TDateTimePicker
    Left = 440
    Top = 35
    Width = 81
    Height = 21
    Date = 43026.485760914350000000
    Time = 43026.485760914350000000
    Kind = dtkTime
    TabOrder = 7
  end
  object DTP_date: TDateTimePicker
    Left = 440
    Top = 8
    Width = 97
    Height = 21
    Date = 43026.488268506950000000
    Time = 43026.488268506950000000
    TabOrder = 8
  end
  object dbgB_setDateTime: TButton
    Left = 440
    Top = 62
    Width = 75
    Height = 25
    Caption = 'dbgB_setDateTime'
    TabOrder = 9
    OnClick = dbgB_setDateTimeClick
  end
  object Timer1sec: TTimer
    OnTimer = Timer1secTimer
    Left = 88
    Top = 64
  end
  object TimerAddSecond: TTimer
    OnTimer = TimerAddSecondTimer
    Left = 136
    Top = 64
  end
end

Unit1.cpp
//---------------------------------------------------------------------------

#include <vcl.h>
#pragma hdrstop

#include <DateUtils.hpp>
#include "Unit1.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------

/*
v0.3 Oct. 18, 2017 Improve debug feature
    - add [dbgB_setDateTime]
    - add [DTP_time]
    - add [DTP_date]
v0.2 Oct. 18, 2017 Dependency Injection for Now()
    - add debug
        + add [dbgB_addHour]
        + add [dbgB_add5Min]
        + add [dbgB_add5Sec]
    - add getNow()
    - add [m_nowDateTime]
v0.1 Oct. 18, 2017
    - add [kInit_dateTime]
    - add getNextAlarmDateTime()
    - add [m_nextDateTime]
*/

static const TDateTime kInit_dateTime = (TDateTime)0;

__fastcall TForm1::TForm1(TComponent* Owner)
    : TForm(Owner)
{
    m_nextDateTime = kInit_dateTime; // @ctor
    m_nowDateTime = Now(); // @ ctor
}
//---------------------------------------------------------------------------

TDateTime __fastcall TForm1::getNextAlarmDateTime(TDateTime now, int hh, int mm)
{
    TDateTime res = RecodeHour(now, hh);
    res = RecodeMinute(res, mm);
    res = RecodeSecond(res, 0);
    if (res <= now) {
        res = IncDay(res, 1);
    }
    return res;
}

TDateTime __fastcall TForm1::getNow(void)
{
    return m_nowDateTime;
    //return Now();
}

void __fastcall TForm1::Timer1secTimer(TObject *Sender)
{
    L_nowDateTime->Caption = getNow().FormatString(L"yyyy/mm/dd hh:nn:ss");

    if (m_nextDateTime == kInit_dateTime) {
        return;
    }
    if (getNow() > m_nextDateTime) {
        m_nextDateTime = IncDay(m_nextDateTime, 1);

        String msg = L"Expired @ " + getNow().DateTimeString();
        Memo1->Lines->Add(msg);
    }
}
//---------------------------------------------------------------------------
void __fastcall TForm1::B_startClick(TObject *Sender)
{
    // TODO: 0m > 関数化

    // 1. フォームからの読取り
    int next_hh, next_mm;
    try {
        next_hh = StrToIntDef(E_hh->Text, -1);
        next_mm = StrToIntDef(E_mm->Text, -1);
    } catch (Exception &exc) {
        ShowMessage(exc.Message);
        return;
    }
    if (next_hh < 0 || next_mm < 0) {
        Memo1->Lines->Add(L"Error: set numerical values for [hh] and [mm]");
        return; // error
    }

    // 2. 次の日時取得
    m_nextDateTime = getNextAlarmDateTime(Now(), next_hh, next_mm);

    String msg = "now: " + getNow().DateTimeString() + L" next: " + m_nextDateTime.DateTimeString();
    Memo1->Lines->Add(msg);
}
//---------------------------------------------------------------------------
void __fastcall TForm1::TimerAddSecondTimer(TObject *Sender)
{
    m_nowDateTime = IncSecond(m_nowDateTime, 1);
}
//---------------------------------------------------------------------------
// デバッグ用
void __fastcall TForm1::dbgB_add5SecClick(TObject *Sender)
{
    m_nowDateTime = IncSecond(m_nowDateTime, 5);
}
void __fastcall TForm1::dbgB_add5MinClick(TObject *Sender)
{
    m_nowDateTime = IncMinute(m_nowDateTime, 5);
}
void __fastcall TForm1::dbgB_addHourClick(TObject *Sender)
{
    m_nowDateTime = IncHour(m_nowDateTime, 1);
}
void __fastcall TForm1::dbgB_setDateTimeClick(TObject *Sender)
{
    m_nowDateTime = DateOf(DTP_date->Date) + TimeOf(DTP_time->Time);
}
//---------------------------------------------------------------------------

結果

Expired が発生した後にTDateTimePickerの日時を次の発生日時の前に変更してdbgB_setDateTimeを押す、ということを繰り返した。
以下となり、実装としては正しそう。

qiita.png

追記

(2017/10/23)

StrToIntDef()にてtry, catchをしているが、try, catchは不要のように思う。

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1