C++ Builder XE4, 10.2 Tokyo > ファイル名から日付を取得 + 指定の日付以前のファイルを削除 > v0.1..v0.3

```txt:動作環境
C++ Builder XE4
RAD Studio 10.2 Tokyo Update 2 (追記: 2018/01/09)
```

ファイル名に日付が入っている状況で、指定日付以前のファイルを削除する処理。

### 対象ファイル

[bash > Brace Expansionで日付のダミーファイルを作る | ファイル名失敗時: MinGW32でファイルを消す](https://qiita.com/7of9/items/078ff8702cbbb64e5d88)
にて作ったファイル。

## v0.1, v0.2
### code

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

#include <vcl.h>
#pragma hdrstop

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

/*
v0.2 2017/10/17
  - リストの対象ファイルを削除 (ゴミ箱には行かない)
  - isDateBefore()追加
  - getFileDateTime()追加
v0.1 2017/10/17
  - 対象フォルダにあるファイルリストを取得
*/


String kTargetFolder = L"D:\\WORK\\filedelete_171017";
TDateTime kLastDate = VarToDateTime("2017/01/15 00:00:00"); // Note: VarToDateTime()使用時はLマクロにしない

__fastcall TForm1::TForm1(TComponent* Owner)
	: TForm(Owner)
{
}
//---------------------------------------------------------------------------

static TDateTime getFileDate(String filePath)
{
	String filename = ExtractFileName(filePath);
	// filename:
	//   例:"X_20170131.csv" (2017 Jan. 31のファイル)

	String strdt = filename.SubString(3, 8); // 3: yyyyの開始インデックス

	// 12345678
	// yyyymmdd
	strdt.Insert("/", 7); // mmとddの間
	strdt.Insert("/", 5); // yyyyとmmの間

	OutputDebugString(filename.c_str());

	return VarToDateTime(strdt + L" 00:00:00");
}

static bool isDateBefore(String filepath, TDate lastDate)
{
	TDateTime trgt;
	try {
		trgt = getFileDate(filepath);
	} catch (...) {
		return false; // ファイル名が日付型でない場合
	}
	if (trgt > lastDate) {
		return false;
	}
	return true;
}

void __fastcall TForm1::dbgB_getListClick(TObject *Sender)
{
	String searchPattern = L"*.csv";
	TSearchOption option = TSearchOption::soAllDirectories;

	TStringDynArray fileList = TDirectory::GetFiles(kTargetFolder, searchPattern, option);
	int allcnt = fileList.Length;

	std::unique_ptr<TStringList> lst(new TStringList);

	TDateTime filedt;
	for(int idx = 0; idx < fileList.Length; idx++) {
		if (isDateBefore(fileList[idx], kLastDate) == false) {
			continue;
		}
		lst->Add(fileList[idx]);

		TFile::Delete(fileList[idx]); /***********************/
	}

    String msg = IntToStr(lst->Count) + L"/" + IntToStr(allcnt);
	OutputDebugString(msg.c_str());

	Memo1->Lines->Assign(lst.get());
}
//---------------------------------------------------------------------------
```

### 実行結果

`2017/01/15`までのファイルが削除される。

### 備考

TFile::Delete()の場合、ごみ箱に行かずに削除される
(Shift + Deleteと同じ)。 

TFile::Move()でごみ箱に移動しようかと検討したが、ごみ箱のパスを取得する方法が見つかっていない。
関連: https://qiita.com/7of9/items/7bb5d9837c696754995d

## v0.3

- 最終日だけでなく、最終日と日数に変更
- 処理を関数化

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

#include <vcl.h>
#pragma hdrstop

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

/*
v0.3 2017/10/17
	- change to range
		+ isInRange() takes [days] arg
		+ refactor > rename isDateBefore() to isInRange()
	- deletePastFiles()追加
v0.2 2017/10/17
	- リストの対象ファイルを削除 (ゴミ箱には行かない)
	- isDateBefore()追加
	- getFileDateTime()追加
v0.1 2017/10/17
	- 対象フォルダにあるファイルリストを取得
*/


String kTargetFolder = L"D:\\WORK\\filedelete_171017";
TDateTime kLastDate = VarToDateTime("2017/01/15 00:00:00"); // Note: VarToDateTime()使用時はLマクロにしない

__fastcall TForm1::TForm1(TComponent* Owner)
	: TForm(Owner)
{
}
//---------------------------------------------------------------------------

static TDateTime getFileDate(String filePath)
{
	String filename = ExtractFileName(filePath);
	// filename:
	//   例:"X_20170131.csv" (2017 Jan. 31のファイル)

	String strdt = filename.SubString(3, 8); // 3: yyyyの開始インデックス

	// 12345678
	// yyyymmdd
	strdt.Insert("/", 7); // mmとddの間
	strdt.Insert("/", 5); // yyyyとmmの間

	OutputDebugString(filename.c_str());

	return VarToDateTime(strdt + L" 00:00:00");
}

static bool isInRange(String filepath, TDate lastDate, int days)
{
	TDateTime trgt;
	TDateTime startdt = IncDay(lastDate, -(days - 1));

	try {
		trgt = getFileDate(filepath);
	} catch (...) {
		return false; // ファイル名が日付型でない場合
	}
	if (trgt < startdt) {
		return false;
	}
	if (trgt > lastDate) {
		return false;
	}
	return true;
}

void __fastcall TForm1::deletePastFiles(String filePattern, TDateTime lastDate, int days, String targetDir, TStringList *delList)
{
	TSearchOption option = TSearchOption::soAllDirectories;

	TStringDynArray fileList = TDirectory::GetFiles(kTargetFolder, filePattern, option);
	int allcnt = fileList.Length;

	for(int idx = 0; idx < fileList.Length; idx++) {
		if (isInRange(fileList[idx], lastDate, days) == false) {
			continue;
		}
		if (delList != NULL) {
			delList->Add(fileList[idx]);
		}

		TFile::Delete(fileList[idx]); // ごみ箱に行かずに消える
	}
}

void __fastcall TForm1::dbgB_getListClick(TObject *Sender)
{
	int days = 10; // テスト用
	std::unique_ptr<TStringList> lst(new TStringList);

	deletePastFiles(L"*.csv", kLastDate, /*days=*/days, /*targetDir=*/kTargetFolder, lst.get());
	Memo1->Lines->Assign(lst.get());
	String msg = IntToStr(lst->Count) + L" deleted";
	OutputDebugString(msg.c_str());
}
//---------------------------------------------------------------------------
```

1月6日から1月15日のファイルを消すようになった。