这个算法是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;

解决方案 »

  1.   

    我想了一种最笨的方法,就是按算法求出每个bit的二进制码组成一个二进制数,然后将二进制数转成INT64.
    问题是我应该如何排序呢?
    到底是:
    bit64~bit39 bit38~bit17 bit16~bit1
    还是:
    bit1~bit16 bit17~bit38 bit39~bit64?
      

  2.   

    没认真看,但是取formatDateTime函数中取分的是nn,不是mm
    Strtoint(formatDateTime('mmddhhnnss',now)); 
      

  3.   

    另外,既然是二进制表示,你这样写肯定是错的。var 
      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; 这样写应该是对的
      

  4.   

    上面有一行写错了:
    atime   :=   atime   +   s   SHL   38; 
      

  5.   

        atime   :=   atime   +   m   SHL   60;
        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
      

  6.   

    改成这样就好了:
    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;
    正在验证是否正确
      

  7.   

    还有,如果要解码,那又应该如何进行位移操作呢?是用shr吗?
      

  8.   

    解码用:
    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;
      

  9.   


    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;