maxbre Ответов: 1

Восстановить значение времени uint обратно в объект datetime


Привет, у меня есть метод, который преобразует значение datetime в число uint, но мне интересно, можно ли преобразовать его обратно в datetime, и если да, то как бы я это сделал?

вот метод, который преобразует значение типа datetime в виде uint:

public static uint ToUIntTime(this DateTime pValue)
{
    uint minute = (uint)(pValue.Minute << 25);
    uint hour = (uint)((pValue.Hour & 0x3F) << 19);
    uint day = (uint)((pValue.Day & 0x3F) << 13);
    uint month = (uint)((pValue.Month & 0x1F) << 8);
    byte year = (byte)(pValue.Year - 2000);

    uint ret = 0;

    ret = ret | minute;
    ret = ret | hour;
    ret = ret | day;
    ret = ret | month;
    ret = ret | year;

    return ret;
}


Что я уже пробовал:

Я посмотрел, как работает побитовый оператор OR, но на самом деле не понимаю, как вернуть значения в исходную форму (минута, час, день, месяц и год).

1 Ответов

Рейтинг:
4

Thomas Daniels

Если цель состоит в том, чтобы сохранить дату-время в виде числа и воссоздать его позже, я бы не стал писать пользовательский код для создания uint, но я бы использовал long и используйте встроенный метод ToBinary (и FromBinary).

Тобинарий[^]:

DateTime dt = ...;
long bin = dt.ToBinary();

Фромбинария[^]:
long bin = ...;
DateTime dt = DateTime.FromBinary(bin);


[Редактировать]

Поскольку вы сказали, что вам действительно нужен uint из-за базы данных, я построил некоторый код, который меняет логику вашего алгоритма сериализации. Как это работает: ваш алгоритм сериализации гарантирует, что все части даты (минута, час, ...) находятся в определенном месте в серии битов, поэтому десериализатор извлекает эту серию, сдвигает ее вправо, чтобы десятичное значение было правильным, и помещает его в новый объект DateTime.

Нужно учитывать две очень важные вещи:

1) это будет работать только в период с 2000 по 2255 год (оба включены), из-за вашей строки " byte year=...". Если это нежелательно,вам нужно придумать другую сериализацию; мой код десериализации может дать вам некоторые идеи для обратного.
2) количество секунд в каждой дате теряется, потому что она не хранится. Код десериализации устанавливает его в 0.
public static DateTime ToDateTime(this uint value)
{
    int year = (byte)(255 & value) + 2000; // note what I said about this!
    int month = (int)((7936 & value) >> 8);
    int day = (int)((516096 & value) >> 13);
    int hour = (int)((33030144 & value) >> 19);
    int minute = (int)((2113929216 & value) >> 25);

    return new DateTime(year, month, day, hour, minute, 0);
}

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

В сериализованном формате месяц хранится от 9-го бита (включено) до 13-го бита (включено) (справа налево), то есть 5 бит. Это означает, что информация, которую мы хотим узнать, может быть представлена в виде: 00000000000000000001111100000000, или 7936. Потому что мы используем & оператор, те 1в это число станет 0s Если они также являются нулями value После этого мы имеем желаемое значение "месяц" в середине битовой последовательности: мы используем правый сдвиг >> 8 чтобы поместить значение в "фронт" (видимый справа) битовой последовательности, таким образом, десятичное значение является фактическим месяцем.


maxbre

Да, я бы предпочел это, но, к сожалению, именно с этим способом мне приходится работать, потому что это выходные данные, которые сохраняются в базе данных, которую читают как мое приложение, так и другие приложения.

Thomas Daniels

Должна быть возможность изменить логику битовых операций-но я не знаю, в чем смысл "& 0x3F". Возможно, я что-то упускаю, но это выглядит бессмысленно, и удаление этого поможет с возвращающейся логикой. Кроме того, ваш расчет "года" звучит опасно: как насчет лет до 2000? Когда вы вернетесь, как вы будете уверены между 1999 и 2255 годами? (потому что вы бросаете -1 в байт, таким образом, переполняясь, снова получая 255)

Thomas Daniels

Я построил некоторый код десериализации; смотрите мой отредактированный ответ для кода и объяснения.

maxbre

Это потрясающе! Большое вам спасибо, а также за хорошее объяснение, очень ценю его.