C# と VB.NET の質問掲示板

ASP.NET、C++/CLI、Java 何でもどうぞ

C# と VB.NET の入門サイト

Re[1]: 22時と6時など、日付を跨いだ条件分岐


(過去ログ 133 を表示中)

[トピック内 7 記事 (1 - 7 表示)]  << 0 >>

■78712 / inTopicNo.1)  22時と6時など、日付を跨いだ条件分岐
  
□投稿者/ WAN (10回)-(2016/02/11(Thu) 22:18:02)

分類:[VB.NET/VB2005 以降] 

2016/02/11(Thu) 22:26:46 編集(投稿者)

失礼致します。

環境はVisual Studio 2012の環境下で、言語はVB2012、.netフレームワークは3.0です。

(1)22時〜6時
(2)6時〜14時
(3)14時〜22時

以上の条件分岐を作成使用しています。
(2)(3)に関してはこれで良いと思うのですが、
(1)に関しては、現在の時間(22時とする) > 6時とすると「22」と「6」なので
条件が成立しないことになってしまいますので、「FTime <= Time3」を除外しています。
以下のプログラムは一応動作していますが時間指定する場合この指定で正しいのでしょうか。
(まだお試しソースなので宣言が多いと思うので申し訳無いです)

Public Class Form1

Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click

Dim NowTime As Date = DateTime.Now
Dim dt1 As Date = NowTime.ToString("F")
Dim dt2 As Date = NowTime.ToString("HH:mm")

Dim FTime As DateTime = DateTime.Parse(dt1)
Dim DTime As DateTime = DateTime.Parse(dt2)

Dim tt1 As Date = NowTime.ToString("06:00")
Dim tt2 As Date = NowTime.ToString("14:00")
Dim tt3 As Date = NowTime.ToString("22:00")

Dim Time1 As DateTime = DateTime.Parse(tt1)
Dim Time2 As DateTime = DateTime.Parse(tt2)
Dim Time3 As DateTime = DateTime.Parse(tt3)

If Time3 < FTime Then
MsgBox(Time3 & "から" & NowTime)
ElseIf Time1 < FTime And FTime <= Time2 Then
MsgBox("Time1から" & NowTime)
ElseIf Time2 < FTime And FTime <= Time3 Then
MsgBox("Time2から" & NowTime)
End If

End Sub
End Class
引用返信 編集キー/
■78713 / inTopicNo.2)  Re[1]: 22時と6時など、日付を跨いだ条件分岐
□投稿者/ furu (47回)-(2016/02/11(Thu) 22:51:12)
No78712 (WAN さん) に返信
> 環境はVisual Studio 2012の環境下で、言語はVB2012、.netフレームワークは3.0です。
>
> (1)22時〜6時
> (2)6時〜14時
> (3)14時〜22時

VB知らないので、考え方だけですが
(1)は、〜6時 or 22時〜です。

or を使いたくないならば、0〜6時の時は事前に24時間を足し、
(0〜6時 → 24時〜30時)とし、

(1)の条件を22時〜30時にします。

ただし、この場合、DateTimeよりTimeSpanを使った方がいいです。

それから、日時や時間を作るのに文字列からのParseを
使うのは止めた方がいいです。

引用返信 編集キー/
■78724 / inTopicNo.3)  Re[2]: 22時と6時など、日付を跨いだ条件分岐
□投稿者/ WAN (11回)-(2016/02/12(Fri) 22:11:58)
> VB知らないので、考え方だけですが
> (1)は、〜6時 or 22時〜です。
>
> or を使いたくないならば、0〜6時の時は事前に24時間を足し、
> (0〜6時 → 24時〜30時)とし、
>
> (1)の条件を22時〜30時にします。
>
> ただし、この場合、DateTimeよりTimeSpanを使った方がいいです。
なるほど、このような方法があるんですね。

> それから、日時や時間を作るのに文字列からのParseを
> 使うのは止めた方がいいです。
プログラム素人なのでダメな理由がピンときていませんが
頭に叩き込んでおこうと思います。

アドバイスありがとうございました!
解決済み
引用返信 編集キー/
■78753 / inTopicNo.4)  Re[3]: 22時と6時など、日付を跨いだ条件分岐
□投稿者/ とくま (3回)-(2016/02/15(Mon) 13:39:44)
No78724 (WAN さん) に返信
とりあえず、
無駄な処理や、後からコードを読んだ他人が誤解しそうな所がたくさんありますが、
プログラムの1つの基準は起こり得る全てのパターンで要件を満たしている
かどうかだと思います。

