2010-02-03 44 views
5

我爲自己工作,我是一名自僱職業編碼人員,因此我沒有代碼審查的豪華感或根據同行編程進行改進的能力。我將以此作爲練習,以查看StackOverflow社區是否可以幫助檢查我寫的一個簡單方法;重構速度:轉換爲日期

internal static DateTime CONVERT_To_DateTime(int binDate) 
    { 
     // 3/10/2008 = 1822556159 
     // 2/10/2008 = 1822523391 
     // 1/10/2008 = 1822490623 
     // 30/09/2008 = 1822392319 
     // 29/09/2008 = 1822359551 

     // September 30th 2008 
     // 1822392319 = 0x6c9f7fff 
     // 0x6c = 108 = 2008 (based on 1900 start date) 
     // 0x9 = 9 = September 
     // 0xf7fff - take top 5 bits = 0x1e = 30 

     // October 1st 2008 
     // 1822490623 = 0x6ca0ffff 
     // 0 x6c = 108 = 2008 
     // 0 xa = 10 = October 
     // 0x0ffff - take top 5 bits = 0x01 = 1 

     // OR using Binary (used by this function) 
     // a = 1822556159 (3/10/2008) 
     // 1101100 1010 00011 111111111111111 

     // b = 1822523391 (2/10/2008) 
     // 1101100 1010 00010 111111111111111 

     // c = 1822490623 (1/10/2008) 
     // 1101100 1010 00001 111111111111111 

     // D = 1822392319 (30/09/2008) 
     // 1101100 1001 11110 111111111111111 

     // Excess 111111 are probably used for time/seconds which 
     // we do not care for at the current time 

     var BaseYear = 1900; 

     // Dump the long date to binary 
     var strBinary = Convert.ToString(binDate); 

     // Calculate the year 
     var strBYear = strBinary.Substring(0, 7); 
     var iYear = Convert.ToInt32(strBYear, 2) + BaseYear; 

     // Calculate the month 
     var strBMonth = strBinary.Substring(7, 4); 
     var iMonth = Convert.ToInt32(strBMonth, 2); 

     // Calculate the day 
     var strBDay = strBinary.Substring(11, 5); 
     var iDay = Convert.ToInt32(strBDay, 2); 

     // ensure that month and day have two digits 
     var strDay = iDay < 10 ? "0" + iDay : iDay.ToString(); 
     var strMonth = iMonth < 10 ? "0" + iMonth : iMonth.ToString(); 

     // Build the final date 
     var convertedDate = iYear + strMonth + strDay; 

     return DateTime.ParseExact(convertedDate, "yyyyMMdd", null); 
    } 

這是一種採用數字表示日期並將其轉換爲DateTime數據類型的方法。我希望對方法進行審查,以實現儘可能快的執行時間,因爲它是在循環內執行的。

對這個方法的任何評論都很讚賞,因爲這對我來說是一個練習。我期待着一些迴應。

+0

您應該總是用編程語言來標記這樣的問題,以幫助人們找到它。 – unwind 2010-02-03 14:54:00

+0

使用位掩碼和位移方法可以更快地執行二進制操作 – tooleb 2010-02-03 15:02:27

+0

僅供參考,省略二進制數字中的前導0可能會讓其他開發人員感到困惑。期望全部32位被表示是公平的。 – 2010-02-03 15:30:36

回答

4

你正在做字符串操作。當在緊密環路中使用時,這是真正的性能殺手。

static DateTime ToDateTime(int value) 
    { 
     var year = (int)((value & 0xff000000) >> 24); 
     var month = (value & 0xf00000) >> 20; 
     var day = (value & (0xf8000)) >> 15; 

     return new DateTime(1900 + year, month, day); 
    } 

下面是你如何做到這一點。首先,採取1822490623並將其轉換爲二進制:

0110 1100 1010 0000 1111 1111 1111 1111 

這是今年面具:

f f 0 0 0 0 0 0 

這是本月:

0 0 f 0 0 0 0 0 

這是白天:

0 0 0 f 8 0 0 0 

「年」值必須右移6 * 4比特,「月」 - 通過5 * 4和「日」 - 通過3 * 4 + 3比特。

+0

那麼你會如何編寫這種方法來獲得更好的性能? – Phillis 2010-02-03 14:58:23

+0

但是如果我們有點偏移,爲什麼我們不能左移<< ??? – Phillis 2010-02-03 15:36:49

+0

thx ..我工作了 – Phillis 2010-02-03 15:59:53

10

相反轉換成字符串,然後爲整數,那麼對字符串,則迄今爲止,僅通過移位和掩蔽得到整數,並且直接從整數值創建DateTime值:

binDate >>= 15; 
int day = binDate & 31; 
binDate >>= 5; 
int month = binDate & 15; 
binDate >>= 8; 
int year = binDate + 1900; 
return new DateTime(year, month, day); 
+0

+1比我的更好,更完整。 :)(雖然我承認我比十進制十六進制位掩碼更喜歡。) – 2010-02-03 15:05:01

+0

C#中緊密位移和掩蓋的美麗示例,做得很好。我與格雷格一起使用十六進制 - 它更清晰並編譯相同。修正了數學年。 – richardtallent 2010-02-03 15:08:42

+0

然而,它並沒有解決「年份」,即年份不正確 – Phillis 2010-02-03 15:09:11

4

歡迎來到社區,Phillis。 :)

安東是正確的,你的字符串操作將會很慢。因爲它看起來像你使用參數作爲位域,我建議尋找各種(快得多)位操作符:< <,>>,&,|和〜。看起來你正在嘗試執行二進制操作,所以使用爲其構建的操作符。

E.g. (未經測試,僅在袖口處):

您的值爲0x6c9f7fff。高位字節構成了一年。掩蓋了一切,是不是一年,這樣做:

int year = ((binDate & 0xFF000000) >> 24) + BaseYear; 

同樣,在接下來的4位是一個月,所以:

int month = (binDate & 0x00F00000) >> 20; 
int date = (binDate & 0x000F8000) >> 15; 
return new DateTime(year, month, date); 
-2

我會建議你找到C/C++代碼,它做類似的工作;然後將其轉換爲C#