是以我們了解到,我們需要更加精确的判斷時間的界限。是以我們重新将代碼改為如下:
static void Main(string[] args)
{
DateTime indate = new DateTime(2008, 9, 30); //入住時間
DateTime outdate = new DateTime(2008, 10, 5, 12, 15, 12); //退房時間
double days = (outdate - indate).Days; //計算入住了幾天
if (outdate.Hour <= 11) //這個時間段是 0:0:0到11:59:59
{
days += 0; //當天不計算房費
}
else
{ //如果小時部分的值是12,且其的分秒部分的值都是0,就是12點整
if (outdate.Hour == 12 && outdate.Minute == 0 && outdate.Second == 0)
{
days += 0; //當天也不計算房費
}
else//12:0:0以後
if (outdate.Hour <= 17) //時間段為 12:0:1到17:59:59
{
days += 0.5; //加收半天房費
}
else //18點之後
{ //如果小時部分的值是18,且其的分秒部分的值都是0,就是18點整
if (outdate.Hour == 18 && outdate.Minute == 0 && outdate.Second == 0)
{
days += 0.5; //加收半天房費
}
else
{//18點之後
days++; //加收一天房費
System.Console.WriteLine("你的入住結算資訊/n入住時間{0}/n退房時間{1}/n一共入住了{2}天", indate, outdate, days);
}
上述的代碼,使用了4個條件的嵌套判斷,将退房的時間作了精确的判斷(考慮到了分秒的臨界點),同時初學的人員再次要了解到注釋的重要性,以上的邏輯,如果不描寫注釋,估計過一個月後,你自己都不知道自己在幹什麼了。
現在我們運作程式,設定以下的時間段
DateTime indate = new DateTime(2008, 9, 30); //入住時間
DateTime outdate = new DateTime(2008, 10, 5, 12, 15, 12); //退房時間
我們程式的運作結果得到了我們樂于見到的5.5天
結構化程式設計,還有一個重要的概念就是子產品化,我們上面的代碼中對整點的判斷。比如12點整
outdate.Hour == 12 && outdate.Minute == 0 && outdate.Second == 0
和18點整
outdate.Hour == 18 && outdate.Minute == 0 && outdate.Second == 0
完全可以函數化,是以我們需要添加一個函數子產品。
/// <summary>
/// 判斷給定的時間是否是一個整時
/// </summary>
/// <param name="date">需要判斷的時間</param>
/// <returns>如果是整時,則傳回true,否則傳回false</returns>
static bool IsZeroTime(DateTime date)
if (date.Minute == 0 && date.Second == 0)//如果給定的時間的分秒值都是0
return true;
return false;
我們新編寫的IsZeroTime将判斷整時的問題進行了函數(子產品)化,不過初學的人要注意一點,如果一個if else 中僅處理一個問題的時候,我們完全可以優化成如下代碼
return date.Minute == 0 && date.Second == 0;
現在我們再來修改原先的邏輯主體的代碼為:
DateTime indate = new DateTime(2008, 9, 30); //入住時間
DateTime outdate = new DateTime(2008, 10, 5, 12, 15, 12); //退房時間
double days = (outdate - indate).Days; //計算入住了幾天
if (outdate.Hour <= 11) //這個時間段是 0:0:0到11:59:59
days += 0; //當天不計算房費
if (outdate.Hour == 12 && IsZeroTime(outdate)) //如果是12點整
days += 0; //當天也不計算房費
if (outdate.Hour <= 17) //時間段為 12:0:1到17:59:59
days += 0.5; //加收半天房費
else
{ //18點之後
if (outdate.Hour == 18 && IsZeroTime(outdate)) //如果是18點整
{ //18點之後
以上代碼使用了IsZeroTime函數,讓代碼的表現能力更強更優雅。那現在是不是萬事大吉呢了?我們現在看看以下的時間:
DateTime indate = new DateTime(2008, 10, 5, 2, 12, 0);//入住時間
DateTime outdate = new DateTime(2008, 10, 5, 12, 0, 0);//退房時間
我們的程式告訴我們,顧客住了0天!!!
而以下的日期
DateTime indate = new DateTime(2008, 10, 5, 19, 12, 0); //入住時間
DateTime outdate = new DateTime(2008, 10, 5, 19, 13, 0); //退房時間
我們的程式告訴我們,顧客住了1天!!!
啊,那是多麼不公平的事情啊,一個住了近10個小時的人計算機竟然說他可以免費,而另一個住了才1分鐘的顧客,竟然要支付整整一天的房價!
問題出在哪裡呢?如果你仔細想想,就可以猜到,我們一開始的計算也許就錯了。
double days = (outdate - indate).Days; //計算入住了幾天
原來這個Days不是計算過了幾個晚上,而是兩個時間的間隔,該間隔用納秒來計算出。是以我們要使用內插補點來計算使用者是不是過夜的話,不能簡單的進行相減。不過如果我們使用些技巧就可以來解決,比如我們把兩個時間都切換到午夜時間(就是午夜兇鈴那個電話鈴響的時間,0:0:0),那麼就可以計算機出使用者是否過夜了。
double days = (outdate.Date - indate.Date).Days; //計算入住了幾天
這樣的話,隻要顧客不是同天退房,就會得到大于0的值,如果值是0就表示使用者是同天退房的。如果使用者是隔夜退房的,我們的邏輯計算照舊,否則要看看使用者住的時間是否超過半天。這樣才合理嘛。
是以,我們需要把代碼作些小的調正,先判斷下顧客是否同天退房,如果是同天退房的話,計算他入住了幾個小時:超過12小時算一天,否則算半天;如果顧客是隔天退房,那還繼續保持我們原有的邏輯處理。
DateTime indate = new DateTime(2008, 10, 5, 19, 12, 0); //入住時間
DateTime outdate = new DateTime(2008, 10, 5, 19, 13, 0); //退房時間
double days = (outdate.Date - indate.Date).Days; //計算入住了幾天
if (days == 0)
{ //同天退房
if ((outdate - indate).TotalHours <= 12) //入住時間不超過12小時
days += 0.5; //以半天房費計算
else //超過12小時
days++; //計算一天的房費
{ //隔夜退房
if (outdate.Hour <= 11) //這個時間段是 0:0:0到11:59:59
days += 0; //當天不計算房費
else
if (outdate.Hour == 12 && IsZeroTime(outdate)) //如果是12點整
days += 0; //當天也不計算房費
else //12:0:0以後
if (outdate.Hour <= 17) //時間段為 12:0:1到17:59:59
{ //18點之後
if (outdate.Hour == 18 && IsZeroTime(outdate)) //如果是18點整
{
days += 0.5; //加收半天房費
}
else
{ //18點之後
days++;//加收一天房費
現在我們可以處理同天退房和隔夜退房的不同邏輯了,我們可以看到,通過精确的控制,我們的代碼可處理的能力越來越強大,不過代碼也越來越複雜了,嵌套也越來越龐大。是以,我們開始反思,為了追求正确的邏輯,我們是不是走了太遠了?
本文轉自shyleoking 51CTO部落格,原文連結:http://blog.51cto.com/shyleoking/805178