2010-02-03 13 views
5

Lavoro per me stesso, sono un programmatore autonomo e di conseguenza non ho il lusso delle recensioni del codice o la possibilità di migliorare in base alla programmazione peer. Ho intenzione di utilizzare questo come un esercizio per vedere se la comunità StackOverflow potrebbe aiutare a rivedere un semplice metodo che ho scritto;Refactor per la velocità: Converti in una data

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

Questo è un metodo che accetta una rappresentazione numerica di una data e lo converte in un tipo di dati DateTime. Vorrei che il metodo da recensione per acheive il più veloce tempo di esecuzione possibile perché è in esecuzione all'interno di un ciclo.

Qualsiasi commento sul metodo è apprezzato in quanto questo sarà un esercizio per me. attendo alcune risposte.

+0

Si dovrebbe sempre contrassegnare domande come questa, con un linguaggio di programmazione, per aiutare le persone lo trovano. – unwind

+0

le operazioni binarie diventano più veloci utilizzando un metodo bit mask e bit shift – tooleb

+0

FYI, omettendo lo 0 iniziale nei numeri binari potrebbe confondere gli altri sviluppatori. È giusto aspettarsi che tutti i 32 bit siano rappresentati. –

risposta

4

Stai facendo manipolazioni di stringhe. Questo è un vero killer delle prestazioni quando viene utilizzato in loop stretti.

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

Ecco come si fa. In primo luogo, prendere 1822490623 e convertirlo in binario:

0110 1100 1010 0000 1111 1111 1111 1111 

Questa è una maschera per l'anno:

f f 0 0 0 0 0 0 

questo è per il mese:

0 0 f 0 0 0 0 0 

e questo è per il giorno:

0 0 0 f 8 0 0 0 

Valore "Anno" deve essere fatto scorrere a destra 6 * 4 bit, "mese" - per 5 * 4, e "giorno" - per 3 * 4 + 3 bit.

+0

quindi come scriveresti questo metodo per ottenere prestazioni migliori? – Phillis

+0

ma se cambiamo leggermente perché non ci spostiamo a sinistra << ??? – Phillis

+0

thx .. ho lavorato fuori – Phillis

10

Invece di conversione in una stringa, in interi, poi a stringa, ad oggi, basta avere gli interi spostando e mascheratura, e creare il valore DateTime direttamente dai valori interi:

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 per il migliore e più completo del mio. :) (Anche se ammetto che preferisco l'esadecimale rispetto ai decimali per le maschere di bit.) –

+0

Bellissimo esempio di cambio di bit e mascheramento stretto in C#, ben fatto. Sono con Greg per l'utilizzo di hex - è più chiaro e compila lo stesso. Risolto il problema matematico dell'anno. – richardtallent

+0

tuttavia non risolve per "anno", ovvero l'anno non è corretto – Phillis

4

Benvenuto nella comunità, Phillis. :)

Anton è corretto, le tue manipolazioni di stringa saranno lente. Poiché sembra che tu stia utilizzando il parametro come bitfield, ti suggerisco di esaminare i vari operatori di bit (molto più veloci): < <, >>, &, |, e ~. Sembra che si sta cercando di fare la manipolazione binaria, in modo da utilizzare gli operatori costruite per esso.

E.g. (non testato, appena inserito):

Si inizia con un valore di 0x6c9f7fff. Il byte di ordine alto costituisce l'anno. Per mascherare fuori tutto ciò che non è l'anno, fare qualcosa di simile:

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

Allo stesso modo, i prossimi 4 bit sono del mese, in modo da:

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

io vi suggerisco di trovare il C/Codice C++ che fa un lavoro simile; poi porta in C#