2010-02-03 55 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#