2024年7月26日 星期五

22.VB.NET 筆記 基礎篇 - 時間 (DateTime)

VB.NET 時間(DateTime)筆記(基礎篇)

VB.NET 時間(DateTime) 筆記(基礎篇)

DateTime 用來表示日期與時間。在 VB.NET 中,也常看到 Date 這個型別名稱;它和 DateTime 指向同一種日期時間結構。只要需求牽涉建立日期、取得目前時間、格式化顯示、計算到期日、比較先後順序或計算時間差,就會用到 DateTime。

DateTime 的重點不是把日期當成字串保存,而是讓日期時間可以被正確建立、加減、比較、解析與格式化。表單程式中,若日期來自 DateTimePicker,通常可以直接取得 DateTime;若日期來自 TextBox,則應先使用 TryParse 或固定格式解析。

先理解 DateTime 是什麼

DateTime:用來保存日期與時間的結構,可包含年、月、日、時、分、秒等資訊。VB.NET 的 DateSystem.DateTime 的語言別名。

DateTime 適合處理真正的日期時間資料

  • 日期顯示:報到日、取件日、建立日、截止日。
  • 時間記錄:簽到時間、完成時間、操作時間戳記。
  • 日期運算:加天數、加小時、計算到期日。
  • 先後比較:檢查起日是否早於迄日、判斷是否逾期。
  • 時間差:兩個日期相減後,可得到 TimeSpan
成員 用途 適合情境
DateTime.Now 取得目前日期與時間。 操作紀錄、即時顯示、建立時間。
DateTime.Today 取得今天日期,時間為 00:00:00。 只需要日期,不需要時分秒。
.Date 取出 DateTime 的日期部分。 忽略時間,只比較日期。
New DateTime(...) 建立指定日期時間。 固定日期、測試資料、排程時間。

基本宣告

VB.NET
Dim currentTime As DateTime = DateTime.Now
Dim todayOnly As DateTime = DateTime.Today
Dim fixedTime As New DateTime(2025, 4, 20, 14, 30, 0)
Dim vbDateValue As Date = Date.Today

建立日期與取得目前時間

場景一:櫃台取件時間戳記

這個範例用取件紀錄示範固定日期與目前時間。固定日期適合測試或指定排程,DateTime.Now 適合記錄執行當下時間。

需要的主控項
  • ButtonCreateStamp:建立取件紀錄。
  • LabelStamp:顯示日期與時間。
範例程式碼
VB.NET / Windows Forms
Public Class Form1
    Private Sub ButtonCreateStamp_Click(sender As Object, e As EventArgs) Handles ButtonCreateStamp.Click
        Dim pickupDate As New DateTime(2025, 4, 20)
        Dim createdAt As DateTime = DateTime.Now

        LabelStamp.Text = "取件日期:" & pickupDate.ToString("yyyy/MM/dd") & vbCrLf &
                          "建立時間:" & createdAt.ToString("yyyy/MM/dd HH:mm:ss")
    End Sub
End Class
畫面輸出結果
取件日期:2025/04/20 建立時間:依執行當下系統時間而定
邏輯解析
  • New DateTime(2025, 4, 20) 建立固定日期,時間預設為午夜 00:00:00。
  • DateTime.Now 取得系統目前日期與時間。
  • 固定資料與即時資料用途不同,不應混在同一個變數意義中。

讀取日期時間部分與格式化

場景二:課程簽到時間顯示

日期時間可以拆成年、月、日、時、分,也可以用格式字串輸出成固定顯示格式。這類處理常出現在簽到紀錄、報表與系統訊息。

需要的主控項
  • ButtonShowCheckIn:顯示簽到時間。
  • LabelCheckIn:顯示結果。
範例程式碼
VB.NET / Windows Forms
Public Class Form1
    Private Sub ButtonShowCheckIn_Click(sender As Object, e As EventArgs) Handles ButtonShowCheckIn.Click
        Dim checkInTime As New DateTime(2025, 4, 20, 9, 5, 30)

        LabelCheckIn.Text = "日期:" & checkInTime.ToString("yyyy/MM/dd") & vbCrLf &
                            "時間:" & checkInTime.ToString("HH:mm:ss") & vbCrLf &
                            "月份:" & checkInTime.Month.ToString() & vbCrLf &
                            "分鐘:" & checkInTime.Minute.ToString()
    End Sub
