資料交換經常會碰到各種日期時間字串,今天來敲門的是"2016年10月5日 下午 10:06:23",他也是Windows中文繁體(台灣)內建的日期時間表示方式。來筆記快速又正確Parse時間字串方法。
由於輸入時間字串有"上午"/"下午",是那種行針鐘錶的12小時制的標記,因為不是航空公司、軍隊、金融業標準常用的ISO8601 24小時制格式,不能單純用DateTime.TryParse,這時候可以用TryParseExact指定格式來處理,關鍵字就是tt。
什麼是tt
觀察Windows OS,電腦畫面右下角的日期時間格式
當我們月曆類型是西曆(中文)時:
日期格式:
時間格式
tt是用來表示上午或下午的符號!
小寫h表示12小時制!大寫H表示24小時制!
好!知道怎麼描述時間格式了,來寫程式!
Parse日期時間字串中的"上午"與"下午"
1.撰寫兩段方法分別使用InvariantCulture及CultureInfo("zh-TW")兩種文化特性Parse日期時間字串。
輸入參數是日期時間字串,用Tuple回傳是否轉換成功(Boolean)及轉換後日期(Datetime)
InvariantCulture
public Tuple<bool, DateTime> InvariantConvert(string sDt)
{
DateTime dt = new DateTime(1900, 1, 1);
string[] sDtPattern = new string[]{
"yyyy年M月d日 上午 hh:mm:ss","yyyy年M月d日 下午 hh:mm:ss",
"yyyy年M月d日 tt hh:mm:ss"
};
return Tuple.Create(DateTime.TryParseExact(sDt, sDtPattern, CultureInfo.InvariantCulture,
DateTimeStyles.AllowWhiteSpaces, out dt), dt);
}
CultureInfo("zh-TW"): 使用台灣文化特性,讓TryParseExact看的懂"年","月","日","上午","下午"這些時間元件
public Tuple<bool, DateTime> TwCultureConvert(string sDt)
{
DateTime dt = new DateTime(1900, 1, 1);
CultureInfo culTW = new CultureInfo("zh-TW", true);
string[] sTwDtPattern = new string[] {
"yyyy年M月d日 tt hh:mm:ss" };
return Tuple.Create(DateTime.TryParseExact(sDt, sTwDtPattern, culTW, DateTimeStyles.AllowWhiteSpaces, out dt), dt);
}
2.撰寫測試程式
依序用2016/10/5 上午 10:06:23及下午 10:06:23測試。
[TestMethod]
public void TestMethod1()
{
//Input Datetime string
string sTWDateTimeAM = "2016年10月5日 上午 10:06:23";
string sTWDateTimePM = "2016年10月5日 下午 10:06:23";
//Expected Result
DateTime TWDateTimeAM = new DateTime(2016, 10, 05, 10, 06, 23);
DateTime TWDateTimePM = new DateTime(2016, 10, 05, 22, 06, 23);
Console.WriteLine("InvariantConvert");
var Result1 = InvariantConvert(sTWDateTimeAM);
Console.WriteLine($"{Result1.Item1}/{Result1.Item2}");
//Assert.AreEqual(TWDateTimeAM, Result1.Item2);
var Result2 = InvariantConvert(sTWDateTimePM);
Console.WriteLine($"{Result2.Item1}/{Result2.Item2}");
//Assert.AreEqual(TWDateTimePM, Result2.Item2);
Console.WriteLine("zh-TW Culture");
var Result3 = TwCultureConvert(sTWDateTimeAM);
Console.WriteLine($"{Result3.Item1}/{Result3.Item2}");
//Assert.AreEqual(TWDateTimeAM, Result3.Item2);
var Result4 = TwCultureConvert(sTWDateTimePM);
Console.WriteLine($"{Result4.Item1}/{Result4.Item2}");
//Assert.AreEqual(TWDateTimePM, Result4.Item2);
}
測試結果:
InvariantCulture: 雖然parse設定hh表示12小時,但因為InvariantCulture直接將"上下午"視為無意義的格式字串,當時間落在下午時,Parse後會失去原來時間的精準度。
CultureInfo("zh-TW"): 台灣繁體中文的文化特性則可以精準的把"上午""下午"的時間都Parse出來。
但如果把日期時間字串中的"上午/下午"改為"AM/PM" ?
再寫一段測試程式
[TestMethod]
public void TestMethod1()
{
//Expected Result
DateTime TWDateTimeAM = new DateTime(2016, 10, 05, 10, 06, 23);
DateTime TWDateTimePM = new DateTime(2016, 10, 05, 22, 06, 23);
Console.WriteLine("");
string sDateTimeAM = "2016年10月5日 AM 10:06:23";
string sDateTimePM = "2016年10月5日 PM 10:06:23";
Console.WriteLine("InvariantConvert");
var Result5 = InvariantConvert(sDateTimeAM);
Console.WriteLine($"{Result5.Item1}/{Result5.Item2}");
//Assert.AreEqual(TWDateTimeAM, Result5.Item2);
var Result6 = InvariantConvert(sDateTimePM);
Console.WriteLine($"{Result6.Item1}/{Result6.Item2}");
//Assert.AreEqual(TWDateTimePM, Result6.Item2);
Console.WriteLine("zh-TW Culture");
var Result7 = TwCultureConvert(sDateTimeAM);
Console.WriteLine($"{Result7.Item1}/{Result7.Item2}");
//Assert.AreEqual(TWDateTimeAM, Result7.Item2);
var Result8 = TwCultureConvert(sDateTimePM);
Console.WriteLine($"{Result8.Item1}/{Result8.Item2}");
//Assert.AreEqual(TWDateTimePM, Result8.Item2);
}
測試結果
1.InvariantCulture可以正確Parse出"AM/PM"。
2.CultureInfo("zh-TW"): 沒辦法Parse,不管AM/PM,日期時間轉換都失敗。
小結
- 看到"上午"/"下午" 用CultureInfo("zh-TW")的tt解題。
- 看到"AM"/"PM" 用InvariantCulture的tt解題。
參考:
CNS7648(中華民國國家標準,資料元件及交換格式-資訊交換-日期及時間表示法)
tt