必要なすべてのデータを 56 バイトに収めるためのスキームのアイデアを次に示します (実際、最大 11 の日付と時刻を 56 バイトに収めることができます)。
このシステムが 1000 年以上続くとは思わないと仮定すると、年の最初の部分を定義できます。つまり、2013 年はエポックと年という 2 つに分割されます。
- エポック: 0 ~ 31 を許可する 5 ビット (または 1 バイト)
- 年: 0 ~ 99 を許可する 7 ビット (または 1 バイト)
- 日: 0 ~ 365 を許可する 9 ビット (2 バイト)
- 時間: 5 ビット (1 バイト) で 0 ~ 24 を許可
- 2 番目: 0 ~ 3600 を許可する 12 ビット (2 バイト)
これで、単純に 7 バイトを使用してそれぞれの値をインクリメントし、最大 8 つの日付と時刻を格納できますが、構造体を作成して個々のビットをビットバンしてさらに圧縮し、40 ビットに詰め込むことができます (または 5 バイト) 11 の日付を許可します。
本当に詰め込みたい場合はエポックを削除することもできますが、上記のスキームでは 3199 までの日付を操作できます。
他のよりコンパクトな方法があると確信しています。つまり、1970 年 1 月 1 日からのミリ秒数は、数年後に数ビット減少する可能性がありますが、コードの寿命は短くなりますが、私は見ていません実際の値。
いくつかのサンプル コード (bool は内部的にはバイト (?!) であるため、BitArray を使用するように更新されていますが、BitArray は実際にはビットです... OPS の場合は非常に重要です。:
OPは、1時間ごとに運転された分の量を保存したいと考えていることに注意する必要がありますが、これにはさらに多くのスペースが必要になります(運転した1時間ごとの記録または日付を示す毎日の開始および停止記録) (結局、停止は開始の後に来る必要があります。) 以下のコードを使用すると、特定の日に何分運転されたかを記録できます。
using System;
using System.Collections;
namespace BitBangingDate
{
class Program
{
static void Main(string[] args)
{
CompactDateManipulator x = new CompactDateManipulator();
Console.WriteLine(x.ToString());
x.Month = 7;
x.Day = 27;
x.Minute = 1234;
Console.WriteLine(x.ToString());
var bitArr = x.GetCompactedArray();
CompactDateManipulator x1 = new CompactDateManipulator();//create new blank date to test whether can be reiitialised from BitArray
x1.ReinitialiseDateFromBitArray(bitArr);
Console.WriteLine(x1.ToString());
}
}
class CompactDateManipulator
{
CompactDate _date = new CompactDate();
public int Month
{
get
{
return BoolArrayToInt(_date.month);
}
set
{
IntToBoolArray(ref _date.month, value);
}
}
public int Day
{
get
{
return BoolArrayToInt(_date.day);
}
set
{
IntToBoolArray(ref _date.day, value);
}
}
public int Minute
{
get
{
return BoolArrayToInt(_date.minute);
}
set
{
IntToBoolArray(ref _date.minute, value);
}
}
public BitArray GetCompactedArray()
{
return _date.GetFullArray();
}
public void ReinitialiseDateFromBitArray(BitArray arr)
{
_date.SetDate(arr);
}
//utility methods
void IntToBoolArray(ref bool[] bits, int input)
{
var len = bits.Length;
for (int i = 0; i < len; i++)
{
bits[i] = (input & 1) == 1 ? true : false;
input >>= 1;
}
}
int BoolArrayToInt(bool[] bits)
{
if (bits.Length > 32) throw new ArgumentException("Can only fit 32 bits in a int");
int r = 0;
for (int i = 0; i < bits.Length; i++)
{
if (bits[i]) r |= 1 << i;
}
return r;
}
public override string ToString()
{
return String.Format("Stored Date mm/dd/ss: {0}/{1}/{2}", Month, Day, Minute);
}
}
class CompactDate
{
//Layout Month(5) Day(9) Minute (12)
// 11111 111111111 111111111111
public bool[] month = new bool[5];
public bool[] day = new bool[9];
public bool[] minute = new bool[12];
public BitArray GetFullArray()
{
int fullLen = month.Length + day.Length + minute.Length;
BitArray full = new BitArray(fullLen);
int index = 0;
for (int i = 0; i < month.Length; i++,index++)
{
full.Set(index,month[i]);
}
for (int i = 0; i < day.Length; i++, index++)
{
full.Set(index, day[i]);
}
for (int i = 0; i < minute.Length; i++, index++)
{
full.Set(index, minute[i]);
}
return full;
}
public void SetDate(BitArray arr)
{
int index = 0;
for (int i = 0; i < month.Length; i++, index++)
{
month[i] = arr.Get(index);
}
for (int i = 0; i < day.Length; i++, index++)
{
day[i] = arr.Get(index);
}
for (int i = 0; i < minute.Length; i++, index++)
{
minute[i] = arr.Get(index);
}
}
}
}