動作環境
C++ Builder XE4
前回: https://qiita.com/7of9/items/b473ad1d0e1a24f40d27
処理概要
- 指定時刻(hh, mm)に処理を行う
毎日処理をする
-
v0.1
- 実装したが、1日一回の処理を待つわけにはいかない
-
v0.2
- Dependency Injectionを使って「現在日時」の(時、分、秒)を変更するボタン3つを追加
- => ボタンをN回押して調整するのが面倒
- Dependency Injectionを使って「現在日時」の(時、分、秒)を変更するボタン3つを追加
-
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を押す、ということを繰り返した。
以下となり、実装としては正しそう。
追記
(2017/10/23)
StrToIntDef()にてtry, catchをしているが、try, catchは不要のように思う。