境界値でバグが起こり易いことを考えれば、今回テストすべきは
 a)00:00…日付の境界
 b)05:00…(1)で日付変更後
 c)06:00…(1)と(2)の境界
 d)12:00…(2)
 e)14:00…(2)と(3)の境界
 f)18:00…(3)
 g)22:00…(3)と(1)の境界
 h)23:00…(1)で日付変更前
の8パターンだと思います。

結果、a)b)c)の3パターンで判定されないように思いますがどうでしょうか?
(1)と判定されるべきが判定されないのであれば、正しくないという事になります。
furu さんご指摘の通り
>(1)は、〜6時 or 22時〜です。
〜6時の判定が抜けていないでしょうか。

また、
ほとんどの言語で日付型は"年月日時分秒"を一体として覚えていて、時分だけ
設定しても、その他をデフォルト値で補完してしまうというのは覚えておいた
方がいいかもです。
https://msdn.microsoft.com/ja-jp/library/3eaydw6e.aspx
内部では連続した数値データに置き換えて記憶しているので、切り離せないんです。
つまり
 Dim dt2 As Date = NowTime.ToString("HH:mm")
 Debug.Print(dt2.ToString("yyyy/MM/dd HH:mm"))
>0001/01/01 20:23
西暦1年1月1日になってます。
※言語によっては1900年になったり、1753年になったりします。

引用返信 編集キー/
■78754 / inTopicNo.5)  Re[4]: 22時と6時など、日付を跨いだ条件分岐
□投稿者/ とくま (4回)-(2016/02/15(Mon) 13:41:38)
No78753 (とくま さん) に返信
それとは別に、ぱっと見以上にやっかいなコードなんですね。。。
>それから、日時や時間を作るのに文字列からのParseを
>使うのは止めた方がいいです。
私もなんのことかなぁ…って思ってたら
http://dobon.net/vb/dotnet/string/datetimeparse.html
>'日付を省略すると、現在の日付となる
なんじゃこりゃあ。。。
 Debug.Print(NowTime.ToString("06:00"))
 Dim tt1 As Date = NowTime.ToString("06:00")
 Debug.Print(tt1.ToString("yyyy/MM/dd HH:mm"))
 Debug.Print(tt1.ToString)
 Dim Time1 As DateTime = DateTime.Parse(tt1)
 Debug.Print(Time1.ToString("yyyy/MM/dd HH:mm"))
>06:00
>0001/01/01 06:00
>06:00
>2016/02/12 06:00
西暦1年1月1日になる動きと食い違ってて非常に危険ですね。
1回暗黙の文字列変換が入って時刻だけしか出力されないから
補完とか。。。予想を超えてました。

