2010-02-03 5 views
5

Trabajo para mí, soy un codificador autónomo y, como resultado, no tengo el lujo de revisiones de código o la capacidad de mejorar en función de la programación entre iguales. Voy a usar esto como un ejercicio para ver si la comunidad de StackOverflow podría ayudar a revisar un método simple que he escrito;Refactor para la velocidad: Convertir a una fecha

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

Este es un método que se lleva a una representación numérica de una fecha y la convierte en un tipo de datos DateTime. Me gustaría que el método sea revisado para lograr el tiempo de ejecución más rápido posible porque se está ejecutando dentro de un ciclo.

Se agradece cualquier comentario sobre el método, ya que este será un ejercicio para mí. Espero algunas respuestas.

+0

Siempre debe etiquetar preguntas como esta con un lenguaje de programación, para ayudar a las personas a encontrarlo. – unwind

+0

las operaciones binarias son más rápidas usando una máscara de bits y enfoque de cambio de bit – tooleb

+0

FYI, omitir el 0 inicial en los números binarios puede ser confuso para otros desarrolladores. Es justo esperar que se representen los 32 bits. –

Respuesta

4

Estás haciendo manipulaciones de cadena. Este es un verdadero asesino de rendimiento cuando se usa en bucles apretados.

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

Así es como se hace eso. En primer lugar, tomar 1822490623 y convertirlo a binario:

0110 1100 1010 0000 1111 1111 1111 1111 

Ésta es una máscara del año:

f f 0 0 0 0 0 0 

Esto es para el mes:

0 0 f 0 0 0 0 0 

Y esto es para el día:

0 0 0 f 8 0 0 0 

"Año" valor tiene que ser desplazado a la derecha por 6 * 4 bits, "mes" - por 5 * 4, y "día" - por 3 * 4 + 3 bits.

+0

entonces, ¿cómo escribirías este método para un mejor rendimiento? – Phillis

+0

, pero si estamos cambiando un poco, ¿por qué no estamos cambiando a la izquierda << ??? – Phillis

+0

thx .. lo resolví – Phillis

10

En lugar de convertir a una cadena, entonces a números enteros, a continuación, a la cadena, a continuación, hasta la fecha, acaba de obtener los números enteros mediante el desplazamiento y el enmascaramiento, y crear el valor DateTime directamente de los valores enteros:

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 para mejor y más completo que el mío. :) (Aunque admito que prefiero el hexadecimal sobre el decimal para las máscaras de bits.) –

+0

Hermoso ejemplo de cambio de bits y enmascaramiento en C#, bien hecho. Estoy con Greg usando hexadecimal, es más claro y compila lo mismo. Se corrigió el año matemático. – richardtallent

+0

, sin embargo, no resuelve el "año", es decir, el año es incorrecto – Phillis

4

Bienvenido a la comunidad, Phillis. :)

Anton es correcto, sus manipulaciones de cadena van a ser lentas. Debido a que parece que está utilizando el parámetro como un campo de bits, le sugiero que examine los diversos operadores de bits (mucho más rápidos): < <, >>, &, | y ~. Parece que estás tratando de hacer una manipulación binaria, así que utiliza los operadores creados para ello.

E.g. (no probado, justo fuera del manguito):

Comienza con un valor de 0x6c9f7fff. El byte de orden superior constituye el año. Para enmascarar todo lo que no es el año, hacer algo como:

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

Del mismo modo, los próximos 4 bits son el mes, así:

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

voy a sugerir que para encontrar la C/Código C++ que hace un trabajo similar; luego póngalo en C#

Cuestiones relacionadas