本文
事情發生是這樣的,今天突然接到一個線上問題,數據報表顯示有問題有幾個不該出現的數據卻出現了。
問題發生當下馬上查了一下撈取數據顯示的語法,想知道判斷日期的地方是否有遺漏,然後就看到了一段類似於下列的語法
WHERE CONVERT(VARCHAR, KeyInDate, 111) >= CONVERT(VARCHAR, Getdate(), 111)
當下不疑有他第一個查的當然是 CONVERT() 的用法,查了一下發現是 VARCHAR 可以轉換成 DATETIME 的語法,而日期格式也有幾種特殊用法就是由後面的數字來區別。
數字 | 日期格式 | 範例 |
---|---|---|
23 | yyyy-mm-dd | 2021-05-31 |
111 | yyyy/mm/dd | 2021/05/31 |
112 | yyyymmdd | 20210531 |
SELECT CONVERT(VARCHAR, Getdate(), 23)
SELECT CONVERT(VARCHAR, Getdate(), 111)
SELECT CONVERT(VARCHAR, Getdate(), 112)
而這次的問題就是原本存放 KeyInDate 這個 VARCHAR 欄位的格式從原本的 2021/05/31 不知道何時起被改成了 2021-05-31,導致原本 WHERE 判斷會誤判。
第一個想法就是全部都改成 111 的方式,後來找主管討論了一下得知原來還有 112 這種 Format,為了預防未來還有可能的奇怪格式出現就使用了 112 這種格式,打完收工又拯救了一次奇怪問題。
大概有人開始越想越不對勁了,對…沒錯我一開始也有同樣的疑問,為甚麼你一個日期存放欄位要開VARCHAR是想害死誰R。
2021/06/06 回來補做法
感謝前輩看到提供了另一個做法當然就是搬回程式內做判斷,可以使用 DateTime.TryParseExact 這個方法來轉換日期格式。
首先來了解一下這個方法要怎麼用。
TryParseExact(String, String, IFormatProvider, DateTimeStyles, DateTime)
//第一個 String 是放我們要轉換的字串
//第二個 String 是我們要轉換的字串日期格式是甚麼例如第一個 String 是2021/06/06那第二個 String 就是yyyy/MM/dd
//IFormatProvider 可以決定當地文化格式例如台灣的話就是使用zh-TW
//DateTimeStyles 則是可以決定我們允許哪些符合的字串格式能夠轉換
//DateTime 這就是我們要輸出的日期格式
簡單範例
static void Main(string[] args)
{
var culture = new CultureInfo("zh-TW");
var dateStr = "2021/06/06";
if (DateTime.TryParseExact(dateStr, "yyyy/MM/dd",culture,DateTimeStyles.None, out var date))
{
Console.WriteLine(date);
}
Console.ReadLine();
}
輸出
而第二個允許的 string 可以是一個 array,所以我們就能夠這麼做。
static void Main(string[] args)
{
Console.WriteLine("請輸入一個日期字串");
var dateStr = Console.ReadLine();
var formate = new[] { "yyyy/MM/dd", "yyyy-MM-dd" };
var culture = new CultureInfo("zh-TW");
if (DateTime.TryParseExact(dateStr, formate,culture,DateTimeStyles.None, out var date))
{
Console.WriteLine($"轉換後的日期格式:{date}");
}
Console.ReadLine();
}
這樣無論是 yyyy/MM/dd 或是 yyyy-MM-dd 就都能夠成功轉換為日期格式,日後如果還要有多日期判斷也可以直接擴充 formate 內容即可。
DateTime Style 的部分就是可以允許一些特殊格式字串出現,例如我們的字串中出現了空格就可以使用 DateTimeStyles.AllowInnerWhite
static void Main(string[] args)
{
Console.WriteLine("請輸入一個日期字串");
var dateStr = Console.ReadLine();
var formate = new[] { "yyyy/MM/dd", "yyyy-MM-dd" };
var culture = new CultureInfo("zh-TW");
if (DateTime.TryParseExact(dateStr, formate, culture,DateTimeStyles.AllowInnerWhite, out var date))
{
Console.WriteLine($"轉換後的日期格式:{date}");
}
Console.ReadLine();
}
至於如果是 UTC 這種日期格式的轉換可以使用 “O” 這個 formate 直接轉換為當地時間。
static void Main(string[] args)
{
var culture = new CultureInfo("zh-TW");
var dateStr = "2021-06-06T16:11:20.0904778Z";
if (DateTime.TryParseExact(dateStr, "o", culture,DateTimeStyles.None, out var date))
{
Console.WriteLine($"轉換後的日期格式:{date}");
}
Console.ReadLine();
}
還有更多用法就留待大家自己研究使用啦~~~