関数化してのテスト結果とPCのシステム時刻を変更してのテストが
食い違っていて???ってなってたんですん。。。
関数化したら、過去日が軒並み判定されずに未来日は全てTime3に
なっていました。
    Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
        Dim NowTime As Date

        NowTime = New DateTime(2016, 2, 10, 13, 59, 0)
        Call test(NowTime)
        NowTime = New DateTime(2016, 2, 10, 14, 0, 0)
        Call test(NowTime)
        NowTime = New DateTime(2016, 2, 10, 14, 1, 0)
        Call test(NowTime)

        NowTime = New DateTime(2016, 2, 12, 5, 59, 0)
        Call test(NowTime)
        NowTime = New DateTime(2016, 2, 12, 6, 0, 0)
        Call test(NowTime)
        NowTime = New DateTime(2016, 2, 12, 6, 1, 0)
        Call test(NowTime)
        NowTime = New DateTime(2016, 2, 12, 13, 59, 0)
        Call test(NowTime)
        NowTime = New DateTime(2016, 2, 12, 14, 0, 0)
        Call test(NowTime)
        NowTime = New DateTime(2016, 2, 12, 14, 1, 0)
        Call test(NowTime)
        NowTime = New DateTime(2016, 2, 12, 21, 59, 0)
        Call test(NowTime)
        NowTime = New DateTime(2016, 2, 12, 22, 0, 0)
        Call test(NowTime)
        NowTime = New DateTime(2016, 2, 12, 22, 1, 0)
        Call test(NowTime)
        NowTime = New DateTime(2016, 2, 13, 0, 0, 0)
        Call test(NowTime)
        NowTime = New DateTime(2016, 2, 13, 1, 0, 0)
        Call test(NowTime)

        NowTime = New DateTime(2016, 2, 14, 13, 59, 0)
        Call test(NowTime)
        NowTime = New DateTime(2016, 2, 14, 14, 0, 0)
        Call test(NowTime)
        NowTime = New DateTime(2016, 2, 14, 14, 1, 0)
        Call test(NowTime)
    End Sub

    Sub test(t As Date)
        Debug.Print("")
        Debug.Print(t.ToString("yyyy/MM/dd HH:mm"))

        Dim NowTime As Date = t
        Dim dt1 As Date = NowTime.ToString("F")
        'Dim dt2 As Date = NowTime.ToString("HH:mm")

        Dim FTime As DateTime = DateTime.Parse(dt1)
        'Dim DTime As DateTime = DateTime.Parse(dt2)

        Dim tt1 As Date = NowTime.ToString("06:00")
        Dim tt2 As Date = NowTime.ToString("14:00")
        Dim tt3 As Date = NowTime.ToString("22:00")

        Dim Time1 As DateTime = DateTime.Parse(tt1)
        Dim Time2 As DateTime = DateTime.Parse(tt2)
        Dim Time3 As DateTime = DateTime.Parse(tt3)

        If Time3 < FTime Then
            Debug.Print("Time3から" & NowTime)
        ElseIf Time1 < FTime And FTime <= Time2 Then
            Debug.Print("Time1から" & NowTime)
        ElseIf Time2 < FTime And FTime <= Time3 Then
            Debug.Print("Time2から" & NowTime)
        End If
    End Sub


解決済み
引用返信 編集キー/
■78759 / inTopicNo.6)  Re[1]: 22時と6時など、日付を跨いだ条件分岐
□投稿者/ 魔界の仮面弁士 (644回)-(2016/02/15(Mon) 16:06:17)
No78712 (WAN さん) に返信
> (1)22時〜6時
> (2)6時〜14時
> (3)14時〜22時

別案。

元の日時を、事前に +2 時間しておくことで、
上記条件が「0時以上24時未満」の範囲内に揃うようにしてみました。



Enum TimeRange
 ''' <summary>22時〜6時</summary>
 Night = 1

 ''' <summary>6時〜14時</summary>
 DayTime = 2

 ''' <summary>14時〜22時</summary>
 Evening = 3
End Enum


Function GetTimeRage(dt As Date) As TimeRange
 Const OffsetHour = 2.0
 Select Case dt.AddHours(OffsetHour).TimeOfDay.TotalHours
  Case Is < OffsetHour + 6 : Return TimeRange.Night
  Case Is < OffsetHour + 14 : Return TimeRange.DayTime
  Case Else : Return TimeRange.Evening
 End Select
End Function

Function GetTimeRage() As TimeRange
 Return GetTimeRage(Now)
End Function
解決済み
引用返信 編集キー/
■78760 / inTopicNo.7)  Re[4]: 22時と6時など、日付を跨いだ条件分岐
□投稿者/ 魔界の仮面弁士 (645回)-(2016/02/15(Mon) 16:19:19)
No78753 (とくま さん) に追記
> 境界値でバグが起こり易いことを考えれば、今回テストすべきは

とくまさんも仰っていますが、しきい値をしっかり確認しておきましょう。


> (1)22時〜6時
> (2)6時〜14時

たとえば出退勤のシステムなどにおいては、
集計システムが秒情報を持たず、HH:mm で管理している場合、
 06:00:59.9999999 までは (1) とし、
 06:01:00.0000000 以降を (2) とする
というルールで運用されているケースがあります。

同様に、HH:mm:ss で管理されており、
秒未満の情報が切り捨てられるような場合には、
 06:00:00.9999999 までは (1) とし、
 06:00:01.0000000 以降を (2) とする
というルールになることもあります。


そして先の私のコードの場合は、
 05:59:59.9999999 までは (1) とし、
 06:00:00.0000000 以降を (2) とする
という処理方法です。
解決済み
引用返信 編集キー/


トピック内ページ移動 / << 0 >>

このトピックに書きこむ

過去ログには書き込み不可

管理者用

- Child Tree -