End Class
畫面輸出結果(LabelCheckIn.Text)
日期:2025/04/20 時間:09:05:30 月份:4 分鐘:5
邏輯解析
  • Month 取得月份,Minute 取得分鐘。
  • ToString("yyyy/MM/dd") 控制日期顯示格式。
  • HH 是 24 小時制小時,mm 是分鐘。

格式字串常見混淆

  • MM 代表月份。
  • mm 代表分鐘。
  • HH 代表 24 小時制小時。
  • hh 代表 12 小時制小時,通常需要搭配 tt 顯示上午或下午。

日期加減與不可變性

DateTime 不可變:AddDaysAddHoursAddMinutes 等方法不會修改原本的 DateTime,而是回傳新的 DateTime 值。

場景三:圖書預約保留期限

預約日加上保留天數,就能算出最後取書日。這個範例示範 DateTimePicker 取得日期,以及 AddDays 產生新的到期日。

需要的主控項
  • DateTimePickerReserve:選擇預約日期。
  • ButtonShowReserveDue:計算保留期限。
  • LabelReserveDue:顯示結果。
範例程式碼
VB.NET / Windows Forms
Public Class Form1
    Private Sub ButtonShowReserveDue_Click(sender As Object, e As EventArgs) Handles ButtonShowReserveDue.Click
        Dim reserveDate As DateTime = DateTimePickerReserve.Value.Date
        Dim lastPickupDate As DateTime = reserveDate.AddDays(5)

        LabelReserveDue.Text = "預約日:" & reserveDate.ToString("yyyy/MM/dd") & vbCrLf &
                               "最後取書日:" & lastPickupDate.ToString("yyyy/MM/dd")
    End Sub
End Class
畫面輸出結果(預約日 = 2025/04/20)
預約日:2025/04/20 最後取書日:2025/04/25
邏輯解析
  • DateTimePickerReserve.Value.Date 取得日期部分,時間為 00:00:00。
  • AddDays(5) 回傳 5 天後的新日期。
  • 若沒有把 AddDays 的回傳值存起來,原本日期不會改變。

日期比較與區間檢查

場景四:讀書室預約起訖時間

日期時間可以直接使用 <>= 比較。比較時會同時納入日期與時間,因此起訖時間檢查必須確認結束時間晚於開始時間。

需要的主控項
  • DateTimePickerStart:選擇開始時間。
  • DateTimePickerEnd:選擇結束時間。
  • ButtonCheckRange:檢查區間。
  • LabelRangeResult:顯示結果。
範例程式碼
VB.NET / Windows Forms
Public Class Form1
    Private Sub ButtonCheckRange_Click(sender As Object, e As EventArgs) Handles ButtonCheckRange.Click
        Dim startTime As DateTime = DateTimePickerStart.Value
        Dim endTime As DateTime = DateTimePickerEnd.Value

        If endTime <= startTime Then
            LabelRangeResult.Text = "結束時間必須晚於開始時間"
            Return
        End If

        Dim minutes As Double = (endTime - startTime).TotalMinutes
        LabelRangeResult.Text = "預約區間有效" & vbCrLf &
                                "總分鐘數:" & minutes.ToString("N0")
    End Sub
End Class
畫面輸出結果(09:00 到 11:30)
預約區間有效 總分鐘數:150
邏輯解析
  • endTime <= startTime 可擋下無效區間。
  • 兩個 DateTime 相減會得到 TimeSpan
  • TotalMinutes 是完整時間差換算成分鐘。

只比較日期時:若時間不重要,應使用 .Date 取出日期部分再比較。否則同一天不同時間也可能被判斷成不相等。

解析文字日期:TryParse 與 TryParseExact

場景五:活動日期輸入檢查

若日期來自 TextBox,建議先檢查格式。一般輸入可用 DateTime.TryParse;若要求固定格式,例如 yyyy-MM-dd,可使用 DateTime.TryParseExact

需要的主控項
  • TextBoxEventDate:輸入活動日期,例如 2025-04-20
  • ButtonParseEventDate:解析日期。
  • LabelEventDate:顯示結果。
範例程式碼
VB.NET / Windows Forms
Imports System.Globalization

