如何将日期和时间打包成 32 位?
How can I pack a Date and Time into 32-bits?
我有一个日期表示,顺序如下,以适合一个 int。日期表示应该是
year : 6 bits
month : 5 bits
day : 5 bits
hours : 4 bits
minutes: 6 bits
seconds: 6 bits
所有日期都应符合 Unit32 date
[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);
上面我尝试了一些按位运算,但结果并不令人满意。我缺少什么或我应该做什么?
例如当前日期是:2021.55.10 13:55:06
二进制转换上面的代码 1010100110101101000110111000011 十六进制表示 54D6 8DC3 表示星期四,1970 年 1 月 1 日 06:01:58 但它应该是今天的日期
谢谢。
你的方案有一些问题:
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 时间的东西? (即简单的纪元以来的秒数)。
Yes there is a reason memory reason which i cant use unix epox time
...因此您需要将该值放入 32 位。这很好,因为您 可以 使用具有 32 位值的 Unix 时间。当然这意味着 you'll run into the Year 2038 problem 但有一些可能的不同解决方案:
- 您可以使用较低的分辨率。
- 例如2 秒或 1 分钟分辨率。
- 您可以使用不同的纪元(基准偏移量)。
- signed 32 位 Unix 时间使用
1970-01-01 00:00:00
,最大日期+时间值为 2038-01-19 03:14:07
。
- 无符号 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'pastable 实现,纪元为 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 );
}
用法:
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 );
给我这个输出:
Now: 10/03/2021 11:26:43 +00:00
As UInt32: 668662003
Decoded from UInt32: 10/03/2021 11:26:43 +00:00
我有一个日期表示,顺序如下,以适合一个 int。日期表示应该是
year : 6 bits
month : 5 bits
day : 5 bits
hours : 4 bits
minutes: 6 bits
seconds: 6 bits
所有日期都应符合 Unit32 date
[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);
上面我尝试了一些按位运算,但结果并不令人满意。我缺少什么或我应该做什么?
例如当前日期是:2021.55.10 13:55:06 二进制转换上面的代码 1010100110101101000110111000011 十六进制表示 54D6 8DC3 表示星期四,1970 年 1 月 1 日 06:01:58 但它应该是今天的日期
谢谢。
你的方案有一些问题:
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 时间的东西? (即简单的纪元以来的秒数)。
Yes there is a reason memory reason which i cant use unix epox time
...因此您需要将该值放入 32 位。这很好,因为您 可以 使用具有 32 位值的 Unix 时间。当然这意味着 you'll run into the Year 2038 problem 但有一些可能的不同解决方案:
- 您可以使用较低的分辨率。
- 例如2 秒或 1 分钟分辨率。
- 您可以使用不同的纪元(基准偏移量)。
- signed 32 位 Unix 时间使用
1970-01-01 00:00:00
,最大日期+时间值为2038-01-19 03:14:07
。 - 无符号 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。
- signed 32 位 Unix 时间使用
所以这是 32 位 Unix 时间的现成复制'n'pastable 实现,纪元为 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 );
}
用法:
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 );
给我这个输出:
Now: 10/03/2021 11:26:43 +00:00
As UInt32: 668662003
Decoded from UInt32: 10/03/2021 11:26:43 +00:00