2010-02-03 40 views
5

Tôi làm việc cho bản thân mình, tôi là một lập trình viên tự làm chủ và kết quả là tôi không có sự đánh giá mã sang trọng hoặc khả năng cải thiện dựa trên lập trình ngang hàng. Tôi sẽ sử dụng điều này như một bài tập để xem liệu cộng đồng StackOverflow có thể giúp xem xét một phương pháp đơn giản mà tôi đã viết hay không;Refactor for Speed: Chuyển đổi thành ngày

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

Đây là phương pháp biểu diễn số ngày và chuyển đổi thành Loại dữ liệu ngày giờ. Tôi muốn phương pháp được xem xét để đạt được thời gian thực thi nhanh nhất có thể bởi vì nó được thực thi trong vòng lặp.

Bất kỳ nhận xét nào về phương pháp đều được đánh giá cao vì đây sẽ là bài tập cho tôi. tôi mong đợi một số câu trả lời.

+0

Bạn nên luôn gắn thẻ các câu hỏi như thế này bằng ngôn ngữ lập trình để giúp mọi người tìm thấy nó. – unwind

+0

hoạt động nhị phân sẽ nhanh hơn bằng cách sử dụng mặt nạ bit và phương pháp thay đổi bit – tooleb

+0

FYI, bỏ qua số 0 hàng đầu trong số nhị phân của bạn có thể gây nhầm lẫn cho các nhà phát triển khác. Đó là công bằng để mong đợi tất cả 32 bit được đại diện. –

Trả lời

4

Bạn đang thực hiện thao tác chuỗi. Đây là sát thủ thực sự thực sự khi được sử dụng trong các vòng chặt chẽ.

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

Đây là cách bạn làm điều đó. Trước tiên, hãy 1822490623 và chuyển nó sang nhị phân:

0110 1100 1010 0000 1111 1111 1111 1111 

Đây là một mặt nạ cho năm:

f f 0 0 0 0 0 0 

này là dành cho tháng:

0 0 f 0 0 0 0 0 

Và đây là dành cho trong ngày:

0 0 0 f 8 0 0 0 

Giá trị "Năm" phải được dịch chuyển ngay bằng 6 * 4 bit, "tháng" - theo số 5 * 4 và "ngày" - theo số 3 * 4 + 3 bit.

+0

Vậy bạn sẽ viết phương pháp này để có hiệu suất tốt hơn như thế nào? – Phillis

+0

nhưng nếu chúng ta chuyển dịch bit thì tại sao chúng ta không chuyển sang bên trái << ??? – Phillis

+0

thx .. tôi đã làm việc nó ra – Phillis

10

Thay vì chuyển đổi thành một chuỗi, sau đó đến số nguyên, sau đó đến chuỗi, sau đó cho đến nay, chỉ nhận được số nguyên bằng cách thay đổi và tạo mặt nạ, và tạo ra giá trị DateTime trực tiếp từ các giá trị số nguyên:

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 cho tốt hơn và đầy đủ hơn tôi. :) (Mặc dù tôi thừa nhận tôi thích hex hơn thập phân cho bitmasks.) –

+0

Ví dụ đẹp về chặt chẽ bit-shifting và masking trong C#, cũng được thực hiện. Tôi với Greg sử dụng hex - nó rõ ràng hơn và biên dịch giống nhau. Đã sửa lỗi toán năm. – richardtallent

+0

tuy nhiên nó không giải quyết cho "năm", tức là năm không chính xác – Phillis

4

Chào mừng đến với cộng đồng, Phillis. :)

Anton đúng, thao tác chuỗi của bạn sẽ chậm. Bởi vì có vẻ như bạn đang sử dụng tham số dưới dạng bitfield, tôi khuyên bạn nên xem xét các toán tử bit khác nhau (nhanh hơn): < <, >>, &, | và ~. Có vẻ như bạn đang cố gắng thực hiện thao tác nhị phân, do đó hãy sử dụng toán tử được tạo cho nó.

Ví dụ: (chưa được kiểm tra, chỉ cần tắt dải):

Bạn bắt đầu với giá trị là 0x6c9f7fff. Thứ tự byte cao tạo nên năm. Để mặt nạ ra tất cả những gì không phải là năm nay, làm một cái gì đó như:

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

Tương tự, 4 bit tiếp theo là tháng, vì vậy:

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

tôi sẽ đề nghị bạn để tìm các C/Mã C++ thực hiện công việc tương tự; sau đó chuyển nó vào C#

Các vấn đề liên quan