2010-02-03 7 views
5

Ich arbeite für mich selbst, bin ein selbständiger Programmierer und als Ergebnis habe ich nicht den Luxus von Code-Reviews oder die Fähigkeit, basierend auf Peer-Programmierung zu verbessern. Ich werde dies als Übung verwenden, um zu sehen, ob die StackOverflow-Community helfen könnte, eine einfache Methode, die ich geschrieben habe, zu überprüfen;Refactor für Geschwindigkeit: Konvertieren zu einem Datum

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

Dies ist eine Methode, die eine numerische Darstellung eines Datums erfolgt und wandelt es in einem DateTime- Datentyp. Ich möchte, dass die Methode überprüft wird, um die schnellstmögliche Ausführungszeit zu erreichen, da sie innerhalb einer Schleife ausgeführt wird.

Alle Kommentare zu der Methode wird geschätzt, da dies eine Übung für mich sein wird. Ich freue mich auf einige Antworten.

+0

Sie sollten immer Fragen wie folgt mit einer Programmiersprache markieren, um Menschen zu helfen, es zu finden. – unwind

+0

binäre Operationen gehen schneller mit einer Bitmaske und Bit-Shift-Ansatz – tooleb

+0

FYI, die führende 0 in Ihren Binärzahlen weglassen kann für andere Entwickler verwirrend sein. Es ist fair zu erwarten, dass alle 32 Bits dargestellt werden. –

Antwort

4

Sie tun String-Manipulationen. Dies ist ein echter Performance-Killer, wenn er in engen Schleifen verwendet wird.

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

Hier ist, wie Sie das tun. Zuerst nehmen 1822490623 und wandeln es in binär:

0110 1100 1010 0000 1111 1111 1111 1111 

Dies ist eine Maske für das Jahr:

f f 0 0 0 0 0 0 

Dies ist für Monat:

0 0 f 0 0 0 0 0 

Und das ist für den Tag:

0 0 0 f 8 0 0 0 

"Jahr" Wert muss um 6 * 4 Bits verschoben werden, "Monat" - von 5 * 4, und "Tag" - von 3 * 4 + 3 Bits.

+0

Wie würden Sie diese Methode für bessere Leistung schreiben? – Phillis

+0

aber wenn wir etwas verschieben, warum verschieben wir uns nicht nach links << ??? – Phillis

+0

thx .. ich arbeitete es aus – Phillis

10

Statt in eine Zeichenfolge zu konvertieren, dann auf ganze Zahlen, dann auf Zeichenfolge, dann bis heute erhalten nur die ganzen Zahlen durch Verschieben und Maskierung, und erstellen Sie den Datetime-Wert direkt aus den ganzzahligen Werten:

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 für besser und vollständiger als meins. :) (Ich gebe zu, ich bevorzuge Hexadezimal gegenüber Dezimal für Bitmasken.) –

+0

Schönes Beispiel für enge Bit-Verschiebung und Maskierung in C#, gut gemacht. Ich bin mit Greg bei der Verwendung von hex - es ist klarer und kompiliert das gleiche. Das Jahr Mathe korrigiert. – richardtallent

+0

aber es löst nicht für "Jahr", d. H. Das Jahr ist falsch – Phillis

4

Willkommen in der Gemeinde, Phillis. :)

Anton ist richtig, Ihre String-Manipulationen werden langsam sein. Da es so aussieht, als würden Sie den Parameter als Bitfeld verwenden, würde ich vorschlagen, die verschiedenen (viel schnelleren) Bitoperatoren zu betrachten: < <, >>, &, |, und ~. Es sieht so aus, als würden Sie versuchen, eine binäre Manipulation durchzuführen, also benutzen Sie die dafür gebauten Operatoren.

z. (ungeprüft, nur aus dem Stand):

Sie beginnen mit einem Wert von 0x6c9f7fff. Das höherwertige Byte bildet das Jahr. Auszublenden alles, was nicht das Jahr, so etwas wie:

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

Ebenso sind die nächsten 4 Bits sind der Monat, so:

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

Ich werde Sie schlagen die C finden/C++ Code, der ähnliche Arbeit leistet; dann portiere es in C#

Verwandte Themen