本文

事情發生是這樣的,今天突然接到一個線上問題,數據報表顯示有問題有幾個不該出現的數據卻出現了。

問題發生當下馬上查了一下撈取數據顯示的語法,想知道判斷日期的地方是否有遺漏,然後就看到了一段類似於下列的語法

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();
}

還有更多用法就留待大家自己研究使用啦~~~

參考連結