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
в это число станет
0
s Если они также являются нулями
value
После этого мы имеем желаемое значение "месяц" в середине битовой последовательности: мы используем правый сдвиг
>> 8
чтобы поместить значение в "фронт" (видимый справа) битовой последовательности, таким образом, десятичное значение является фактическим месяцем.
maxbre
Да, я бы предпочел это, но, к сожалению, именно с этим способом мне приходится работать, потому что это выходные данные, которые сохраняются в базе данных, которую читают как мое приложение, так и другие приложения.
Thomas Daniels
Должна быть возможность изменить логику битовых операций-но я не знаю, в чем смысл "& 0x3F". Возможно, я что-то упускаю, но это выглядит бессмысленно, и удаление этого поможет с возвращающейся логикой. Кроме того, ваш расчет "года" звучит опасно: как насчет лет до 2000? Когда вы вернетесь, как вы будете уверены между 1999 и 2255 годами? (потому что вы бросаете -1 в байт, таким образом, переполняясь, снова получая 255)