---
# System prepended metadata

title: 'DB: DateTime2 Convert DateTime & EF 的陷阱'
tags: [被玩壞了]

---

# DB: DateTime2 Convert DateTime & EF 的陷阱
###### tags: `被玩壞了`

## 發生情境
故事是這樣的，又是~~該死的~~日期問題
我們的主角---**開始日期**和**截止日期**
此時的 DB 資料型態是 Datetime

### 舉例: 一個報名機制
開始日期 = 7/1
截止日期 = 7/31
理論上， 7/31 應該要可以報名，但發現不行。於是發現 DB 中，截止日期為 2020/07/31 00:00:00.000，這樣的意思就是 7/30 23:59:59 就截止了！

## 試圖修正
於是在程式中，我試圖讓截止日期的欄位去存成 2020-07-28 23:59:59

程式碼如下：
```
if (@new.LaunchEndDate.HasValue)
    @new.LaunchEndDate = @new.LaunchEndDate.Value.Add(DateTime.MaxValue.TimeOfDay);
```
在這邊使用 DateTime.MaxValue 感覺應該是正確的選擇，好維護的程式碼。

### 發生什麼事？沒有 23:59:59，還變成下一天了！

**[寫 Log](https://hackmd.io/@Moira/S1RpmHplv) 才發現，EF 在這邊給的型態是 Datetime2！**

![](https://i.imgur.com/Z9L1vTe.png)

## 試著了解原因
### 解釋 Datetime & Datetime2 差別
Datetime 的精準度到小數點後 3 碼 00:00:00.000
Datetime2 的精準度到小數點後 7 碼 00:00:00.0000000

### Datetime2 最大值轉成 DateTime 時四捨五入
![](https://i.imgur.com/85L8ux7.png)

![](https://i.imgur.com/VjE451r.png)

## 最終修正

因為發現了 EF 轉的語法是 Datetime2
而程式寫的 Datetime 是 MaxValue，代表極有可能是 => 23:59:59.9999999
故只好捨棄 MaxValue ，自己改小時、分鐘、秒數，期望他會是 23:59:59.0000000

程式碼如下：
```
if (@new.LaunchEndDate.HasValue)
    @new.LaunchEndDate = @new.LaunchEndDate.Value.Add(DateTime.MinValue.AddHours(23).AddMinutes(59).AddSeconds(59).TimeOfDay);
```
這邊改用 DateTime.MinValue 在去更改 Hours, Minutes, Seconds ( 用 DateTime.MinValue 感覺程式碼比較精簡而已，也可以另外寫XD or 太多地方要用就寫成 Function )

## 結果：成功