2010-02-03 3 views
5

Je travaille pour moi-même, je suis un codeur indépendant et par conséquent, je n'ai pas le luxe de critiques de code ou la possibilité d'améliorer en fonction de la programmation par les pairs. Je vais utiliser cela comme un exercice pour voir si la communauté StackOverflow pourrait aider à revoir une méthode simple que j'ai écrite;Refactor pour la vitesse: Convertir en une date

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

C'est une méthode qui prend une représentation numérique d'une date et il se transforme en un type de données DateTime. Je voudrais que la méthode soit revue pour atteindre le temps d'exécution le plus rapide possible car elle est exécutée dans une boucle.

Tous les commentaires sur la méthode est apprécié car ce sera un exercice pour moi. J'attends avec impatience quelques réponses.

+0

Vous devriez toujours étiqueter des questions comme celles-ci avec un langage de programmation, pour aider les gens à les trouver. – unwind

+0

opérations binaires vont plus vite en utilisant un masque de bits et approche de décalage de bits – tooleb

+0

FYI, en omettant le 0 principal dans vos nombres binaires peut être source de confusion pour d'autres développeurs. Il est juste de s'attendre à ce que tous les 32 bits soient représentés. –

Répondre

4

Vous effectuez des manipulations de chaînes. C'est vrai tueur de performance lorsqu'il est utilisé dans des boucles serrées.

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

Voici comment procéder. Tout d'abord, prendre 1822490623 et le convertir en binaire:

0110 1100 1010 0000 1111 1111 1111 1111 

Ceci est un masque pour l'année:

f f 0 0 0 0 0 0 

C'est pour le mois:

0 0 f 0 0 0 0 0 

Et ceci est pour jour:

0 0 0 f 8 0 0 0 

Valeur "Année" doit être décalé à droite par 6 * 4 bits, "mois" - par 5 * 4, et "jour" - par 3 * 4 + 3 bits.

+0

alors comment écrire cette méthode pour de meilleures performances? – Phillis

+0

mais si nous sommes en train de changer de direction, pourquoi ne passons-nous pas à gauche << ??? – Phillis

+0

thx .. je l'ai élaboré – Phillis

10

Au lieu de convertir en une chaîne, puis à des entiers, puis à chaîne, à ce jour, juste obtenir les entiers en déplaçant et le masquage, et de créer la valeur DateTime directement à partir des valeurs entières:

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 pour le meilleur et plus complet que le mien. :) (Bien que j'admette que je préfère hex au décimal pour les masques de bit.) –

+0

Bel exemple de décalage de bit et de masquage en C#, bravo. Je suis avec Greg en utilisant hex - c'est plus clair et compile la même chose. Correction de l'année mathématique. – richardtallent

+0

Cependant, il ne résout pas pour "année", c'est-à-dire l'année est incorrecte – Phillis

4

Bienvenue dans la communauté, Phillis. :)

Anton a raison, vos manipulations de chaînes vont être lentes. Comme il semble que vous utilisiez le paramètre comme un champ de bits, je suggérerais d'examiner les différents opérateurs (beaucoup plus rapides): < <, >>, &, |, et ~. Il semble que vous essayez de faire une manipulation binaire, utilisez donc les opérateurs construits pour cela.

E.g. (non testé, juste à côté du brassard):

Vous commencez avec une valeur de 0x6c9f7fff. L'octet de poids fort constitue l'année. Pour masquer tout ce qui est pas l'année, faire quelque chose comme:

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

De même, les 4 bits suivants du mois, donc:

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

Je vous suggère de trouver le C/Code C++ qui fait un travail similaire; puis portez-le en C#