Refactor for Speed: конвертировать в дату - PullRequest
5 голосов
/ 03 февраля 2010

Я работаю на себя, я работающий не по найму программист, и в результате у меня нет такой роскоши, как пересмотр кода или возможность совершенствоваться на основе однорангового программирования.Я собираюсь использовать это как упражнение, чтобы увидеть, может ли сообщество StackOverflow помочь в рассмотрении простого метода, который я написал;

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

Это метод, который принимает числовое представление даты ипреобразует его в тип данных DateTime.Я хотел бы, чтобы метод был пересмотрен для достижения максимально быстрого времени выполнения, потому что он выполняется внутри цикла.

Любые комментарии к методу приветствуются, так как это будет упражнение для меня.Я с нетерпением жду некоторых ответов.

Ответы [ 4 ]

10 голосов
/ 03 февраля 2010

Вместо преобразования в строку, затем в целые числа, затем в строку, затем в дату, просто получите целые числа путем сдвига и маскирования и создайте значение DateTime непосредственно из целочисленных значений:

binDate >>= 15;
int day = binDate & 31;
binDate >>= 5;
int month = binDate & 15;
binDate >>= 8;
int year = binDate + 1900;
return new DateTime(year, month, day);
4 голосов
/ 03 февраля 2010

Добро пожаловать в сообщество, Филлис. :)

Антон прав, ваши струнные манипуляции будут медленными. Поскольку похоже, что вы используете параметр в качестве битового поля, я бы посоветовал изучить различные (гораздо более быстрые) битовые операторы: <<, >>, &, | и ~. Похоже, что вы пытаетесь сделать бинарную манипуляцию, так что используйте операторы, созданные для него.

например. (не проверено, только с манжеты):

Вы начинаете со значения 0x6c9f7fff. Байт старшего разряда составляет год. Чтобы замаскировать все, что не год, сделайте что-то вроде:

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

Аналогично, следующие 4 бита - это месяц, поэтому:

int month = (binDate & 0x00F00000) >> 20;
int date = (binDate & 0x000F8000) >> 15;
return new DateTime(year, month, date);
4 голосов
/ 03 февраля 2010

Вы делаете строковые манипуляции.Это настоящий убийца производительности при использовании в тесных циклах.

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

Вот как вы это делаете.Сначала возьмите 1822490623 и преобразуйте его в двоичный код:

0110 1100 1010 0000 1111 1111 1111 1111

Это маска для года:

f    f    0    0    0    0    0    0 

Это для месяца:

0    0    f    0    0    0    0    0

И это для дня:

0    0    0    f    8    0    0    0

Значение «год» должно быть смещено вправо на 6 * 4 бит, «месяц» - на 5 * 4, а «день» - на 3 * 4 + 3 бит.

0 голосов
/ 03 февраля 2010

Я предлагаю вам найти код C / C ++, который выполняет аналогичную работу; затем перенести его в C #

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...