Public Class Form1
    Private Sub ButtonParseEventDate_Click(sender As Object, e As EventArgs) Handles ButtonParseEventDate.Click
        Dim sourceText As String = TextBoxEventDate.Text.Trim()
        Dim eventDate As DateTime

        If Not DateTime.TryParseExact(sourceText,
                                      "yyyy-MM-dd",
                                      CultureInfo.InvariantCulture,
                                      DateTimeStyles.None,
                                      eventDate) Then
            LabelEventDate.Text = "日期格式需為 yyyy-MM-dd"
            Return
        End If

        LabelEventDate.Text = "活動日期:" & eventDate.ToString("yyyy/MM/dd")
    End Sub
End Class
畫面輸出結果(TextBoxEventDate = 2025-04-20)
活動日期:2025/04/20
邏輯解析
  • TryParseExact 會依指定格式解析。
  • yyyy-MM-dd 要求使用四位年份、兩位月份與兩位日期。
  • 固定格式資料比自由格式輸入更容易控制結果。

TimeSpan:表示兩個時間的差距

TimeSpan:表示一段時間長度。兩個 DateTime 相減後會得到 TimeSpan,可用來取得相差天數、時數、分鐘數或秒數。

場景六:自習室使用時間統計

這個範例用開始與結束時間計算自習室使用多久。若要取得完整小時數,使用 TotalHours;若只讀 Hours,得到的是扣除天數後剩下的小時部分。

需要的主控項
  • ButtonShowStudyTime:計算使用時間。
  • LabelStudyTime:顯示結果。
範例程式碼
VB.NET / Windows Forms
Public Class Form1
    Private Sub ButtonShowStudyTime_Click(sender As Object, e As EventArgs) Handles ButtonShowStudyTime.Click
        Dim startTime As New DateTime(2025, 4, 20, 8, 40, 0)
        Dim endTime As New DateTime(2025, 4, 20, 12, 10, 0)
        Dim duration As TimeSpan = endTime - startTime

        LabelStudyTime.Text = "使用分鐘:" & duration.TotalMinutes.ToString("N0") & vbCrLf &
                              "使用小時:" & duration.TotalHours.ToString("N1")
    End Sub
End Class
畫面輸出結果(LabelStudyTime.Text)
使用分鐘:210 使用小時:3.5
邏輯解析
  • endTime - startTime 會得到 TimeSpan
  • TotalMinutes 表示完整時間差換算成分鐘。
  • TotalHours 表示完整時間差換算成小時。
屬性 意思 注意事項
Days 整天數部分。 不是完整換算小時。
Hours 扣除天數後的小時部分。 不是完整總小時。
TotalHours 完整時間差換算成小時。 常用於統計總時數。
TotalMinutes 完整時間差換算成分鐘。 常用於預約時間長度。

實務判斷與常見誤區

常見問題整理

  • 把日期當字串比較:日期先後應使用 DateTime 比較,不應只比較文字。
  • 忽略時間部分:同一天不同時間的 DateTime 不一定相等;只看日期時應使用 .Date
  • 混淆 MM 與 mm:MM 是月份,mm 是分鐘。
  • 以為 AddDays 會改原值:DateTime 方法通常回傳新值,需接住結果。
  • 直接解析使用者輸入:日期文字可能格式錯誤,應使用 TryParseTryParseExact
  • 誤用 TimeSpan.Hours:若要完整總小時,應使用 TotalHours
需求 建議做法 原因
取得目前時間 DateTime.Now 包含日期與時分秒。
只需要今天日期 DateTime.Today 時間固定為 00:00:00。
只比較日期 使用 .Date 避免時間部分影響結果。
固定格式文字轉日期 TryParseExact 格式清楚,較不受地區設定影響。
計算時間差 TimeSpan 兩個 DateTime 相減後取得。

重點整理

  1. DateTime 用來保存日期與時間,VB.NET 的 Date 是 DateTime 的別名。
  2. DateTime.Now 取得目前日期與時間;DateTime.Today 取得今天日期。
  3. 格式化時要注意 MM 是月份,mm 是分鐘。
  4. AddDaysAddHours 等方法會回傳新的 DateTime,不會修改原值。
  5. DateTime 可直接比較先後,但比較時會包含時間部分。
  6. 只想比較日期時,應先使用 .Date
  7. 文字轉日期時,表單輸入適合使用 TryParse;固定格式適合使用 TryParseExact
  8. 兩個 DateTime 相減會得到 TimeSpan,完整總時數應使用 TotalHours