Unit ImportTU;

interface

Uses windows, // StrUtils,
  m_api;

type
  PDayTable = ^TDayTable;
  TDayTable = array [1 .. 12] of Word;

const
  MonthDays: array [Boolean] of TDayTable = (
    (31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31),
    (31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31));

function Timestamp(Year, Month, Day, Hour, Min, Sec: Word; toGMT: Boolean = true): LongWord;
{ function TimestampICQ(Year,Month,Day,Hour,Min,Sec:Word):LongWord; }
function DateTimeToTimeStamp(const DateTime: TDateTime; toGMT: Boolean = true): DWord;

{ ***** Authtor of this procedures Alexey Kulakov aka Awkward***** }
function ChangeUnicode(str: PWideChar): PWideChar;
function UTF8Len(src: PAnsiChar): integer;
function WideToANSI(src: PWideChar; var dst: PAnsiChar; cp: DWord = CP_ACP): PAnsiChar;
function ANSIToWide(src: PAnsiChar; var dst: PWideChar; cp: DWord = CP_ACP): PWideChar;
function ANSIToUTF8(src: PAnsiChar; var dst: PAnsiChar; cp: DWord = CP_ACP): PAnsiChar;
function UTF8toANSI(src: PAnsiChar; var dst: PAnsiChar; cp: DWord = CP_ACP): PAnsiChar;
function UTF8toWide(src: PAnsiChar; var dst: PWideChar; len: cardinal = DWord(-1)): PWideChar;
function WidetoUTF8(src: PWideChar; var dst: PAnsiChar): PAnsiChar;
{ ***** }

implementation

uses SysUtils;

function IsLeapYear(Year: Word): Boolean;
begin
  Result := (Year mod 4 = 0) and ((Year mod 100 <> 0) or (Year mod 400 = 0));
end;

function Timestamp(Year, Month, Day, Hour, Min, Sec: Word; toGMT: Boolean = true): LongWord;
var
  i: integer;
  DayTable: PDayTable;
  DT, D: LongWord;
begin
  // fix for 2 digit year
  if Year > 0 then
    if Year < 90 then
      inc(Year, 2000)
    else if Year < 100 then
      inc(Year, 1900);
  //
  DayTable := @MonthDays[IsLeapYear(Year)];
  for i := 1 to Month - 1 do
    inc(Day, DayTable^[i]);
  i := Year - 1;
  D := i * 365 + i div 4 - i div 100 + i div 400 + Day -
    (1969 * 365 + 492 - 19 + 4 + 1);
  DT := (D * 24 * 60 * 60) + (Hour * 3600 + Min * 60 + Sec);
  // �������� � GMT...���� �� ����� ������� ������ ���������� � GMT
  if toGMT then
    Result := DT - (Longword(CallService(MS_DB_TIME_TIMESTAMPTOLOCAL, DT, 0)) - DT)
  else
    Result := DT;
end;

function DateTimeToTimeStamp(const DateTime: TDateTime; toGMT: Boolean = true): DWord;
begin
  Result := Round((DateTime - UnixDateDelta) * SecsPerDay);
  if toGMT then
    Result := Result - (Dword(CallService(MS_DB_TIME_TIMESTAMPTOLOCAL, Result, 0)) - Result);
end;

function ChangeUnicode(str: PWideChar): PWideChar;
var
  i, len: integer;
begin
  Result := str;
  if str = nil then
    exit;
  if (Word(str^) = $FFFE) or (Word(str^) = $FEFF) then
  begin
    len := lstrlenw(str);
    if Word(str^) = $FFFE then
    begin
      i := len - 1;
      while i > 0 do // str^<>#0
      begin
        pword(str)^ := swap(pword(str)^);
        inc(str);
        dec(i);
      end;
      // str:=result;
    end;
    move((Result + 1)^, Result^, len * SizeOf(WideChar));
  end;
end;

function WideToANSI(src: PWideChar; var dst: PAnsiChar; cp: DWord = CP_ACP): PAnsiChar;
var
  len, l: integer;
