这个算法是CMPP3.0中产生Msg_Id的算法。
算法如下:
采用64位(8字节)的整数:
(1) 时间(格式为MMDDHHMMSS,即月日时分秒):bit64~bit39,
其中
bit64~bit61:月份的二进制表示;
bit60~bit56:日的二进制表示;
bit55~bit51:小时的二进制表示;
bit50~bit45:分的二进制表示;
bit44~bit39:秒的二进制表示;
(2) 短信网关代码:bit38~bit17,把短信网关的代码转换为整数填写到该字段中。
(3) 序列号:bit16~bit1,顺序增加,步长为1,循环使用。
各部分如不能填满,左补零,右对齐。我的方法如下,但总不对。
function GetInt64(Id:String):int64;
var
atime:int64;
asmc:int64;
aSerial:int64;
begin
aTime:=Strtoint(formatDateTime('mmddhhmmss',now));
aTime:=aTime shl 38;
asmc:=Strtoint(ID);
asmc:=asmc shl 16;
aSerial:=Message_Index;
if Message_Index>=65535 then Message_Index:=0 else Message_Index:=Message_Index+1;
Result:=aTime or asmc or aSerial;
end;
算法如下:
采用64位(8字节)的整数:
(1) 时间(格式为MMDDHHMMSS,即月日时分秒):bit64~bit39,
其中
bit64~bit61:月份的二进制表示;
bit60~bit56:日的二进制表示;
bit55~bit51:小时的二进制表示;
bit50~bit45:分的二进制表示;
bit44~bit39:秒的二进制表示;
(2) 短信网关代码:bit38~bit17,把短信网关的代码转换为整数填写到该字段中。
(3) 序列号:bit16~bit1,顺序增加,步长为1,循环使用。
各部分如不能填满,左补零,右对齐。我的方法如下,但总不对。
function GetInt64(Id:String):int64;
var
atime:int64;
asmc:int64;
aSerial:int64;
begin
aTime:=Strtoint(formatDateTime('mmddhhmmss',now));
aTime:=aTime shl 38;
asmc:=Strtoint(ID);
asmc:=asmc shl 16;
aSerial:=Message_Index;
if Message_Index>=65535 then Message_Index:=0 else Message_Index:=Message_Index+1;
Result:=aTime or asmc or aSerial;
end;
问题是我应该如何排序呢?
到底是:
bit64~bit39 bit38~bit17 bit16~bit1
还是:
bit1~bit16 bit17~bit38 bit39~bit64?
Strtoint(formatDateTime('mmddhhnnss',now));
y,m,d,h,n,s,ms:word;DecodeDateTime(Now,y,m,d,h,n,s,ms);
atime := 0;
atime := atime + m SHL 60;
atime := atime + d SHL 55;
atime := atime + h SHL 50;
atime := atime + n SHL 44;
atime := atime + m SHL 38; asmc:=Strtoint(ID);
asmc:=asmc shl 16;
aSerial:=Message_Index;
if Message_Index> =65535 then Message_Index:=0 else Message_Index:=Message_Index+1;
Result:=aTime or asmc or aSerial; 这样写应该是对的
atime := atime + s SHL 38;
atime := atime + d SHL 55;
atime := atime + h SHL 50;
atime := atime + n SHL 44;
atime := atime + s SHL 38;这部份代码出错了:[DCC Error] Unit4.pas(50): E1012 Constant expression violates subrange bounds
var
y,m,d,h,n,s,ms:Word;
mm,dd,hh,nn,ss:Int64;
atime:int64;
asmc:int64;
aSerial:int64;
begin
DecodeDateTime(Now,y,m,d,h,n,s,ms);
mm := m;
dd := d;
hh := h;
nn := n;
ss := s;
atime := 0;
atime := atime + mm SHL 60;
atime := atime + dd SHL 55;
atime := atime + hh SHL 50;
atime := atime + nn SHL 44;
atime := atime + ss SHL 38; asmc:=Strtoint(ID);
asmc:=asmc shl 16;
aSerial:=Message_Index;
if Message_Index>=65535 then Message_Index:=0 else Message_Index:=Message_Index+1;
Result:=aTime or asmc or aSerial;
正在验证是否正确
procedure DecodeInt64(value:Int64):int64;
type
PInt64Rec = ^Int64Rec;
var
date,code,MsgID,TmpVal:Int64;
PRec:PInt64Rec;
begin PRec := @value;
MsgID := PRec^.Words[0];//MsgID已成功解码出来,date和code就搞不掂了
end;
uses DateUtils;var
iSerialNo: Integer;function Encode(iGatewayCode: Integer; var iSerialNo: Integer): Int64;
var
ATime : TDateTime;
begin
ATime := Now();
Result := MonthOf(ATime);
Result := Result shl 5 + DayOf(ATime);
Result := Result shl 5 + HourOf(ATime);
Result := Result shl 6 + MinuteOf(ATime);
Result := Result shl 6 + SecondOf(ATime);
Result := Result shl 22 + iGatewayCode and $3FFFFF;
Result := Result shl 16 + iSerialNo and $FFFF;
iSerialNo := (iSerialNo + 1) and $FFFF;
end;procedure Dencode(iNumber: Int64; var iMonth, iDay, iHour, iMinute, iSecond, iGatewayCode, iSerialNo: Integer);
begin
iSerialNo := iNumber and $FFFF;
iNumber := iNumber shr 16;
iGatewayCode := iNumber and $3FFFFF;
iNumber := iNumber shr 22;
iSecond := iNumber and $3F;
iNumber := iNumber shr 6;
iMinute := iNumber and $3F;
iNumber := iNumber shr 6;
iHour := iNumber and $1F;
iNumber := iNumber shr 5;
iDay := iNumber and $1F;
iNumber := iNumber shr 5;
iMonth := iNumber;
end;procedure TForm1.FormCreate(Sender: TObject);
begin
iSerialNo := 0;
end;procedure TForm1.Button1Click(Sender: TObject);
var
iNumber : Int64;
iMonth, iDay, iHour, iMinute, iSecond, iGatewayCode, iSerialNo2: Integer;
begin
iNumber := Encode(1234567, iSerialNo);
Label1.Caption := IntToStr(iNumber); Dencode(iNumber, iMonth, iDay, iHour, iMinute, iSecond, iGatewayCode, iSerialNo2);
Label2.Caption := Format('%d-%d, %d:%d:%d, GatewayCode=%d, SerialNo=%d',
[iMonth, iDay, iHour, iMinute, iSecond, iGatewayCode, iSerialNo2]);
end;