C# 如何将日期和时间打包为32位?
为了符合int,我有以下顺序的日期重新植入。日期重新植入应为C# 如何将日期和时间打包为32位?,c#,bitwise-operators,C#,Bitwise Operators,为了符合int,我有以下顺序的日期重新植入。日期重新植入应为 year : 6 bits month : 5 bits day : 5 bits hours : 4 bits minutes: 6 bits seconds: 6 bits 所有日期都应适合Unit32日期 [year(5bits),month(5bits),day(6bits),hours(4bits),minutes(6bits),seconds(6bit)] UInt32 date =
year : 6 bits
month : 5 bits
day : 5 bits
hours : 4 bits
minutes: 6 bits
seconds: 6 bits
所有日期都应适合Unit32日期
[year(5bits),month(5bits),day(6bits),hours(4bits),minutes(6bits),seconds(6bit)]
UInt32 date = 0;
date= date| (UInt32) (DateTime.Now.Year%2000)<< 26;
date= date| ((uint)DateTime.Now.Month << 22);
date= date| (uint)DateTime.Now.Day << 17;
date= date| ((uint)DateTime.Now.Hour << 15);
date= date| ((uint)DateTime.Now.Minute << 6);
date= date| ((uint)DateTime.Now.Second);
string binary = Convert.ToString(date, 2);
[年(5位)、月(5位)、日(6位)、时(4位)、分(6位)、秒(6位)]
UInt32日期=0;
date=date |(UInt32)(DateTime.Now.Year%2000)您的方案存在一些问题:
year : 6 bits - 0 to 63
month : 5 bits - 0 to 31
day : 5 bits - 0 to 31
hours : 4 bits - 0 to 15
minutes: 6 bits - 0 to 63
seconds: 6 bits - 0 to 63
- 主要问题是您的方案仅使用4位表示小时,因此它不能表示下午4点到午夜之间的时间(即16到23小时)
- 其次,您的方案效率低下,因为它浪费比特(一分钟内有
0-59
秒,而不是0-63
)
- …这意味着您的方案可能表示无效值,例如2月31日第15小时第63分钟的第63秒-这不是真实的日期+时间
与其重新发明轮子,为什么不使用Unix时间之类的工具呢?(即从一个纪元开始的秒数)
是的,有一个原因,内存原因,我不能使用unix epox时间
…因此您需要将值拟合到32位。这很好,因为可以使用带有32位值的Unix时间。当然,这意味着有几种可能的不同解决方案:
- 您可以使用较低的分辨率。
- e、 g.2秒或1分钟的分辨率
- 可以使用不同的历元(基准偏移)。
- 已签名32位Unix时间使用最大日期+时间值为
2038-01-19 03:14:07的1970-01-01 00:00:00
- 无符号32位Unix时间的最大值为
2106-02-07 06:28:15
- 如果将
2000-01-01 00:00:00
的历元与无符号32位整数一起使用,则最大值为2136-02-07 14:28:15
- 135整年的范围比您的方案好得多,因为您的方案使用6位作为年份,即0-63,上次我检查时,135大于63
下面是一个32位Unix时间的现成拷贝“n”实现,其纪元为2000-01-01 00:00:00
:
private const Int64 YEAR_2000 = 946713600; // The year where there are no elephants. There is also no unethical treatment of elephants.
private static readonly DateTimeOffset _maxValueForUnsigned32Bits = DateTimeOffset( YEAR_2000 + UInt32.MaxValue ); // 2136-02-07 14:28:15
static UInt32 GetTimeAsUInt32( DateTimeOffset dt )
{
if (dt.Year < 2000 || dt > _maxValueForUnsigned32Bits ) throw new ArgumentOutOfRangeException( paramName: nameof(dt), actualValue: dt, message: "Must be between 2000 and 2136-02-07 14:28:15 inclusive." );
Int64 unixFrom2000_64 = dt.ToUnixTimeSeconds() - YEAR_2000;
// `unixFrom2000_64` *will always fit in 32-bits* due to the year range check above, and subtracting the new epoch.
UInt32 unixFrom2000_32 = (UInt32)unixFrom2000_64;
return unixFrom2000_32;
}
static DateTimeOffset GetTimeFromUInt32( UInt32 value )
{
Int64 asUnixTime = value + YEAR_2000;
return DateTimeOffset.FromUnixTimeSeconds( asUnixTime );
}
给我这个输出:
现在:2021年3月10日11:26:43+00:00
同于UInt32:668662003
从UInt32:10/03/2021 11:26:43+00:00解码
“结果并不令人满意。”这并不是对您遇到的问题的最清晰的描述。您使用的移位常量看起来也不正确(尤其是小时15和17,月22和26),因为您使用的是DateTime。现在,在每一行上,如果时间在计算过程中逐渐变为新的小时/分钟/天,那么您可能会得到一些非常奇怪的数字。您不应该使用DateTime。现在
以相同的方法重复使用-您需要先在变量中存储快照值,这是因为DateTime.Now
可以在调用之间更改(例如,如果您的代码开始于23:59:59.999
但结束于00:00:00.001
。4位代表0到23之间的值?祝您好运!@canton7已修复,谢谢。
DateTimeOffset now = DateTimeOffset.UtcNow; // WARNING: Using `Now` instead of `UtcNow` will include an offset value that will not be persisted.
Console.WriteLine( "Now: {0}", now );
UInt32 myTime = GetTimeAsUInt32( now );
Console.WriteLine( "As UInt32: {0:D}", myTime );
DateTimeOffset decoded = GetTimeFromUInt32( myTime );
Console.WriteLine( "Decoded from UInt32: {0}", decoded );