begin
  if (src = nil) or (src^ = #0) then
  begin
    GetMem(dst, 1);
    dst^ := #0;
  end
  else
  begin
    l := lstrlenw(src);
    len := WideCharToMultiByte(cp, 0, src, l, NIL, 0, NIL, NIL) + 1;
    GetMem(dst, len);
    FillChar(dst^, len, 0);
    WideCharToMultiByte(cp, 0, src, l, dst, len, NIL, NIL);
  end;
  Result := dst;
end;

function ANSIToWide(src: PAnsiChar; var dst: PWideChar; cp: DWord = CP_ACP): PWideChar;
var
  len, l: integer;
begin
  if (src = nil) or (src^ = #0) then
  begin
    GetMem(dst, SizeOf(WideChar));
    dst^ := #0;
  end
  else
  begin
    l := lstrlena(src);
    len := MultiByteToWideChar(cp, 0, src, l, NIL, 0) + 1;
    GetMem(dst, len * SizeOf(WideChar));
    FillChar(dst^, len * SizeOf(WideChar), 0);
    MultiByteToWideChar(cp, 0, src, l, dst, len);
  end;
  Result := dst;
end;

function ANSIToUTF8(src: PAnsiChar; var dst: PAnsiChar; cp: DWord = CP_ACP): PAnsiChar;
var
  tmp: PWideChar;
begin
  ANSIToWide(src, tmp, cp);
  Result := WidetoUTF8(tmp, dst);
  FreeMem(tmp);
end;

function UTF8Len(src: PAnsiChar): integer; // w/o zero
begin
  Result := 0;
  if src <> nil then
  begin
    while src^ <> #0 do
    begin
      if (ord(src^) and $80) = 0 then
      else if (ord(src^) and $E0) = $E0 then
        inc(src, 2)
      else
        inc(src);
      inc(Result);
      inc(src);
    end;
  end;
end;

function CalcUTF8Len(src: PWideChar): integer;
begin
  Result := 0;
  if src <> nil then
  begin
    while src^ <> #0 do
    begin
      if src^ < #$0080 then
      else if src^ < #$0800 then
        inc(Result)
      else
        inc(Result, 2);
      inc(src);
      inc(Result);
    end;
  end;
end;

function UTF8toWide(src: PAnsiChar; var dst: PWideChar; len: cardinal = DWord(-1)): PWideChar;
var
  w: Word;
  p: PWideChar;
begin
  GetMem(dst, (UTF8Len(src) + 1) * SizeOf(WideChar));
  p := dst;
  if src <> nil then
  begin
    while (src^ <> #0) and (len > 0) do
    begin
      if ord(src^) < $80 then
        w := ord(src^)
      else if (ord(src^) and $E0) = $E0 then
      begin
        w := (ord(src^) and $1F) shl 12;
        inc(src);
        dec(len);
        w := w or (((ord(src^)) and $3F) shl 6);
        inc(src);
        dec(len);
        w := w or (ord(src^) and $3F);
      end
      else
      begin
        w := (ord(src^) and $3F) shl 6;
        inc(src);
        dec(len);
        w := w or (ord(src^) and $3F);
      end;
      p^ := WideChar(w);
      inc(p);
      inc(src);
      dec(len);
    end;
  end;
  p^ := #0;
  Result := dst;
end;

function UTF8toANSI(src: PAnsiChar; var dst: PAnsiChar; cp: DWord = CP_ACP): PAnsiChar;
var
  tmp: PWideChar;
begin
  UTF8toWide(src, tmp);
  Result := WideToANSI(tmp, dst, cp);
  FreeMem(tmp);
end;

function WidetoUTF8(src: PWideChar; var dst: PAnsiChar): PAnsiChar;
var
  p: PAnsiChar;
begin
  GetMem(dst, CalcUTF8Len(src) + 1);
  p := dst;
  if src <> nil then
  begin
    while src^ <> #0 do
    begin
      if src^ < #$0080 then
        p^ := AnsiChar(src^)
      else if src^ < #$0800 then
      begin
        p^ := AnsiChar($C0 or (ord(src^) shr 6));
        inc(p);
        p^ := AnsiChar($80 or (ord(src^) and $3F));
      end
      else
      begin
        p^ := AnsiChar($E0 or (ord(src^) shr 12));
        inc(p);
        p^ := AnsiChar($80 or ((ord(src^) shr 6) and $3F));
        inc(p);
        p^ := AnsiChar($80 or (ord(src^) and $3F));
      end;
      inc(p);
      inc(src);
    end;
  end;
  p^ := #0;
  Result := dst;
end;

end.