時間(DateTime型)を丸める処理を書いてみました。
果てーーーーーーーーーーしなく地味な内容です。。。
Environment
- Visual Studio 2015 Update1 ( Enterprise )
System.DateTimeとSystem.TimeSpanしか使わないので、C#でこれ使えれば環境の依存はないです。
ただ、サンプルコードでは、C#6.0のExpression-bodied functionとstring-interpolation(文字列挿入)は使ってます。まだの方は、先生がわかりやすくまとめておりますので、ご参考にしていただければと。
C# 6.0 の新機能 expression-bodied な関数メンバー
C# 6.0 の新機能 文字列挿入
Overview
やりたいことは、特定の時間に対して、既定のインターバルで切り上げたり切り下げたりしたい。
具体的には、
08:59:01に対して、インターバルが15分だと、
- 切り上げ:09:00:00
- 切り下げ:08:45:00
09:00:01に対して、インターバル15分だと、
- 切り上げ:09:15:00
- 切り下げ:09:00:00
09:00:00ちょうどの場合は、
- 切り上げ:09:00:00
- 切り下げ:09:00:00
をしたいだけです。
インターバルに入れる数値の前提は、以下とします。
- 0はあかん。
- 60で割り切れる数字
実装方法なんてなんぼでもあると思いますが、今回はDateTime.Ticks プロパティ (System) | Microsoft DocsとTimeSpan.Ticks プロパティ (System) | Microsoft Docsを使います。
地味感に溢れているので、説明雑に行きます。
切り上げ
現在のTicksからインターバルのTicksから1引いた数値を割って、それをインターバルのTicksで掛け算すればサクッとできちゃいます(説明が雑ですいません...)。
static DateTime RoundUp(DateTime input, TimeSpan interval) => new DateTime(((input.Ticks + interval.Ticks - 1) / interval.Ticks) * interval.Ticks, input.Kind);
09:00:00のようなちょうどの時間に対応するため、1引いてます(説明が雑ですいませ...)。
切り下げ
さっきの考え方を逆にしてあげればよいだけです(説明が雑で...)。
static DateTime RoundDown(DateTime input, TimeSpan interval) => new DateTime((((input.Ticks + interval.Ticks) / interval.Ticks) - 1) * interval.Ticks, input.Kind);
インターバルのTicksからは1を引かず、割り算した結果から1ひいちゃえばサクサクッとできちゃいます(説.....)。
>動作確認
Consoleのプロジェクトで、試しに動かしてみると、
public void Main() { var interval = TimeSpan.FromMinutes(15); var dt1 = DateTime.Parse("2016-01-03 08:59:01"); Inspection1(dt1, interval); var girigiriSaaaafe = DateTime.Parse("2016-01-03 09:00:00"); Inspection1(girigiriSaaaafe, interval); var chikooooooooku = DateTime.Parse("2016-01-03 09:00:01"); Inspection1(chikooooooooku, interval); } static void Inspection1(DateTime input, TimeSpan interval) { Console.WriteLine($"input:{input} (interval:{interval})"); Console.WriteLine($"up :{RoundUp(input, interval)}"); Console.WriteLine($"down :{RoundDown(input, interval)}"); Console.WriteLine(); }
結果は、こんな感じで無事に表示。
サンプルということでべたーっと書きましたが、用途に応じて拡張メソッドにしてあげるとかでしょうかね。
あと、インターバルに制約設けるなら、enumかなんかにした方がリスクないでしょうかね。
おしまい。