将uint时间值恢复为datetime对象
我有一个方法可以将日期时间值转换为uint数字,但我想知道是否可以将其转换回日期时间,如果是这样,我该如何做?
这里是将日期时间转换为uint的方法:
Hi, I have a method that converts a datetime value into a uint number but I wonder if its possible to convert it back into a datetime and if so how would I do that?
here is the method that converts the datetime into a 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运算符是如何工作的,但是不知道如何将值恢复到原始形式(分钟,小时,日,月和年)。
What I have tried:
I have looked at how the bitwise OR operator works but dont really understand anyways how to get the values back to its original form (minute, hour, day, month and year).
如果目的是将DateTime存储为数字并稍后重新创建,我不会编写自定义代码来创建uint
,但我会使用long
并使用内置的ToBinary(和FromBinary)方法。
ToBinary [ ^ ]:
If the purpose is to store the DateTime as a number and recreate it later, I would not write custom code to create auint
, but I would use along
and use the built-in ToBinary (and FromBinary) method.
ToBinary[^]:
DateTime dt = ...;
long bin = dt.ToBinary();
FromBinary [ ^ ]:
FromBinary[^]:
long bin = ...;
DateTime dt = DateTime.FromBinary(bin);
正如你所说的,因为数据库你真的需要一个uint,我构建了一些反转序列化算法逻辑的代码。工作原理:序列化算法确保日期(分钟,小时......)的所有部分都位于一系列位中的特定位置,因此解串器提取该系列,将其向右移动,使得小数值是正确的,并把它放在一个新的DateTime对象中。
两个非常重要的事情需要考虑:
1)这只适用于2000年至2255年(包括两者),因为你的'byte year = ...'行。如果这是不希望的,你需要提出一个不同的序列化;我的反序列化代码可以为你提供一些相反的想法。
2)每个日期的秒数都会丢失,因为它没有存储。反序列化代码将其设置为0.
As you said that you really need a uint because of a database, I built some code that reverses the logic of your serialization algorithm. How it works: your serialization algorithm makes sure that all parts of the date (minute, hour, ...) are at a specific location in the series of bits, so the deserializer extracts that series, shifts it to the right so the decimal value is correct, and puts that in a new DateTime object.
Two very important things to consider:
1) This will only work for the years 2000 till 2255 (both included), because of your 'byte year = ...' line. If this is undesired, you need to come up with a different serialization; my deserialization code can give you some ideas for the reverse.
2) The number of seconds in each date is lost because it's not stored. The deserialization code sets it to 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如果它们在值
中也是零。在此之后,我们在比特序列的中间有我们想要的'月'值:我们使用右移>> 8
将值放在位序列的前(从右侧看),因此小数值是实际的月份。
To give a more detailed explanation on what this does, I'll take 'month' as example, but it's the same for the other values.
In the serialized format, the month is stored from the 9th bit (included) till the 13th bit (included) (right-to-left), so 5 bits. This means that the information we want to learn about, can be represented as: 00000000000000000001111100000000
, or 7936
. Because we use the &
operator, those 1
s in that integer will become 0
s if they are also zeroes in value
. After this, we have our desired 'month' value in the middle of the bit sequence: we use the right shift >> 8
to put the value at the 'front' (seen from the right) of the bit sequence, so the decimal value is the actual month.